What is the best way to emulate Tagged union in databases?
I’m talking about something like this:
create table t1 {
vehicle_id INTEGER NOT NULL REFERENCES car(id) OR motor(id) -- not valid
...
}
where vehicle_id would be id in car table OR motor table, and it would know which.
(assume that motor and car tables have nothing in common0
Some people use a design called Polymorphic Associations to do this, allowing
vehicle_idto contain a value that exists either incarormotortables. Then add avehicle_typethat names the table which the given row int1references.The trouble is that you can’t declare a real SQL foreign key constraint if you do this. There’s no support in SQL for a foreign key that has multiple reference targets. There are other problems, too, but the lack of referential integrity is already a deal-breaker.
A better design is to borrow a concept from OO design of a common supertype of both
carandmotor:Then make
t1reference this super-type table:And also make the sub-types reference their parent supertype. Note that the primary key of the sub-types is not auto-incrementing. The parent supertype takes care of allocating a new id value, and the children only reference that value.
Now you can have true referential integrity, but also support multiple subtype tables with their own attributes.
The answer by @Quassnoi also shows a method to enforce disjoint subtypes. That is, you want to prevent both
carandmotorfrom referencing the same row in their parent supertype table. When I do this, I use a single-column primary key forIdentifiable.idbut also declare aUNIQUEkey overIdentifiable.(id, type). The foreign keys incarandmotorcan reference the two-column unique key instead of the primary key.