Frage

Angenommen, Sie waren eine Datenbank einrichten Crashtestdaten verschiedenen Fahrzeuge zu speichern. Sie wollen für Schnellboote, Autos Daten von Crash-Tests speichern und Go-Karts.

könnten Sie erstellen drei separate Tabellen: SpeedboatTests, CarTests und GokartTests. Aber viele Ihrer Spalten werden die gleichen in jeder Tabelle sein (zum Beispiel der Mitarbeiter-ID der Person, die den Test durchgeführt, um die Richtung der Kollision (vorne, seitlich, hinten), etc.). Allerdings werden viele Spalten unterschiedlich sein, so dass man einfach nicht alle Testdaten in einer einzigen Tabelle setzen wollen, weil Sie schon einige Spalten werden, die immer für speedboats null sein wird, ganz wenige, die immer sein null für Autos, und nicht wenige, die für go-Karts immer null sein wird.

Angenommen, Sie wollen auch einige Informationen speichern, die nicht direkt an den Tests (wie die Mitarbeiter-ID des Designers der Sache getestet) verwandt ist. Diese Spalten nicht richtig erscheinen in einem „Test“ Tisch legen überhaupt, vor allem, weil sie für alle Tests auf demselben Fahrzeug wiederholt werden werden.

Lassen Sie mich eine mögliche Anordnung von Tabellen veranschaulichen, so können Sie die Fragen sehen beteiligt.

Speedboats
id | col_about_speedboats_but_not_tests1 | col_about_speedboats_but_not_tests2

Cars
id | col_about_cars_but_not_tests1 | col_about_cars_but_not_tests2

Gokarts
id | col_about_gokarts_but_not_tests1 | col_about_gokarts_but_not_tests2

Tests
id | type | id_in_type | col_about_all_tests1 | col_about_all_tests2
(id_in_type will refer to the id column of one of the next three tables,
depending on the value of type)

SpeedboatTests
id | speedboat_id | col_about_speedboat_tests1 | col_about_speedboat_tests2

CarTests
id | car_id | col_about_car_tests1 | col_about_car_tests2

GokartTests
id | gokart_id | col_about_gokart_tests1 | col_about_gokart_tests2

Was ist gut / schlecht über diese Struktur und was die bevorzugte Art und Weise so etwas wie dies umzusetzen sei?

Was ist, wenn es auch einige Informationen, die für alle Fahrzeuge gilt, die Sie in einem Fahrzeug Tisch haben lieber? Würde die CarTests Tabelle dann so etwas wie ... aussieht

id | vehicle_id | ...

With a Vehicles table like this:
id | type | id_in_type
(with id_in_type pointing to the id of either a speedboat, car, or go-kart)

Dies ist immer nur eine königliche Chaos zu sein scheint. Wie sollte so etwas wie dies einrichten?

War es hilfreich?

Lösung

Das type und id_in_type Design Polymorphe Verbände genannt. Dieser Entwurf bricht Regeln der Normalisierung in mehrfacher Hinsicht. Wenn nichts anderes, soll es eine rote Fahne, die Sie nicht deklariert einen echten Fremdschlüssel, weil die id_in_type irgendeine von mehreren Tabellen verweisen kann.

Hier ist eine bessere Möglichkeit, Ihre Tabellen zu definieren:

  • Erstellen Sie eine abstrakte Tabelle Vehicles einen abstrakten Bezugspunkt für alle Fahrzeug-Untertypen und Fahrzeugtests zur Verfügung zu stellen.
  • Jedes Fahrzeug-Untertyp hat einen Primärschlüssel, die nicht Autoinkrement der Fall ist, sondern verweist Vehicles.
  • Jeder Test-Untertyp hat einen Primärschlüssel, die nicht Autoinkrement der Fall ist, sondern verweist Tests.
  • Jeder Test-Untertyp hat auch einen Fremdschlüssel mit dem entsprechenden Fahrzeug-Untertyp.

Hier Probe DDL:

CREATE TABLE Vehicles (
 vehicle_id INT AUTO_INCREMENT PRIMARY KEY
);

CREATE TABLE Speedboats (
 vehicle_id INT PRIMARY KEY,
 col_about_speedboats_but_not_tests1 INT,
 col_about_speedboats_but_not_tests2 INT,
 FOREIGN KEY(vehicle_id) REFERENCES Vehicles(vehicle_id)
);

CREATE TABLE Cars (
 vehicle_id INT PRIMARY KEY,
 col_about_cars_but_not_tests1 INT,
 col_about_cars_but_not_tests2 INT,
 FOREIGN KEY(vehicle_id) REFERENCES Vehicles(vehicle_id)
);

CREATE TABLE Gokarts (
 vehicle_id INT PRIMARY KEY,
 col_about_gokarts_but_not_tests1 INT,
 col_about_gokarts_but_not_tests2 INT,
 FOREIGN KEY(vehicle_id) REFERENCES Vehicles(vehicle_id)
);

CREATE TABLE Tests (
 test_id INT AUTO_INCREMENT PRIMARY KEY,
 col_about_all_tests1 INT,
 col_about_all_tests2 INT
);

CREATE TABLE SpeedboatTests (
 test_id INT PRIMARY KEY,
 vehicle_id INT NOT NULL,
 col_about_speedboat_tests1 INT,
 col_about_speedboat_tests2 INT,
 FOREIGN KEY(test_id) REFERENCES Tests(test_id),
 FOREIGN KEY(vehicle_id) REFERENCES Speedboats(vehicle_id)
);

CREATE TABLE CarTests (
 test_id INT PRIMARY KEY,
 vehicle_id INT NOT NULL,
 col_about_car_tests1 INT,
 col_about_car_tests2 INT,
 FOREIGN KEY(test_id) REFERENCES Tests(test_id),
 FOREIGN KEY(vehicle_id) REFERENCES Cars(vehicle_id)
);

CREATE TABLE GokartTests (
 test_id INT PRIMARY KEY,
 vehicle_id INT NOT NULL,
 col_about_gokart_tests1 INT,
 col_about_gokart_tests2 INT,
 FOREIGN KEY(test_id) REFERENCES Tests(test_id),
 FOREIGN KEY(vehicle_id) REFERENCES Gokarts(vehicle_id)
);

Sie könnten alternativ Tests.vehicle_id erklären die Vehicles.vehicle_id Referenzen und Untertyp Tabelle des vehicle_id Fremdschlüssels in jedem Test loszuwerden, aber das würde erlauben Anomalien, wie ein Schnellboot Test, der eine Gokart von id verweist.

Andere Tipps

Für Mapping Vererbungshierarchien auf Datenbanktabellen, ich glaube, Martin Fowler die Alternativen ziemlich gut in seinem Buch Patterns of Enterprise Application Architecture legt.

http://martinfowler.com/eaaCatalog/singleTableInheritance.html

http://martinfowler.com/eaaCatalog/classTableInheritance.html

http://martinfowler.com/eaaCatalog/concreteTableInheritance.html

Wenn die Anzahl der zusätzlichen Felder / Spalten für Subklassen klein ist, dann einzelne Tabelle Vererbung ist in der Regel die einfachste zu behandeln.

Wenn Sie PostgreSQL für Ihre Datenbank verwenden und Sie sind bereit, sich auf eine Datenbank-spezifische Funktion zu binden, es unterstützt Tabelle Vererbung direkt:

http://www.postgresql.org/docs/8.3/ static / DDL-inherit.html

Ich würde es brechen in verschiedene Tabellen nach oben, zum Beispiel Fahrzeug (ID, Typ usw.) VehicleAttributes () VehicleID, AttributeID, Wert), CrashTestInfo (VehicleID, CrashtestID, Datum etc.) CrashtestAttributes (CrashTestID, AttributeID, Wert)

oder eher als Attribut, getrennte Tabellen für jeden Satz von ähnlichem Detail, die aufgezeichnet werden sollen.

Wenn Sie mit SQLAlchemy , ein objektrelationalen Mapper für Python, können Sie konfigurieren, wie Vererbungshierarchien auf Datenbanktabellen abgebildet werden . Object-Relational-Mapper ist gut für die Zähmung sonst mühsame SQL.

Ihr Problem könnte eine gute Passform für die vertikalen Tabellen sein. Statt alles in dem Schema des Speicherns, das Typen des Objekts speichert und Primärschlüssel in einer Tabelle und Schlüssel / Wert-Tupel für jedes Objekt in einer anderen Tabelle. Wenn Sie wirklich Auto-Tests wurden speichern, würde dieses Setup macht es viel einfacher, neue Arten von Ergebnissen hinzuzufügen.

Führen Sie eine Google-Suche auf "gen-spec relationale Modellierung". Sie finden Artikel auf, wie Tabellen einrichten, die die Attribute der generali Einheit speichern (was OO Programmierer könnte die übergeordnete Klasse nennen), getrennte Tabellen für jede der spezialisierten Einheiten (Unterklassen), und wie Fremdschlüssel zu verwenden, um es zu verlinken alle zusammen.

Die besten Artikel, IMO, diskutieren in Bezug auf die ER-Modellierung gen-spec. Wenn Sie wissen, wie ein ER-Modell in ein relationales Modell übersetzen und von dort nach SQL-Tabellen, werden Sie wissen, was zu tun ist, wenn sie Ihnen zeigen, wie Gen-spec in IHM modellieren.

Wenn Sie einfach mal googlen auf „gen-spec“, das meiste, was Sie Objekt sehen werden orientiert ist, nicht orientiert relational. Das Zeug kann nützlich sein, als auch, solange Sie wissen, wie die objektrelationale Impedance Mismatch zu überwinden.

Ihr Design ist sinnvoll und wird im Anschluss an die richtigen Normalisierungsregeln. Sie könnten eine Fahrzeug Tabelle mit einem Fahrzeug-ID und Typ (dh die „Eltern“ für Schnellboote, Autos und Gokarts ... wo man Sachen wie „DesignedByUserId“ halten würde) fehlen. Zwischen der Fahrzeugtabelle und der Speedboats Tabelle ist ein Eins - zu -. Eine Beziehung, und zwischen Fahrzeug und Speedboat / Autos / GoKarts gibt es eine 1-und-nur-1-Beziehung (dh ein Fahrzeug nur 1 Datensatz für Schnellboot haben kann, Autos oder go-Karts) ... obwohl die meisten DBs für das nicht einen einfachen Durchsetzungsmechanismus bieten.

Eine Normalisierungsregel, die diese Art von Dingen hilft zu identifizieren ist, dass ein Feld nur auf dem Primärschlüssel der Tabelle abhängen. In einem konsolidierten Tisch, an dem Schnellboot, Autos und Gokart Testergebnisse zusammen gelagert werden dann die Autos verwandten Bereiche hängen nicht nur von dem Prüftermin, sondern auch auf dem vechicle ID und Fahrzeugtyp. Der Primärschlüssel für die Testergebnisse Tabelle ist Prüftermin + Fahrzeug-ID und Fahrzeugtyp ist nicht das, was die Testdatenreihe einzigartig macht (dh ist es trotzdem einen Test auf 01/01/200912 durchzuführen:. 30pm auf einem bestimmten Fahrzeug dass sowohl ein Schnellboot und Auto ... nee ... kann nicht durchgeführt werden).

Ich erkläre nicht die Normalisierungsregel particularily gut ... aber 3. / 4. / 5. Normalformen Regeln immer verwirrt mich, wenn ich die formale Beschreibungen lesen. Einer von denen, (3. / 4. / 5.) befasst sich mit den Feldern auf dem Primärschlüssel abhängig und nur den Primärschlüssel. Die Regel davon ausgehen, dass der Primärschlüssel korrekt identifiziert (falsch defininh der Primärschlüssel viel zu einfach ist zu tun).

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top