同一个 table 中的多对多关系?

Many to many relationship in the same table?

我是设计数据库的新手,我想知道在同一 table 中的行之间实现多对多关系的规范方法是什么。

在我的例子中,我有一个 table 的公式,我想说 table 中的两个公式是相关的:

公式table:

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

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

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 具有相同的值。我敢肯定,由于我自己的经验不足,我还没有看到其他潜在的问题。

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

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).)

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;