This question already has an answer here:
- Can a foreign key be NULL and/or duplicate? 10 answers
In our database project we have a table Sale
that has an primary key and two exclusive foreign keys: Vehicle_ID
and Piece_ID
. For example if we sell a vehicle we need Vehicle_ID
as a foreign key but not Piece_ID
. Can we put NULL to Piece_ID
, could a foreign key be null? Or is there a way to do this job?
Thanks.
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 shouldn't complain if you have a null foreign key.
Were you running across some errors?
The column (or columns) of a primary key must be NOT NULL. A record cannot be uniquely identified by a NULL. So the ID columns on the referenced end of the foreign key must be defined as NOT NULL.
However, it is a legitimate design decision for a foreign key relationship to be optional, and the way to represent that is by making the referencing end of the key optional, i.e. allowing NULLs.
In data modelling terms what you have described is an (exclusive) arc: "a table ... with two or more foreign keys where one and only one of them can be non-null." In logical modelling arcs are perfectly acceptable, but there is a strong body of opinion in favour of implementing them as separate tables. In your scenario that would be a generic
Sale
table plus two sub-type tables,VehicleSale
andPieceSale
.The advantages of the separate table implementation are:
However, the advantages aren't all one-way. While it is pretty easy to ensure that a
Sale
applies either to aVehicleSale
or aPieceSale
but not both, enforcing a rule that aSale
must have a child record actually gets pretty gnarly.So, the prevailing advice is that an exclusive arc is mistaken, and it is generally good advice. But it's not as clear as some make out.
Answer:
Yes, you can do that - make the FKs themselves NULL-able, but add a CHECK to ensure exactly one of them contains a non-NULL value.
Elaboration:
A FK can be NULL-able, which models a 1..0:N relationship. In other words, a "child" row can (but is not required to) have a "parent" row.
A NOT NULL foreign key models a 1:N relationship. In other words, every child must have a parent.
When a FK is composite1, and at least one of its fields is NULL-able, a mix of NULL and non-NULL values is handled in a special way:
Most DBMSes default to MATCH SIMPLE (with the notable exception of MS Access) and most don't support anything but the default.
1 Which you don't have here - just mentioning it for completeness.