I'd treat these as three separate attributes, not a heirarchy exactly.
I'd create additional tables that provides a map between a given
manufacturer, material, and color. That way you can track what you need
to display in the second and third drop-down once the user has chosen
the first one.
And the mapping table has a compound primary key over the three fields,
to which the three fields in the user's order reference using a foreign
key relationship.
Since the offerings inevitably change over time, you'll also need
another field in the mapping table to mark certain combinations as
"discontinued" and use that to exclude them from being shown in
drop-down menus, while still allowing them to stay in the database so
that past customer orders can maintain their referential integrity.
Regards,
Bill K.
You might want to get a copy of TREES & HIERARCHIES IN SQL, tho, for
future use.
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.
Wouldn't the vehicle type be deriveable directly from VIN?
I believe that decoding VIN would give not only typr designator (SUV versus
SEDAN) but also body style (2,3,4 or 5 doors).
Kan M. Nelken
Yes, in this case. I prefer to say verifiable from the VIN. A key
needs validation and verification.
'MaterialStructure' which consists of ParentMaterialID (PK)(FK),
ChildMaterialID (PK)(FK), and StructureName - This would include
Mouldings, Mats, Frames, Prints, etc.
'Material' which consists of MaterialID, MaterialConsistsOfID, and
MaterialName - This would include Metal, Wood, Plastic, Glass, etc.
'MaterialConsistsOf' which consists of MaterialConsistsOfID, Component
- This would define what a specific material consists of. For example,
'Material' wood is further classified by 'MaterialConsistsOf' pine.
'Material' glass, could be further classified by 'MaterialConsistsOf'
tempered, leaded, etc.
Again, if you think of this as a recipe model, you'll see the logic.
I'm still refining the model but I think you can see where I'm coming
from.
Food:
Food_ID
Food_Desc
Food_Structure
Parent_Food_ID
Child_Food_ID
Child_Food_Qty_Used
This set of relationships can answer the following questions:
- What is used in the making of a food element?
- What quantity is used to make another food element?
- What food elements does another comprise?
- What quantity of a food element is used in another?
It's the same idea I'm using for my scenario with the addition of the
'MaterialConsistsOf' table.