Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

Wie kann man Vererbung in einer Datenbank darstellen?

@Bill Karwin beschreibt in seinem Buch SQL Antipatterns drei Vererbungsmodelle, wenn er Lösungen für das Antipattern SQL Entity-Attribute-Value vorschlägt. Dies ist eine kurze Übersicht:

Einzeltabellenvererbung (auch bekannt als Tabelle pro Hierarchievererbung):

Die Verwendung einer einzelnen Tabelle wie in Ihrer ersten Option ist wahrscheinlich das einfachste Design. Wie Sie bereits erwähnt haben, muss vielen subtypspezifischen Attributen ein NULL gegeben werden Wert auf Zeilen, auf die diese Attribute nicht zutreffen. Bei diesem Modell hätten Sie eine Richtlinientabelle, die etwa 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 -----/

Es ist von Vorteil, das Design einfach zu halten, aber die Hauptprobleme bei diesem Ansatz sind die folgenden:

  • Wenn es darum geht, neue Untertypen hinzuzufügen, müssten Sie die Tabelle ändern, um die Attribute aufzunehmen, die diese neuen Objekte beschreiben. Dies kann schnell problematisch werden, wenn Sie viele Untertypen haben oder regelmäßig Untertypen hinzufügen möchten.

  • Die Datenbank kann nicht erzwingen, welche Attribute zutreffen und welche nicht, da es keine Metadaten gibt, um zu definieren, welche Attribute zu welchen Untertypen gehören.

  • Sie können auch NOT NULL nicht erzwingen auf Attributen eines Untertyps, die obligatorisch sein sollten. Sie müssten dies in Ihrer Anwendung berücksichtigen, was im Allgemeinen nicht ideal ist.

Konkrete Tabellenvererbung:

Ein weiterer Ansatz zur Bekämpfung der Vererbung besteht darin, für jeden Untertyp eine neue Tabelle zu erstellen und alle gemeinsamen Attribute in jeder Tabelle zu wiederholen. Zum Beispiel:

--// 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 wird im Wesentlichen die Probleme lösen, die für die Einzeltabellenmethode identifiziert wurden:

  • Pflichtattribute können jetzt mit NOT NULL erzwungen werden .

  • Das Hinzufügen eines neuen Untertyps erfordert das Hinzufügen einer neuen Tabelle, anstatt Spalten zu einer vorhandenen hinzuzufügen.

  • Es besteht auch kein Risiko, dass ein ungeeignetes Attribut für einen bestimmten Untertyp gesetzt wird, wie z. B. die vehicle_reg_no Feld für eine Eigenschaftsrichtlinie.

  • Der type ist nicht erforderlich Attribut wie bei der Einzeltabellenmethode. Der Typ wird jetzt durch die Metadaten definiert:den Tabellennamen.

Allerdings hat dieses Modell auch einige Nachteile:

  • Die allgemeinen Attribute sind 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 gemeinsamen Attribute für jede Untertyptabelle wiederholen. Das ist definitiv nicht TROCKEN.

  • Die Suche nach allen Richtlinien unabhängig vom Untertyp wird schwierig und würde eine Menge UNION erfordern s.

So 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 das Hinzufügen neuer Untertypen erfordern würde, dass die obige Abfrage mit einem zusätzlichen UNION ALL geändert wird für jeden Untertyp. 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 gemeinsamen Attribute enthält. Dann würden Sie für jeden Untertyp spezifische 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 Probleme, die in den anderen beiden Entwürfen identifiziert wurden:

  • Pflichtattribute können mit NOT NULL erzwungen werden .

  • Das Hinzufügen eines neuen Untertyps erfordert das Hinzufügen einer neuen Tabelle, anstatt Spalten zu einer vorhandenen hinzuzufügen.

  • Kein Risiko, dass ein unpassendes Attribut für einen bestimmten Untertyp gesetzt wird.

  • Keine Notwendigkeit für den type Attribut.

  • Jetzt werden die allgemeinen Attribute nicht mehr mit den Subtype-spezifischen Attributen gemischt.

  • Wir können endlich TROCKEN bleiben. Beim Erstellen der Tabellen müssen die gemeinsamen Attribute nicht für jede Untertyptabelle wiederholt werden.

  • Verwalten einer automatisch inkrementierenden id für die Richtlinien wird einfacher, da dies von der Basistabelle gehandhabt werden kann, anstatt dass jede Untertyptabelle sie unabhängig generiert.

  • Die Suche nach allen Richtlinien unabhängig vom Untertyp wird jetzt sehr einfach:Kein UNION s erforderlich - nur ein SELECT * FROM policies .

Ich halte den Klassentabellen-Ansatz für die meisten Situationen für am geeignetsten.

Die Namen dieser drei Modelle stammen aus dem Buch Patterns of Enterprise Application Architecture von Martin Fowler.