我对设计数据库比较陌生,我想知道在同一个表中实现行之间多对多关系的规范方法是什么。
在我的情况下,我有一个公式表,我想说表中的两个公式是相关的:
公式表:
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具有相同值的问题。我确信还有其他潜在的问题,由于我自己的经验不足,我没有看到。
有人能指出我正确的方向吗?
答案 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)
);
(我还假设您的关系是对称的,因此i
与A[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;
)