Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
Home
Discussion Groups
Database Servers
DB2InformixIngresMS SQLOraclePervasive.SQLPostgreSQLProgressSybase
Desktop Databases
FileMakerFoxProMS AccessParadox
General
General DB TopicsDatabase Theory
Related Topics
Java Development.NET DevelopmentVB DevelopmentMore Topics ...

Database Forum / General DB Topics / DB Theory / September 2008

Tip: Looking for answers? Try searching our database.

primary key as subtype discriminator

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
philiptaylor51@yahoo.com - 31 Aug 2008 17:51 GMT
Hello,

I have something like:

TABLE A
a PK

TABLE B
b PK

TABLE AB (many-to-many table)
a, b PK

TABLE AB-1 (AB subtype)
a, b PK

TABLE AB-2 (AB subtype)
a, b PK

Can I use the attribute "a" (part of PK) as subtype discriminator?

Thanks,
philip
jefftyzzer - 03 Sep 2008 01:37 GMT
On Aug 31, 9:51 am, philiptaylo...@yahoo.com wrote:
> Hello,
>
[quoted text clipped - 19 lines]
> Thanks,
> philip

Hi, Philip.

I think that's a bad idea. I know this may sound a bit shop-worn, but
all subtypes should be mutually exclusive and exhaustive. Further,
they should each describe a semantically unique "kind of" the
supertype, with each subtype described by attributes unique to it.

Taking these two guidelines together, this suggests (to me, anyway)
that if all subtypes are known, then all instances of the domain of
any category discriminator of these subtypes are also to be known.

Inspecting the value of the PK to decide which subtype to navigate to
also smacks of "smart" keys, which gets us to the whole natural key
vs. smart key vs. surrogate key holy war. Besides, if the PK is, say,
a 4-byte unsigned integer, are you saying you'd have (in order to
satisfy the "exhaustive" property) 4,294,967,296 subtypes?

Now, if you wanted to add a category discriminator to your AB
supertype and make it part of a three part composite key, that's
possible, assuming you're enforcing a business rule that mandates that
you may only have one instance of each subtype.

Perhaps you can elaborate a bit more on what you're after, and we can
humbly suggest better approaches?

Regards,

--Jeff
philiptaylor51@yahoo.com - 04 Sep 2008 14:12 GMT
> I think that's a bad idea. I know this may sound a bit shop-worn, but

Hi Jeff, thanks for your answer. I think that's a bad idea too, but
for different reasons. In my opinion the compound PK in the subtypes
becomes "redundant". You always know the value of part of the PK given
a subtype. I see this like a normalization error.

> all subtypes should be mutually exclusive and exhaustive. Further,

You can use a role entity to relax the mutual exclusivity requirement.

> they should each describe a semantically unique "kind of" the
> supertype, with each subtype described by attributes unique to it.

> vs. smart key vs. surrogate key holy war. Besides, if the PK is, say,
> a 4-byte unsigned integer, are you saying you'd have (in order to
> satisfy the "exhaustive" property) 4,294,967,296 subtypes?

What if, for instance, PK BETWEEN 1 AND 5? You are considering the
whole 4-byte unsigned integer domain without constraints. Moreover I
could use a natural key as category discriminator.
jefftyzzer - 05 Sep 2008 18:08 GMT
On Sep 4, 6:12 am, philiptaylo...@yahoo.com wrote:

> > I think that's a bad idea. I know this may sound a bit shop-worn, but
>
[quoted text clipped - 16 lines]
> whole 4-byte unsigned integer domain without constraints. Moreover I
> could use a natural key as category discriminator.

You're right, using a 1:M role is a great way getting around the
mutual-exclusivity requirement (assuming that's what the business
rules dictate). Your point in re: the integer is also well-taken: I
should have said "up to 4,294,967,296 subtypes," but regardless, it
was still a bit of an exaggeration.

Regards,

--Jeff
-CELKO- - 03 Sep 2008 12:46 GMT
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.
philiptaylor51@yahoo.com - 04 Sep 2008 01:58 GMT
[cut]

> CREATE TABLE Vehicles
> (vin CHAR(17) NOT NULL PRIMARY KEY,
[quoted text clipped - 7 lines]
> assure that the vehicle_type is locked and agrees with the Vehicles
> table. Add some DRI actions and you are done:

[cut]

Thanks for your answer. I'm not sure about this implementation of a
generalization structure. The problem is the UNIQUE constraint and not
only because it's redundant.

> 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')),

Here a Vehicle can be just a Sedan even if 2 subtypes are present (two-
door and four-door). This violates the "exhaustive" rule.

>  UNIQUE (vin, vehicle_type),
>  FOREIGN KEY (vin, vehicle_type)
>   REFERENCES Vehicles(vin, vehicle_type)

If 'vehicle_type' is 2DR or 4DR, then you can't reference the Vehicles
table - CHECK(vehicle_type IN ('SUV', 'SED')). If you change it into
CHECK(vehicle_type IN ('SUV', 'SED', '2DR', '4DR')) then 2DR and 4DR
are both subtypes of Vehicles and not of Sedans. Otherwise you are
using a category discriminator to provide the domain for more than a
generalization structure.

>   ON UPDATE CASCADE
>   ON DELETE CASCADE,
>  ..);

[cut]
-CELKO- - 04 Sep 2008 21:56 GMT
>> Here a Vehicle can be just a Sedan even if 2 subtypes are present (two- door and four-door). This violates the "exhaustive" rule. <<

You can add a constraint to assure that only "leaf nodes" have more
than one row in their table. The constraint can be a CREATE ASSERTION
if your product has it, a trigger (ugh!) or a constraint on a locking
column of the form " lock CHAR(1) DEFAULT 'X' NOT NULL UNIQUE CHECK
(lock = 'X'), ".  The bad news is that the last one is true for an
empty table as well as a single row table.
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.