同桌中的多对多关系?

时间:2015-08-19 01:36:34

标签: database postgresql database-design many-to-many

我对设计数据库比较陌生,我想知道在同一个表中实现行之间多对多关系的规范方法是什么。

在我的情况下,我有一个公式表,我想说表中的两个公式是相关的:

公式表:

formula_id SERIAL PRIMARY KEY
name TEXT NOT NULL
formula TEXT NOT NULL

我假设我会创建一个名为related_formulas的新表,然后执行以下操作:

formula_relation_id SERIAL PRIMARY KEY
formula_id INT REFERENCES formulas (formula_id) ON DELETE CASCADE
formula_id2 INT REFERENCES formulas (formula_id) ON DELETE CASCADE

然后我预见到诸如防止同一行中的两个id具有相同值的问题。我确信还有其他潜在的问题,由于我自己的经验不足,我没有看到。

有人能指出我正确的方向吗?

2 个答案:

答案 0 :(得分:2)

SERIAL我假设PostgreSQL ......

CREATE TABLE formula_relation (
  formula_relation_id SERIAL PRIMARY KEY,
  formula1_id INT REFERENCES formulas (formula_id) ON DELETE CASCADE,
  formula2_id INT REFERENCES formulas (formula_id) ON DELETE CASCADE,
  CHECK (formula1_id < formula2_id)
);

SQLFiddle

(我还假设您的关系是对称的,因此iA[i]相关也意味着A[i]i相关;因此,formula1_id < formula2_id确保行只能有一个规范的变体,而且你不需要检查反向配对。如果关系不对称,你应该只CHECK (formula1_id != formula2_id)。)

答案 1 :(得分:0)

Amadan 的回答很好,可以确保以一种规范的方式插入数据,但是如果您不想在插入公式时将数据库用户限制为特定顺序(这是由 CHECK (formula1_id < formula2_id) 在 Amadan 的回答中强加的) ,你可以考虑:

CREATE TABLE formula (
    id int PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY,
    formula_name text NOT NULL,
    formula text NOT NULL
);

CREATE TABLE formula_formula_relation (
    id int PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY,
    formula1_id int NOT NULL REFERENCES formula ON DELETE CASCADE,
    formula2_id int NOT NULL REFERENCES formula ON DELETE CASCADE,
    CHECK (formula1_id <> formula2_id),
    CONSTRAINT already_related_formulas_not_allowed_again EXCLUDE USING gist (
        LEAST    (formula1_id, formula2_id) WITH =,
        GREATEST (formula1_id, formula2_id) WITH =
    )
);

(您可能需要运行 CREATE EXTENSION btree_gist;