SQL / DB设计:将多列外键与混合NULL / NOT NULL视为必需或可选?

时间:2010-11-23 23:32:45

标签: sql database-design foreign-keys

在DB design / SQL中理论上可以声明类似的东西:

CREATE TABLE Groups
(
  round_id    INTEGER  NOT NULL,
  ordinal_nbr SMALLINT NOT NULL,
  PRIMARY KEY (round_id, ordinal_nbr),
  FOREIGN KEY (round_id) REFERENCES Rounds (id) /* irrelevant, just a reference to another table's ID */
)

CREATE TABLE Games
(
  id               INTEGER  NOT NULL IDENTITY,
  round_id         INTEGER  NOT NULL,          /* !!! */
  ordinal_nbr      SMALLINT NULL,              /* !!! */
  scheduled_tipoff DATETIME NOT NULL,
  PRIMARY KEY (id),
  FOREIGN KEY (round_id, ordinal_nbr) REFERENCES Groups (round_id, ordinal_nbr) /* multi-column FK round_id NOT NULL, ordinal_nbr NULL */

现在的问题是:

由于必须考虑这是一个编程错误,为这些场景调整的最佳方法是什么:将此类FK视为强制性或将其视为可选项?

这里的逻辑政策是什么?

5 个答案:

答案 0 :(得分:1)

当我考虑它时,考虑整个FK似乎更有意义。一旦缺少一条信息,无论是否有意,整个FK都取决于其值尚未设置的列。

毕竟,NULL破坏了义务。对我而言,这比其他方式更有意义。

答案 1 :(得分:0)

我认为没有一般的答案。在现有数据中,games.ordinal_nbr中是否有空值?可能存在希望能够在其中放置null的代码,因此您检查了使用该表的所有代码。更有趣的是,不同的数据库以不同的方式处理它。有些人认为“null = null”是真的,而其他人认为任何比较运算符都是假的,如果两边都是null,即使两者都是。

答案 2 :(得分:0)

为什么它必须是一个错误?

考虑一个Adults表和一个引用它的Offspring表。

(之前未说明)编辑:

如果有后代你确实知道父母的话怎么办?只要忽略它们的存在。

编辑:

这是我刚刚遇到的一个真实例子:

我的数据库基于非规范化的源,我无法控制数据。应逻辑上要求引用所有者表的密钥。运行查询我遇到了一个所有者名称:

'UNKOWN OWNER'

嗯,这可能会漂浮很长一段时间,这只是我抓住它的机会。我对所有者表运行聚合查询,这样的事情会给我不正确的结果。该数据库的设计者通过用自己的null品牌隐藏它来处理null的“巨大复杂性”。

如果值为空或null,则会立即引发错误,我可以在设计开头更改表。此外,在聚合查询中,空值不属于连接,因此您没有不正确的结果。当我想要它们时,我只是left join表。

答案 3 :(得分:0)

SQL中可以为空的外键有很多缺点。从语义建模的角度来看,它不太可能有意义。例如,假设null ordinal_nbr的预期含义是该属性未知。在这种情况下,即使没有与round_id的已知值匹配的行,SQL也可能不会评估其他属性并且不会返回错误(YMMV取决于DBMS和其他选项)。

我建议你重新设计它,以便消除所有可以为空的外键。

答案 4 :(得分:0)

在“组”表中创建一个字段作为主键并加入...

你这里有一场行政噩梦。

NULL<>NULL !!!!!

如果X是未知且Y是未知,你能说X = Y吗? 根据您的DB \ Configuration,Join甚至可能会失败..在我的选项中,任何数据库允许NUll=NULL返回True的事实都是错误的。