具有复合主键约束的多对多关系

Many-to-many relationship with compound primary key constraint

我收到了在 DBMS 中进行多对多关系设计的要求,但有其他限制。

有两个table,t1t2,其中t1.idt2.id分别是主键。 t1t2 是多对多的关系,所以一个自然的设计是添加第三个 table t3 外键。例如,

t3:
id
t1_id     (foreign key refereed to t1.id)
t2_id     (foreign key refereed to t2.id)

另一个要求pair(t1.id, t2.id) 应该与t4.id 具有一对一 关系。用primary_key(t1.id, t2.id)t5好不好?或者我们可以直接使用 t3's t1_id, t2_id 作为复合主键?我们需要快速扫描 pair(t1.id, t2.id)t4 中是否有实体,即 pair(t1.id, t2.id)t4.id.

是否存在一对一关系

如果你能给我一些提示,我将不胜感激。

如果您必须在 (t1.id,t2.id)t4.id 之间强制执行一对一关系,这似乎表明 (t1.id,t2.id) 是唯一的。

如果是这样,如果 (t1.id,t2.id)t3 中应该是唯一的,那么您可以将 PRIMARY KEY 设为 t3 .

您可以添加对 t4 的外键引用,并使其唯一,这样 t3 中不超过一行可以关联到 t4。或者,您可以使外键引用以另一种方式进行,并将 t3 的主键值存储在 t4.

例如将t3中的外键变为t4

 CREATE TABLE t3
 ( t1_id  INT NOT NULL       COMMENT 'pk, fk ref t1'
 , t2_id  INT NOT NULL       COMMENT 'pk, fk ref t2'
 , t4_id  INT                COMMENT 'fk ref t4'
 , PRIMARY KEY (t1_id,t2_id)
 , CONSTRAINT t3_ux2 UNIQUE KEY (t4_id)
 , CONSTRAINT fk_t3_t1 FOREIGN KEY (t1_id) REFERENCES t1(id)
     ON DELETE CASCADE ON UPDATE CASCADE
 , CONSTRAINT fk_t3_t2 FOREIGN KEY (t2_id) REFERENCES t2(id)
     ON DELETE CASCADE ON UPDATE CASCADE
 , CONSTRAINT fk_t3_t4 FOREIGN KEY (t4_id) REFERENCES t4(id)
     ON DELETE RESTRICT ON UPDATE CASCADE
 ) ...

或者,您可以在 t3 上引入代理主键。 (我们通常只在有其他 table 具有指向 t3 的外键引用时才这样做;因为现在 t3 正在执行更像是一个实际的实体,而不是纯粹的关系。这避免了我们必须使用复合键作为另一个 table 中的外键来引用 t3.

例如:

 CREATE TABLE t3
 ( id     INT NOT NULL       COMMENT 'pk'
 , t1_id  INT NOT NULL       COMMENT 'fk ref t1'
 , t2_id  INT NOT NULL       COMMENT 'fk ref t2'
 , PRIMARY KEY (t3_id)
 , CONSTRAINT t3_ux1 UNIQUE KEY (t1_id,t2_id)
 , CONSTRAINT fk_t3_t1 FOREIGN KEY (t1_id) REFERENCES t1(id) 
     ON DELETE CASCADE ON UPDATE CASCADE
 , CONSTRAINT fk_t3_t2 FOREIGN KEY (t2_id) REFERENCES t2(id) 
     ON DELETE CASCADE ON UPDATE CASCADE
 ) ...

您可以在此 table t3 中添加外键以引用 t4,如上例所示。

或者您可以实现从 t4 到引用 t3.

的关系

两种方法都行。

我的决定主要基于

1) 避免将复合键作为外键(如果没有实体 table 具有复合键)

2) 我们是否想要或需要 ON DELETE CASCADE 功能,以及它需要以何种方式工作...从 t3 删除应该级联删除到 t4,反之亦然。

我在给 t3 添加 t4_id fk 列的示例中展示了 ON DELETE RESTRICT。我认为从 t4 中删除可能不应该 "break" t1t2[=70= 之间的关系] 通过从 t3.

中删除行