在我们的数据库项目中,我们有一个表Sale
,它有一个主键和两个独占外键: Vehicle_ID
和Piece_ID
. 例如,如果我们出售一辆车,我们需要Vehicle_ID
外键但不需要Piece_ID
。我们可以将 NULL 放入Piece_ID
,外键可以为空吗?或者有没有办法完成这项工作?
谢谢。
在我们的数据库项目中,我们有一个表Sale
,它有一个主键和两个独占外键: Vehicle_ID
和Piece_ID
. 例如,如果我们出售一辆车,我们需要Vehicle_ID
外键但不需要Piece_ID
。我们可以将 NULL 放入Piece_ID
,外键可以为空吗?或者有没有办法完成这项工作?
谢谢。
主键的列(或列)必须为 NOT NULL。一条记录不能由 NULL 唯一标识。因此,外键引用端的 ID 列必须定义为 NOT NULL。
然而,外键关系是可选的,这是一个合理的设计决策,表示它的方式是使键的引用端是可选的,即允许 NULL。
在数据建模术语中,您所描述的是一个(排他的)弧:“一个表......具有两个或多个外键,其中一个且只有一个可以是非空的。” 在逻辑建模中,弧线是完全可以接受的,但有强烈的意见支持将它们作为单独的表来实现。在您的场景中,这将是一个通用Sale
表加上两个子类型表,VehicleSale
并且PieceSale
.
分表实现的优点是:
然而,优势并非都是单向的。虽然很容易确保 aSale
适用于 aVehicleSale
或 aPieceSale
但不能同时适用于两者,但强制执行 aSale
必须有子记录的规则实际上变得非常棘手。
因此,普遍的建议是排他弧是错误的,这通常是好的建议。但这并不像有些人说的那么清楚。
是的,您可以这样做 - 使 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你在这里没有 - 只是为了完整性而提及它。
Depending on what you mean by "exclusive foreign keys", you might be thinking of vehicles and pieces as two subclasses of some larger superclass, call it saleable items.
If you use a design pattern called "class table inheritance", you will have three tables, one for the superclass, and one for each subclass table. If in addition, you use a design called "shared primary key", you can use the same primary key for all three tables.
This would enable your Sale table to have a single foreign key, Saleable_Item_Id, that references the Saleable_Item table and also either the Vehicle or the Piece table, depending on the case. This could work out better for you than the existing design.
google "class table inheritance" and "shared primary key" for more details.
如果您有一个空外键,Oracle 不应该抱怨。
您是否遇到了一些错误?