在我们的数据库项目中,我们有一个表Sale
,它有一个主键和两个独占外键:Vehicle_ID
和Piece_ID
。例如,如果我们销售车辆,我们需要Vehicle_ID
作为外键,而不是Piece_ID
。我们可以将NULL放到Piece_ID
,外键是否可以为空?或者有办法做这个工作吗?
感谢。
答案 0 :(得分:11)
主键的列(或列)必须为NOT NULL。无法通过NULL唯一标识记录。因此,外键引用末尾的ID列必须定义为NOT NULL。
但是,外键关系是可选的合法设计决策,表示方式的方法是使键的引用结束是可选的,即允许NULL。
在数据建模术语中,你所描述的是一个(独占)弧:“一个表......有两个或多个外键,其中一个且只有一个非空。”在逻辑建模中,弧是完全可以接受的,但是有一大堆意见支持将它们作为单独的表来实现。在您的方案中,这将是一个通用Sale
表加上两个子类型表,VehicleSale
和PieceSale
。
单独的表实现的优点是:
然而,优势并非都是单向的。虽然很容易确保Sale
适用于VehicleSale
或PieceSale
但不适用于两者,但要强制执行Sale
必须1}的规则em>有一个儿童记录实际上变得非常粗糙。
所以,流行的建议是,专属弧是错误的,这通常是好建议。但它并不像有些人那样明确。
答案 1 :(得分:6)
是的,你可以这样做 - 让FK本身为NULL,但添加一个CHECK以确保其中一个包含非NULL值。
FK可以为NULL,它可以模拟1..0:N关系。换句话说,“子”行可以(但不是必须)具有“父”行。
NOT NULL外键模拟1:N关系。换句话说,每个孩子必须拥有父母。
当FK是复合 1 ,并且其至少一个字段为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不应该抱怨。
您是否遇到过一些错误?