dbTalk Databases Forums  

"or"-relation between 3 tables?

comp.databases comp.databases


Discuss "or"-relation between 3 tables? in the comp.databases forum.



Reply
 
Thread Tools Display Modes
  #1  
Old   
Boris
 
Posts: n/a

Default "or"-relation between 3 tables? - 07-07-2004 , 10:59 AM






I try to normalize a database which has three tables like this (pk should be
the primary key, data just a data column and fk a foreign key):

table 1: pk, data, fk
table 2: pk, data
table 3: pk, data

When a new dataset is inserted into table 1 fk should point to pk in table 2
or table 3. Of course the database has to remember somehow if a dataset in
table 1 is linked to a dataset in table 2 or table 3. So there is no static
link between table 1, table 2 and table 3 but it really depends on the
datasets. I wonder how to do this right in regard of normalization?

Thanks for any help,
Boris



Reply With Quote
  #2  
Old   
Kristian Damm Jensen
 
Posts: n/a

Default Re: "or"-relation between 3 tables? - 07-08-2004 , 02:02 AM






"Boris" <boris (AT) gtemail (DOT) net> wrote

Quote:
I try to normalize a database which has three tables like this (pk should be
the primary key, data just a data column and fk a foreign key):

table 1: pk, data, fk
table 2: pk, data
table 3: pk, data

When a new dataset is inserted into table 1 fk should point to pk in table 2
or table 3. Of course the database has to remember somehow if a dataset in
table 1 is linked to a dataset in table 2 or table 3. So there is no static
link between table 1, table 2 and table 3 but it really depends on the
datasets. I wonder how to do this right in regard of normalization?
Sound to me like you are trying to implement subtypes.

The usual way to do this is having the subtype reference the
supertype, not the other way around, like you are doing. i.e.

table 1: pk, data
table 2: pk, data, fk(referencing table 1)
table 3: pk, data, fk(referencing table 1)

In addition it may be useful to add an attribute to table 1 telling
which subtype we are handling.

Regards,
Kristian


Reply With Quote
  #3  
Old   
Tony
 
Posts: n/a

Default Re: "or"-relation between 3 tables? - 07-08-2004 , 07:48 AM



"Boris" <boris (AT) gtemail (DOT) net> wrote

Quote:
I try to normalize a database which has three tables like this (pk should be
the primary key, data just a data column and fk a foreign key):

table 1: pk, data, fk
table 2: pk, data
table 3: pk, data

When a new dataset is inserted into table 1 fk should point to pk in table 2
or table 3. Of course the database has to remember somehow if a dataset in
table 1 is linked to a dataset in table 2 or table 3. So there is no static
link between table 1, table 2 and table 3 but it really depends on the
datasets. I wonder how to do this right in regard of normalization?
Foreign keys can't "fork" to 2 different parents, so you need 2 fk
columns:

table1: pk, data, fk_to_table2, fk_to_table3

All you need now is a check constraint to ensure that it always has
one or the other, not both (if that is the rule):

alter table table1 add constraint chk1 check ((fk_to_table2 is not
null and fk_to_table3 is null) or (fk_to_table2 is null and
fk_to_table3 is not null));

Of course, this is only 1 way to do it. Another would be to split
table1 into 2 tables, one for the data associated with table2 and
another for the data associated with table3.


Reply With Quote
  #4  
Old   
--CELKO--
 
Posts: n/a

Default Re: "or"-relation between 3 tables? - 07-11-2004 , 01:44 PM



The classic scenario calls for a root class with all the common
attributes and then specialized sub-classes under it. As an example,
let's take the class of Vehicles and find an industry standard
identifier (VIN), and add two mutually exclusive sub-classes, Sport
utility vehicles and sedans ('SUV', 'SED').

CREATE TABLE Vehicles
(vin CHAR(17) NOT NULL PRIMARY KEY,
vehicle_type CHAR(3) NOT NULL
CHECK(vehicle_type IN ('SUV', 'SED')),
UNIQUE (vin, vehicle_type),
..);

Notice the overlapping candidate keys. I then use a compound candidate
key (vin, vehicle_type) and a constraint in each sub-class table to
assure that the vehicle_type is locked and agrees with the Vehicles
table. Add some DRI actions and you are done:

CREATE TABLE SUV
(vin CHAR(17) NOT NULL PRIMARY KEY,
vehicle_type CHAR(3) DEFAULT 'SUV' NOT NULL
CHECK(vehicle_type = 'SUV'),
UNIQUE (vin, vehicle_type),
FOREIGN KEY (vin, vehicle_type)
REFERENCES Vehicles(vin, vehicle_type)
ON UPDATE CASCADE
ON DELETE CASCADE,
..);

CREATE TABLE Sedans
(vin CHAR(17) NOT NULL PRIMARY KEY,
vehicle_type CHAR(3) DEFAULT 'SED' NOT NULL
CHECK(vehicle_type = 'SED'),
UNIQUE (vin, vehicle_type),
FOREIGN KEY (vin, vehicle_type)
REFERENCES Vehicles(vin, vehicle_type)
ON UPDATE CASCADE
ON DELETE CASCADE,
..);

I can continue to build a hierarchy like this. For example, if I had
a Sedans table that broke down into two-door and four-door sedans, I
could a schema like this:

CREATE TABLE Sedans
(vin CHAR(17) NOT NULL PRIMARY KEY,
vehicle_type CHAR(3) DEFAULT 'SED' NOT NULL
CHECK(vehicle_type IN ('2DR', '4DR', 'SED')),
UNIQUE (vin, vehicle_type),
FOREIGN KEY (vin, vehicle_type)
REFERENCES Vehicles(vin, vehicle_type)
ON UPDATE CASCADE
ON DELETE CASCADE,
..);

CREATE TABLE TwoDoor
(vin CHAR(17) NOT NULL PRIMARY KEY,
vehicle_type CHAR(3) DEFAULT '2DR' NOT NULL
CHECK(vehicle_type = '2DR'),
UNIQUE (vin, vehicle_type),
FOREIGN KEY (vin, vehicle_type)
REFERENCES Sedans(vin, vehicle_type)
ON UPDATE CASCADE
ON DELETE CASCADE,
..);

CREATE TABLE FourDoor
(vin CHAR(17) NOT NULL PRIMARY KEY,
vehicle_type CHAR(3) DEFAULT '4DR' NOT NULL
CHECK(vehicle_type = '4DR'),
UNIQUE (vin, vehicle_type),
FOREIGN KEY (vin, vehicle_type)
REFERENCES Sedans (vin, vehicle_type)
ON UPDATE CASCADE
ON DELETE CASCADE,
..);

The idea is to build a chain of identifiers and types in a UNIQUE()
constraint that go up the tree when you use a REFERENCES constraint.
Obviously, you can do variants of this trick to get different class
structures.

If an entity doesn't have to be exclusively one subtype, you play with
the root of the class hierarchy:

CREATE TABLE Vehicles
(vin CHAR(17) NOT NULL,
vehicle_type CHAR(3) NOT NULL
CHECK(vehicle_type IN ('SUV', 'SED')),
PRIMARY KEY (vin, vehicle_type),
..);

Now start hiding all this stuff in VIEWs immediately and add an
INSTEAD OF trigger to those VIEWs.

Reply With Quote
Reply




Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off



Powered by vBulletin Version 3.5.3
Copyright ©2000 - 2012, Jelsoft Enterprises Ltd.