外键可以为空吗?

时间:2012-12-24 14:49:31

标签: sql oracle database-design foreign-keys data-integrity

在我们的数据库项目中,我们有一个表Sale,它有一个主键和两个独占外键:Vehicle_IDPiece_ID。例如,如果我们销售车辆,我们需要Vehicle_ID作为外键,而不是Piece_ID。我们可以将NULL放到Piece_ID,外键是否可以为空?或者有办法做这个工作吗?

感谢。

4 个答案:

答案 0 :(得分:11)

主键的列(或列)必须为NOT NULL。无法通过NULL唯一标识记录。因此,外键引用末尾的ID列必须定义为NOT NULL。

但是,外键关系是可选的合法设计决策,表示方式的方法是使键的引用结束是可选的,即允许NULL。

在数据建模术语中,你所描述的是一个(独占)弧:“一个表......有两个或多个外键,其中一个且只有一个非空。”在逻辑建模中,弧是完全可以接受的,但是有一大堆意见支持将它们作为单独的表来实现。在您的方案中,这将是一个通用Sale表加上两个子类型表,VehicleSalePieceSale

单独的表实现的优点是:

  • 更容易执行外键约束;
  • 更容易添加与(例如)车辆销售相关的其他不适用于单件销售的列;
  • 更容易使用其他子类型扩展模型;
  • 更清晰的数据模型,可以简化应用程序开发。

然而,优势并非都是单向的。虽然很容易确保Sale适用于VehicleSalePieceSale但不适用于两者,但要强制执行Sale 必须有一个儿童记录实际上变得非常粗糙。

所以,流行的建议是,专属弧是错误的,这通常是好建议。但它并不像有些人那样明确。

答案 1 :(得分:6)

答案:

是的,你可以这样做 - 让FK本身为NULL,但添加一个CHECK以确保其中一个包含非NULL值。

精化:

FK可以为NULL,它可以模拟1..0:N关系。换句话说,“子”行可以(但不是必须)具有“父”行。

NOT NULL外键模拟1:N关系。换句话说,每个孩子必须拥有父母。

当FK是复合 1 ,并且其至少一个字段为NULL时,以特殊方式处理NULL和非NULL值的混合:

  • 如果FK为MATCH FULL,则所有值必须为NULL或所有值必须为非NULL且与某些父行匹配。
  • 如果FK是MATCH PARTIAL,则只有那些非NULL的值必须与某个父行匹配(忽略NULL)。
  • 如果FK是MATCH SIMPLE,则所有值都是非NULL且必须与某个父行匹配,或者至少有一个NULL值(在这种情况下,非NULL不需要匹配)。

大多数DBMS默认为MATCH SIMPLE(除MS Access之外的明显例外),大多数DBMS默认不支持任何内容。


1 你没有这里 - 只是提到完整性。

答案 2 :(得分:1)

根据“独占外键”的含义,您可能会将车辆和碎片视为某个较大超类的两个子类,称之为可销售物品。

如果使用名为“类表继承”的设计模式,则将有三个表,一个用于超类,另一个用于每个子类表。此外,如果使用名为“共享主键”的设计,则可以对所有三个表使用相同的主键。

这将使您的Sale表具有一个外键,Saleable_Item_Id,它引用Saleable_Item表以及Vehicle或Piece表,具体取决于具体情况。这可能比现有设计更适合您。

google“class table inheritance”和“shared primary key”了解更多详情。

答案 3 :(得分:0)

如果你有一个空的外键,Oracle不应该抱怨。

您是否遇到过一些错误?