Reputation: 15404
I have a table which contains a list of components associated with a device.
dev_comps
=========
dev_id comp_type comp_id
------ --------- -------
1 A 1234
1 A 1237
1 A 1238
1 B 5678
1 C 1234
2 A 1235
(yes I can have multiples of each kind of component on the device, otherwise I'd just attach them to the device table instead of having a junction table)
I also have several table for the types of components (which of course all have a little bit different options each other).
comp_a
======
comp_a_id color style
--------- ----- -----
1234 red glass
1235 blue wood
comp_c
======
comp_c_id style length
--------- ----- ------
1234 glass 5
1235 wood 7
Is it possible to set up an integrity constrain between dev_comps.comp_id
and comp_a.comp_a_id
; and dev_comps.comp_id
and comp_c.comp_c_id
; etc.?
In general I don't want my app/users to be able to create an entry in dev_comps
where I don't have a matching comp_id
in the corresponding comp_*
table.
Or, is there a better way to do this?
Edit
I've come to the conclusion that what I'm really doing here is Column Overloading. Which as I recall from my old Intro to DBs course is generally considered a poor design. Is there a clean way out of this?
Upvotes: 0
Views: 69
Reputation: 231721
No, you can't have a foreign key constraint that refers to one of two possible parent tables. There are two common approaches to this sort of issue:
You can combine all the comp_*
tables into a single table, adding in a comp_type
column. Presumably, this would mean that many attributes would be NULL for every row since each type of component only has a small number of the available attributes. You can add constraints that ensure that the appropriate set of columns are NULL
or NOT NULL
depending on the comp_type
but you'll waste a bit of space. On the other hand, storing NULL
values, particularly at the end of the row, is pretty cheap.
You can create a master_component
table that just has the comp_id
and comp_type
. The various comp_*
tables could have foreign keys that point to that table (though you'd want comp_type
to be added at least as a virtual column). And dev_comps
could point at the master_component
table.
Of course, there are other options depending on the specifics of the problem. If there are a large number of components with lots of different attributes, such that combining tables would produce a master_component
table with hundreds of columns, it may make more sense to have a single master_component
table with a component_attribute
table that stores attributes as rows rather than as columns. But that's more of a specialized case not something I'd start with.
Upvotes: 2