Reputation: 55584
I've got one table containing some sort of items
, and two tables (a
and b
) to which these items belong to.
One item refers to either one row in a
or one row in b
. One a
or b
can have multiple items.
Is there a better design than the following (using Oracle 10)?
Any pitfalls to watch out for?
id a_id(fk) b_id(fk)
1 1 NULL
2 1 NULL
3 NULL 1
4 2 NULL
Upvotes: 3
Views: 181
Reputation: 9044
refer to Mapping Inheritance Structures, there are 4 techniques mentioned there,
and see "2.6 Comparing The Strategies" for pros & cons.
Upvotes: 0
Reputation: 81990
I'd suggest to a add a check constraint that enforces at least (or possible exactly) one of the id fields being null.
Also a view and/or function based index for the value nvl(a_id, b_id) might be useful. With Oracle11 you could use a virtual column.
Upvotes: 2
Reputation: 9208
That's a pretty good design on a number of counts:
The only snag is that this database structure by itself doesn't check that an item is linked to only one of A or B (and not both). Check constraints on the Items table will do this job.
Pseudo-code example:
CONSTRAINT a_eor_b CHECK
(
NOT (a_id IS NULL AND b_id IS NULL)
AND NOT (a_id IS NOT NULL AND b_id IS NOT NULL)
)
Upvotes: 4
Reputation: 425623
A
and B
are disjoint subtypes of a more general type.
Let's call it refs
:
CREATE TABLE refs (type CHAR(1) NOT NULL, id INT NOT NULL, PRIMARY KEY (type, id), CHECK (type IN ('A', 'B')))
CREATE TABLE a (type CHAR(1) NOT NULL, id INT NOT NULL PRIMARY KEY, FOREIGN KEY (type, id) REFERENCES refs (type, id) ON DELETE CASCADE, CHECK (type = 'A'))
CREATE TABLE b (type CHAR(1) NOT NULL, id INT NOT NULL PRIMARY KEY, FOREIGN KEY (type, id) REFERENCES refs (type, id) ON DELETE CASCADE, CHECK (type = 'B'))
CREATE TABLE items (id INT NOT NULL, type CHAR(1) NOT NULL, ref INT NOT NULL, FOREIGN KEY (type, id) REFERENCES refs)
With this design, you should never delete from A
or B
directly: delete from the parent table refs
instead.
Upvotes: 0