【问题标题】:Deciding FK between tables which have one to one relation在具有一对一关系的表之间确定 FK
【发布时间】:2013-12-01 19:25:44
【问题描述】:

我是 DB 设计的新手,很抱歉这个菜鸟问题。我有 2 个简单的表,它们之间有 1 对 1 的关系。哪个表的 PK 在其他表中应该是 FK ?我该如何决定?

【问题讨论】:

  • 这种关系是真的1 :: 1吗? (即表 A 中的每一行都会在表 B 中具有相关行 - 反之亦然?)还是1::0..1 关系? (即 B 中的每一行在 A 中都有相关的行,但 A 中的行可能不会(全部)在 B 中具有一行)
  • @ypercube 这是真正的一对一关系。

标签: database database-design foreign-keys primary-key one-to-one


【解决方案1】:

为了确定这一点,要问的问题是这种关系是否是真实的1 :: 1

如果关系是1 :: 0..1(即,B 中的每一行在 A 中都有相关的行,但 A 中的行可能不是(全部)在 B 中有一行),那么应该有一个 FOREIGN KEY in表B (pk)REFERENCES A (pk)。这是最常见的情况,几乎可以在所有 DBMS 中轻松实现。

如果关系是真实的1 :: 1(即表 A 中的每一行在表 B 中都有一个相关行 - 反之亦然),那么应该有两个外键,一个从 B 到 A,另一个从 A朝向 B。这也很容易声明,但要使其真正发挥作用并不是那么简单。

问题源于先有鸡还是先有蛋的问题:我应该先在哪个表中插入一行?如果我们先插入 A,外键(朝向 B)将禁止插入。如果我们先插入 B,那么外键(朝向 A)这次将禁止插入。

为了完成这项工作,2 个插入语句必须在一个事务中 - 并且外键必须定义为 DEFERRABLE - 即在事务结束时检查。因此,如果您在 SQL-Server(或 MySQL)中工作,您根本无法做到这一点。如果您在 Postgres 或 Oracle 或任何其他已实现可延迟约束的 DBMS 中,这是可以实现的。

【讨论】:

  • 感谢您的回答。
【解决方案2】:

哪个表的PK应该是其他表的FK?

两者兼而有之。对于 true “1 对 1”,您需要循环外键(这也意味着您需要延迟外键来在插入新数据时打破“鸡和蛋”问题,这不是所有 DBMS 都支持)。

或者只是将两个表合并为一个表(在大多数情况下建议这样做)。


但是,我怀疑您说的不是真正的“1 到 1”,而是“1 到 0 或 1”,在这种情况下,“0 或 1”端点应该包含外键,例如:

CREATE TABLE ONE (
    ID INT PRIMARY KEY
);

CREATE TABLE ZERO_OR_ONE (
    ID INT PRIMARY KEY REFERENCES ONE (ID)
);

【讨论】:

  • 我说的是真正的一对一,而不是 1 对 0 或 1。
  • @Tartar 然后将它们合并到一个表中,除非您有specific reasons 不这样做。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-06
  • 1970-01-01
  • 2018-03-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多