Chevrolet stellt keinen Mustang her. Ford hat 1960 keinen Mustang hergestellt. Ihre Struktur wird eine Menge Unsinn zulassen.
Das Problem besteht nicht darin, dass jede Spalte ein Fremdschlüssel ist; daran ist nicht unbedingt etwas auszusetzen. Das Problem ist, dass die Fremdschlüssel falsch sind.
Ich habe das in eine Tabelle der Marken (Ford, Chevrolet, BMW usw.) und Modelle (Impala, Camaro, F-150 usw.) und Jahre (1920, ... 2012) und Motoren (327, 350 usw.) aufgeteilt.
Und genau deshalb sind sie falsch. Wenn Sie eine Beziehung normalisieren, müssen Sie Start mit der Beziehung, ermitteln die Schlüsselkandidaten und arbeiten die funktionalen Abhängigkeiten aus. Einfach nur einspaltige "Nachschlagetabellen" für jede Spalte zu erstellen, ist keine Normalisierung und schränkt Ihre Daten nicht in der erforderlichen Weise ein. (Und in diesem speziellen Fall sind die Beschränkungen das fehlende Element, nicht die Normalisierung auf 5NF).
Make Model Yr Engine
--
Ford F-150 2012 3.7L V6
Ford F-150 2012 3.5L V6 EcoBoost
Ford F-150 2012 5.0L V8
Ford F-150 2012 6.2L V8
Ford F-150 2011 3.7L V6
Ford F-150 2011 3.5L V6 EcoBoost
Ford F-150 2011 5.0L V8
Ford F-150 2011 6.2L V8
Chevrolet Camaro 2012 3.6L V6
Chevrolet Camaro 2011 3.6L V6
Chevrolet Camaro 2011 6.2L V8
Chevrolet Camaro 1980 229ci V6
Chevrolet Camaro 1980 267ci V8
Chevrolet Camaro 1980 305ci V8
Cadillac CTS 2004 3.6L V6
Vauxhall Astra 1979 1.3L
Vauxhall Astra 1979 1.6L
Vauxhall Astra 1979 1.8L
Opel Astra 1979 1.5L
Opel Astra 1979 2.0L
Es sollte klar sein, dass der einzige mögliche Schlüssel {Marke, Modell, Baujahr, Motor} ist. Diese Tabelle ist also ein reiner Schlüssel und hat keine Attribute, die keine Primzahlen sind.
Um "Lookup"-Tabellen als Datenbeschränkungen hinzuzufügen, reicht es nicht aus, zu sagen, dass man in der ersten Spalte aus {Ford, Chevrolet, Cadillac, Vauxhall, Opel} und in der zweiten Spalte aus {F-150, Camaro, CTS, Astra} wählen muss. Die rechte "Lookup"-Tabelle für Marke und Modell enthält sowohl Marke als auch Modell; Sie wählen aus {Ford F-150, Chevrolet Camaro, Cadillac CTS, Vauxhall Astra, Opel Astra}. (In diesem Fall geht es sogar noch weiter, siehe die Tabelle model_years unten).
create table makes (
make varchar(25) primary key
);
insert into makes values
('Ford'),
('Chevrolet'),
('Cadillac'),
('Vauxhall'),
('Opel');
create table models (
make varchar(25) not null references makes (make),
model varchar(25) not null,
primary key (make, model)
);
insert into models values
('Ford', 'F-150'),
('Chevrolet', 'Camaro'),
('Cadillac', 'CTS'),
('Vauxhall', 'Astra'),
('Opel', 'Astra');
create table model_years (
make varchar(25) not null,
model varchar(25) not null,
year integer not null check (year between 1900 and 2050),
primary key (make, model, year),
foreign key (make, model) references models (make, model)
);
insert into model_years values
('Ford', 'F-150', 2012),
('Ford', 'F-150', 2011),
('Chevrolet', 'Camaro', 2012),
('Chevrolet', 'Camaro', 2011),
('Chevrolet', 'Camaro', 1980),
('Cadillac', 'CTS', 2004),
('Vauxhall', 'Astra', 1979),
('Opel', 'Astra', 1979);
create table model_year_engines (
make varchar(25) not null,
model varchar(25) not null,
year integer not null,
engine varchar(25) not null,
primary key (make, model, year, engine),
foreign key (make, model, year) references model_years (make, model, year)
);
insert into model_year_engines values
('Ford', 'F-150', 2012, '3.7L V6'),
('Ford', 'F-150', 2012, '3.5L V6 EcoBoost'),
('Ford', 'F-150', 2012, '5.0L V8'),
('Ford', 'F-150', 2012, '6.2L V8'),
('Ford', 'F-150', 2011, '3.7L V6'),
('Ford', 'F-150', 2011, '3.5L V6 EcoBoost'),
('Ford', 'F-150', 2011, '5.0L V8'),
('Ford', 'F-150', 2011, '6.2L V8'),
('Chevrolet', 'Camaro', 2012, '3.6L V6'),
('Chevrolet', 'Camaro', 2011, '3.6L V6'),
('Chevrolet', 'Camaro', 2011, '6.2L V8'),
('Chevrolet', 'Camaro', 1980, '229ci V6'),
('Chevrolet', 'Camaro', 1980, '267ci V8'),
('Chevrolet', 'Camaro', 1980, '305ci V8'),
('Cadillac', 'CTS', 2004, '3.6L V6'),
('Vauxhall', 'Astra', 1979, '1.3L'),
('Vauxhall', 'Astra', 1979, '1.6L'),
('Vauxhall', 'Astra', 1979, '1.8L'),
('Opel', 'Astra', 1979, '1.5L'),
('Opel', 'Astra', 1979, '2.0L');
Kein Motor kann in diese Tabelle aufgenommen werden, wenn seine Zeile nicht zuerst in model_years vorhanden ist. Kein Jahr kann in model_years aufgenommen werden, wenn die entsprechende Zeile nicht zuerst in models vorhanden ist. Und keine Zeile kann in "models" aufgenommen werden, wenn die Zeile nicht zuerst in "makes" vorhanden ist.
Sie können ein gutes Argument für die Verwendung von ON UPDATE CASCADE
in einem Schema wie diesem. Es gibt auch gute Argumente dafür, sie nicht zu verwenden. Oracle unterstützt nicht ON UPDATE CASCADE
Das ist ein Grund, warum man in Oracle-Tabellen ID-Nummern sieht und warum man manchmal sagt: "Primärschlüsselwerte müssen niemals ändern."
Dies sind die Arten von Tabellen, die Sie benötigen, um Ihre bekannten Anforderungen umzusetzen.