@ Bill Karwin beschreibt drei Vererbungsmodelle in seinem Buch SQL Antipatterns , wenn er Lösungen für das Antipattern SQL Entity-Attribute-Value vorschlägt. Dies ist eine kurze Übersicht:
Vererbung einzelner Tabellen (auch Vererbung von Tabellen pro Hierarchie genannt):
Die Verwendung einer einzelnen Tabelle wie in Ihrer ersten Option ist wahrscheinlich das einfachste Design. Wie Sie bereits erwähnt haben, müssen viele subtypspezifische Attribute NULL
in Zeilen, in denen diese Attribute nicht zutreffen , mit einem Wert versehen werden. Mit diesem Modell hätten Sie eine Richtlinientabelle, die ungefähr so aussehen würde:
+------+---------------------+----------+----------------+------------------+
| id | date_issued | type | vehicle_reg_no | property_address |
+------+---------------------+----------+----------------+------------------+
| 1 | 2010-08-20 12:00:00 | MOTOR | 01-A-04004 | NULL |
| 2 | 2010-08-20 13:00:00 | MOTOR | 02-B-01010 | NULL |
| 3 | 2010-08-20 14:00:00 | PROPERTY | NULL | Oxford Street |
| 4 | 2010-08-20 15:00:00 | MOTOR | 03-C-02020 | NULL |
+------+---------------------+----------+----------------+------------------+
\------ COMMON FIELDS -------/ \----- SUBTYPE SPECIFIC FIELDS -----/
Das Design einfach zu halten ist ein Plus, aber die Hauptprobleme bei diesem Ansatz sind die folgenden:
Wenn Sie neue Untertypen hinzufügen möchten, müssen Sie die Tabelle ändern, um die Attribute zu berücksichtigen, die diese neuen Objekte beschreiben. Dies kann schnell problematisch werden, wenn Sie viele Untertypen haben oder wenn Sie regelmäßig Untertypen hinzufügen möchten.
Die Datenbank kann nicht erzwingen, welche Attribute zutreffen und welche nicht, da keine Metadaten vorhanden sind, um zu definieren, welche Attribute zu welchen Untertypen gehören.
Sie können auch keine NOT NULL
Attribute eines Subtyps erzwingen , die obligatorisch sein sollten. Sie müssten dies in Ihrer Anwendung behandeln, was im Allgemeinen nicht ideal ist.
Vererbung von Betontabellen:
Ein anderer Ansatz zur Bekämpfung der Vererbung besteht darin, für jeden Subtyp eine neue Tabelle zu erstellen und alle gemeinsamen Attribute in jeder Tabelle zu wiederholen. Beispielsweise:
--// Table: policies_motor
+------+---------------------+----------------+
| id | date_issued | vehicle_reg_no |
+------+---------------------+----------------+
| 1 | 2010-08-20 12:00:00 | 01-A-04004 |
| 2 | 2010-08-20 13:00:00 | 02-B-01010 |
| 3 | 2010-08-20 15:00:00 | 03-C-02020 |
+------+---------------------+----------------+
--// Table: policies_property
+------+---------------------+------------------+
| id | date_issued | property_address |
+------+---------------------+------------------+
| 1 | 2010-08-20 14:00:00 | Oxford Street |
+------+---------------------+------------------+
Dieses Design löst im Wesentlichen die Probleme, die für die Einzeltabellenmethode identifiziert wurden:
Obligatorische Attribute können jetzt mit erzwungen werden NOT NULL
.
Das Hinzufügen eines neuen Untertyps erfordert das Hinzufügen einer neuen Tabelle, anstatt einer vorhandenen Spalte Spalten hinzuzufügen.
Es besteht auch kein Risiko, dass ein unangemessenes Attribut für einen bestimmten Subtyp festgelegt wird, z. B. das vehicle_reg_no
Feld für eine Eigenschaftsrichtlinie.
Das type
Attribut ist nicht wie bei der Einzeltabellenmethode erforderlich . Der Typ wird jetzt durch die Metadaten definiert: den Tabellennamen.
Dieses Modell hat jedoch auch einige Nachteile:
Die allgemeinen Attribute werden mit den subtypspezifischen Attributen gemischt, und es gibt keine einfache Möglichkeit, sie zu identifizieren. Die Datenbank wird es auch nicht wissen.
Beim Definieren der Tabellen müssten Sie die allgemeinen Attribute für jede Untertypentabelle wiederholen. Das ist definitiv nicht trocken .
Das Suchen nach allen Richtlinien unabhängig vom Subtyp wird schwierig und erfordert eine Reihe von UNION
s.
Auf diese Weise müssten Sie alle Richtlinien unabhängig vom Typ abfragen:
SELECT date_issued, other_common_fields, 'MOTOR' AS type
FROM policies_motor
UNION ALL
SELECT date_issued, other_common_fields, 'PROPERTY' AS type
FROM policies_property;
Beachten Sie, dass für das Hinzufügen neuer Untertypen die obige Abfrage mit einem zusätzlichen UNION ALL
für jeden Untertyp geändert werden muss . Dies kann leicht zu Fehlern in Ihrer Anwendung führen, wenn dieser Vorgang vergessen wird.
Vererbung von Klassentabellen (auch bekannt als Vererbung von Tabellen pro Typ):
Dies ist die Lösung, die @David in der anderen Antwort erwähnt . Sie erstellen eine einzelne Tabelle für Ihre Basisklasse, die alle allgemeinen Attribute enthält. Dann würden Sie für jeden Subtyp bestimmte Tabellen erstellen, deren Primärschlüssel auch als Fremdschlüssel für die Basistabelle dient. Beispiel:
CREATE TABLE policies (
policy_id int,
date_issued datetime,
-- // other common attributes ...
);
CREATE TABLE policy_motor (
policy_id int,
vehicle_reg_no varchar(20),
-- // other attributes specific to motor insurance ...
FOREIGN KEY (policy_id) REFERENCES policies (policy_id)
);
CREATE TABLE policy_property (
policy_id int,
property_address varchar(20),
-- // other attributes specific to property insurance ...
FOREIGN KEY (policy_id) REFERENCES policies (policy_id)
);
Diese Lösung löst die in den beiden anderen Designs identifizierten Probleme:
Obligatorische Attribute können mit erzwungen werden NOT NULL
.
Das Hinzufügen eines neuen Untertyps erfordert das Hinzufügen einer neuen Tabelle, anstatt einer vorhandenen Spalte Spalten hinzuzufügen.
Kein Risiko, dass für einen bestimmten Subtyp ein unangemessenes Attribut festgelegt wird.
Das type
Attribut ist nicht erforderlich .
Jetzt werden die allgemeinen Attribute nicht mehr mit den subtypspezifischen Attributen gemischt.
Wir können endlich trocken bleiben. Es ist nicht erforderlich, die allgemeinen Attribute für jede Subtyp-Tabelle beim Erstellen der Tabellen zu wiederholen.
Das Verwalten eines automatischen Inkrementierens id
für die Richtlinien wird einfacher, da dies von der Basistabelle verwaltet werden kann, anstatt dass jede Subtyp-Tabelle sie unabhängig generiert.
Das Suchen nach allen Richtlinien unabhängig vom Subtyp wird jetzt sehr einfach: Keine UNION
s erforderlich - nur a SELECT * FROM policies
.
Ich halte den Klassentabellenansatz in den meisten Situationen für am besten geeignet.
Die Namen dieser drei Modelle stammen aus Martin Fowlers Buch Patterns of Enterprise Application Architecture .