Implementieren eines Untertyps eines Untertyps in ein Typ / Untertyp-Entwurfsmuster mit sich gegenseitig ausschließenden Unterklassen


20

Einführung

Damit diese Frage für zukünftige Leser nützlich ist, werde ich das generische Datenmodell verwenden, um das Problem zu veranschaulichen, mit dem ich konfrontiert bin.

Unser Datenmodell besteht aus drei Einheiten, die als markiert werden sollen A, Bund C. Um die Dinge einfach zu halten, werden alle ihre Attribute vom intTyp sein.

Einheit Ahat folgende Eigenschaften: D, Eund X;

Einheit Bhat folgende Eigenschaften: D, Eund Y;

Die Entität Chat folgende Attribute: Dund Z;

Da alle Entitäten ein gemeinsames Attribut haben D, habe ich mich für das Design von Typ / Untertyp entschieden .

Wichtig: Einheiten schließen sich gegenseitig aus! Dies bedeutet, dass die Entität entweder A oder B oder C ist.

Problem:

Entitäten Aund Bhaben noch ein weiteres gemeinsames Attribut E, aber dieses Attribut ist in der Entität nicht vorhanden C.

Frage:

Ich möchte das oben beschriebene Merkmal nutzen, um mein Design nach Möglichkeit weiter zu optimieren.

Um ehrlich zu sein, ich habe keine Ahnung, wie das geht und wo ich anfangen soll, daher dieser Beitrag.

Antworten:


6

Insofern ist diese Frage eine Fortsetzung von Ist meine Implementierung des Entwurfsmusters Typ / Subtyp (für sich gegenseitig ausschließende Subklassen) korrekt? , was selbst eine Fortsetzung von Weiß nicht, wie man eine variable Entität in eine relationale Tabelle umwandelt , würde ich fragen: Was genau versuchen Sie zu optimieren? Lager? Das Objektmodell? Komplexität abfragen? Abfrageleistung? Es gibt Kompromisse bei der Optimierung eines Aspekts gegen einen anderen, da nicht alle Aspekte gleichzeitig optimiert werden können.

Ich stimme Remus in folgenden Punkten voll und ganz zu:

  • Es gibt Vor- und Nachteile für jeden Ansatz (dh den allgegenwärtigen "es hängt davon ab" -Faktor) und
  • Die erste Priorität ist die Effizienz des Datenmodells (ein ineffizientes Datenmodell kann nicht durch sauberen und / oder effizienten App-Code korrigiert werden).

Das heißt, Sie haben die Wahl zwischen den folgenden Optionen, die in der Reihenfolge der niedrigsten Normalisierung bis zur höchsten Normalisierung angeordnet sind:

  • Förderung des Eigentums Ean der Basis-Typ-Tabelle
  • Aufbewahrung in mehreren Untertypen-Tabellen
  • vollständig zu normalisieren E, um eine neue, Vermittler Unterklasse Tabelle auf dem gleichen Niveau wie C, dass Aund Bwird direkt Unterklassen (sein @ MDCCL Antwort )

Schauen wir uns jede Option an:

Verschieben Sie die Eigenschaft Ein die Tabelle des Basistyps

PROs

  • Reduced Abfrage Komplexität für Abfragen, die Notwendigkeit , Eaber nicht X, Yoder Z.
  • Potenziell effizienter für Abfragen, die Notwendigkeit , Eaber nicht X, Yoder Z(vor allem aggregierte Abfragen) aufgrund kein JOIN.
  • Potenzielle Erstellung eines Index für (D, E)(und (D, E)in diesem Fall möglicherweise eines gefilterten Index für EntityType <> C, sofern eine solche Bedingung zulässig ist)

CONs

  • Kann nicht Eals markierenNOT NULL
  • Benötigen Sie zusätzliche CHECK CONSTRAINTTabellen für den E IS NULLBasistyp, um sicherzustellen, dass bei EntityType = C(obwohl dies kein großes Problem ist)
  • Sie müssen die Benutzer des Datenmodells darüber informieren, warum EntityType = Eerforderlich NULList und warum dies überhaupt ignoriert werden sollte C.
  • Etwas weniger effizient, wenn Ees sich um einen Typ mit fester Länge handelt und ein großer Teil der Zeilen für EntityType von bestimmt ist C(dh nicht verwendet wird, Eweshalb dies der Fall ist NULL) und weder die SPARSEOption für die Spalte noch die Datenkomprimierung für den Clustered Index verwendet
  • Potenziell weniger effizient für Abfragen, die nicht benötigt werden, Eda das Vorhandensein Ein der Basistabelle die Größe jeder Zeile erhöht, was wiederum die Anzahl der Zeilen verringert, die auf eine Datenseite passen. Dies hängt jedoch in hohem Maße vom genauen Datentyp E, dem FILLFACTOR, der Anzahl der Zeilen in der Basistabelle usw. ab.

Behalten Sie die Eigenschaft Ein jeder Subtyp-Tabelle bei

PROs

  • Saubereres Datenmodell (dh Sie müssen sich keine Gedanken darüber machen, warum die Spalte Ein der Basistabelle nicht verwendet werden sollte, weil "es wirklich nicht da ist")
  • Wahrscheinlich ähnelt er eher dem Objektmodell
  • Kann Spalte markieren, als NOT NULLob dies eine erforderliche Eigenschaft der Entität ist
  • Keine Notwendigkeit für zusätzliche CHECK CONSTRAINTTabellen auf E IS NULLBasisbasis, um sicherzustellen, dass bei EntityType = C(obwohl dies kein großer Gewinn ist)

CONs

  • Benötigt JOIN, um die Eigenschaft zu erhalten
  • Potenziell etwas weniger effizient bei Bedarf E, aufgrund des JOIN, je nachdem, wie viele Zeilen A+ BSie haben, im Gegensatz zu wie vielen Zeilen Ces gibt.
  • Etwas schwieriger / komplexer für Operationen, die sich ausschließlich mit Entitäten befassen Aund B(und nicht C ) vom gleichen "Typ" sind. Natürlich können Sie dies über eine Ansicht abstrahieren, die eine UNION ALLzwischen einer SELECTder JOINed-Tabellen für Aund einer anderen SELECTder JOINed-Tabellen für ausführt B. Dies verringert die Komplexität von SELECT-Abfragen, ist jedoch für INSERTund UPDATEAbfragen weniger hilfreich .
  • Abhängig von den spezifischen Abfragen und der Häufigkeit, mit der sie ausgeführt werden, kann dies eine potenzielle Ineffizienz sein, wenn ein Index für (D, E)eine oder mehrere häufig verwendete Abfragen hilfreich ist, da sie nicht zusammen indiziert werden können.

Normalisieren Sie Ezwischen Basisklasse und A& auf VermittlertabelleB

(Bitte beachten Sie, dass ich die Antwort von @ MDCCL je nach den Umständen als sinnvolle Alternative mag . Das Folgende ist nicht als strenge Kritik an diesem Ansatz gedacht, sondern als Mittel, um eine Perspektive hinzuzufügen - meine natürlich - durch Bewerten Dies erleichtert die Klärung dessen, was ich als relativen Unterschied zwischen der vollständigen Normalisierung und dem derzeitigen Ansatz der teilweisen Normalisierung betrachte.)

PROs

  • Das Datenmodell ist vollständig normalisiert (daran kann nichts von Natur aus falsch sein, da RDBMS dafür ausgelegt sind).
  • Reduzierte Abfragekomplexität für Abfragen, die Aund benötigen B, jedoch nicht C(dh keine Notwendigkeit für zwei über verknüpfte Abfragen UNION ALL)

CONs

  • etwas mehr Platz in Anspruch genommen (die BarTabelle dupliziert die ID, und es gibt eine neue Spalte BarTypeCode) [zu vernachlässigen, aber etwas zu beachten]
  • Eine leichte Erhöhung der Abfragekomplexität JOINist erforderlich, um entweder zu Aoder zu gelangenB
  • Erhöhte Sperrfläche, meistens aktiviert INSERT( DELETEkann implizit durch Markieren von Fremdschlüsseln als behandelt werden ON CASCADE DELETE), da die Transaktion auf der Basisklassentabelle (dh Foo) etwas länger offen gehalten wird [vernachlässigbar, aber etwas, das beachtet werden muss]
  • keine direkte Kenntnis des tatsächlichen Typs - Aoder B- innerhalb der Basisklassentabelle Foo; es kennt nur den Typ, Brder entweder Aoder sein kann B:

    Das heißt, wenn Sie Abfragen über die allgemeinen Basisinformationen durchführen müssen, diese jedoch entweder nach Entitätstyp kategorisieren oder einen oder mehrere Entitätstypen herausfiltern müssen, verfügt die Basisklassentabelle nicht über genügend Informationen. In diesem Fall ist dies erforderlich LEFT JOINder BarTisch. Dies verringert auch die Wirksamkeit der Indizierung der FooTypeCodeSpalte.

  • Kein einheitlicher Ansatz für die Interaktion mit A& Bvs C:

    Das heißt, wenn sich jede Entität direkt auf die Basisklassentabelle bezieht, sodass immer nur ein JOIN vorhanden ist, um die vollständige Entität abzurufen, kann jeder schneller und einfacher eine Vertrautheit in Bezug auf die Arbeit mit dem Datenmodell aufbauen. Es wird einen gemeinsamen Ansatz für Abfragen / gespeicherte Prozeduren geben, der die Entwicklung beschleunigt und die Wahrscheinlichkeit von Fehlern verringert. Ein konsistenter Ansatz erleichtert und beschleunigt das Hinzufügen neuer Untertypen in Zukunft.

  • Möglicherweise weniger anpassungsfähig an Geschäftsregeln, die sich im Laufe der Zeit ändern:

    Das heißt, die Dinge ändern sich immer und es ist ziemlich einfach, Ezur Basisklassentabelle aufzusteigen, wenn sie allen Untertypen gemeinsam ist. Es ist auch einfach genug, eine gemeinsame Eigenschaft in die Untertypen zu verschieben, wenn Änderungen in der Art der Entitäten dies zu einer lohnenden Änderung machen. Es ist einfach genug, einen Untertyp in zwei Untertypen zu unterteilen (nur einen anderen SubTypeIDWert zu erstellen ) oder zwei oder mehr Untertypen zu einem zu kombinieren. Umgekehrt, was wäre, wenn Espäter eine gemeinsame Eigenschaft aller Untertypen geworden wäre? Dann wäre die Zwischenschicht der BarTabelle bedeutungslos und die zusätzliche Komplexität wäre es nicht wert. Natürlich ist es unmöglich zu wissen, ob eine solche Änderung in 5 oder sogar 10 Jahren eintreten würde, daher Barist dies nicht unbedingt der Fallund wahrscheinlich auch nicht eine schlechte Idee (weshalb ich sagte " möglicherweise weniger anpassungsfähig"). Dies sind nur Punkte, die berücksichtigt werden müssen. Es ist ein Glücksspiel in beide Richtungen.

  • potenziell unangemessene Gruppierung:

    Das heißt, nur weil die EEigenschaft von Entitätstypen gemeinsam genutzt wird Aund Bdies nicht bedeutet Aund zusammengefasst werden B sollte . Nur weil die Dinge gleich "aussehen" (dh gleiche Eigenschaften), heißt das nicht, dass sie gleich sind.

Zusammenfassung

Genau wie bei der Entscheidung, ob und wann eine Denormalisierung erfolgen soll, hängt die beste Vorgehensweise für diese bestimmte Situation davon ab, ob die folgenden Aspekte der Verwendung des Datenmodells berücksichtigt werden und ob der Nutzen die Kosten überwiegt:

  • wie viele Zeilen Sie für jeden EntityType haben werden (sehen Sie mindestens 5 Jahre später nach, unter der Annahme eines überdurchschnittlichen Wachstums)
  • Wie viele GB wird jede dieser Tabellen (Basistyp und Untertypen) in 5 Jahren sein?
  • Welcher bestimmte Datentyp ist Eigentum E
  • ist es nur eine eigenschaft oder gibt es einige oder sogar mehrere eigenschaften?
  • Welche Abfragen benötigen Sie dazu Eund wie oft werden sie ausgeführt
  • Welche Abfragen Sie benötigen, brauchen Sie nicht Eund wie oft werden sie ausgeführt

Ich denke, ich neige dazu, standardmäßig Ein den separaten Untertypentabellen zu bleiben, weil es zumindest "sauberer" ist. Ich würde in Betracht ziehen, Ein die Basistabelle IF zu wechseln : Die meisten Zeilen waren nicht für EntityType von C; und die Zahl Reihen war mindestens in den Millionen; und ich habe häufig Abfragen ausgeführt, die benötigt werden, Eund / oder die Abfragen, die von einem Index für profitieren würden, werden (D, E)entweder sehr häufig ausgeführt und / oder erfordern genügend Systemressourcen, so dass der Index die gesamte Ressourcennutzung verringert oder zumindest verhindert Anstieg des Ressourcenverbrauchs, der über das akzeptable Maß hinausgeht oder lange genug anhält, um übermäßige Blockierung und / oder Zunahme von Deadlocks zu verursachen.


AKTUALISIEREN

OP kommentierte diese Antwort wie folgt:

Meine Arbeitgeber haben die Geschäftslogik geändert und E komplett entfernt!

Diese Änderung ist besonders wichtig, da dies genau das ist, was ich im Unterabschnitt "CONs" des obigen Abschnitts " EAuf Zwischentabelle normalisieren zwischen Basisklasse und A& B" vorausgesagt habe (6. Aufzählungspunkt). Das spezifische Problem ist, wie einfach / schwierig es ist, das Datenmodell umzugestalten, wenn solche Änderungen auftreten (und das tun sie immer). Einige werden argumentieren, dass jedes Datenmodell überarbeitet / geändert werden kann. Beginnen Sie also mit dem Ideal. Aber während es wahr ist , auf einem technischen Niveau , dass etwas Refactoring werden kann, die Realität der Situation ist eine Frage des Maßstabs.

Ressourcen sind nicht unendlich, nicht nur CPU / Disk / RAM, sondern auch Entwicklungsressourcen: Zeit und Geld. Unternehmen setzen ständig Prioritäten für Projekte, da diese Ressourcen sehr begrenzt sind. Und nicht selten (zumindest nach meiner Erfahrung) werden Projekte zur Steigerung der Effizienz (selbst die Systemleistung sowie eine schnellere Entwicklung / weniger Fehler) vor Projekten priorisiert, die die Funktionalität erhöhen. Während es für uns Techniker frustrierend ist, weil wir die langfristigen Vorteile von Refactoring-Projekten verstehen, ist es nur die Natur des Geschäfts, dass die weniger technischen Geschäftsleute die direkte Beziehung zwischen neuen Funktionen und neuen Funktionen leichter erkennen können Einnahmen. Darauf kommt es an: "Wir werden später zurückkommen, um das zu beheben." == "

Wenn die Größe der Daten klein genug ist, so dass Änderungen sehr abfragbar sind, und / oder wenn Sie ein Wartungsfenster haben, das lang genug ist, um nicht nur die Änderungen vorzunehmen, sondern auch ein Rollback durchzuführen, wenn etwas passiert falsch, dann könnte das Normalisieren Eauf eine Zwischentabelle zwischen der Basisklassentabelle und der A& BUnterklassentabelle funktionieren (obwohl Sie dann immer noch keine direkten Kenntnisse über den bestimmten Typ haben ( AoderB) in der Basisklassentabelle). ABER wenn Sie Hunderte Millionen Zeilen in diesen Tabellen haben und unglaublich viel Code auf die Tabellen verweist (Code, der getestet werden muss, wenn Änderungen vorgenommen werden), lohnt es sich normalerweise, pragmatischer als idealistisch zu sein. Und mit dieser Umgebung musste ich jahrelang umgehen: 987 Millionen Zeilen und 615 GB in der Basisklassentabelle, verteilt auf 18 Server. Und so viel Code traf auf diese Tabellen (Tabellen der Basis- und Unterklassen), dass es - meistens vom Management, manchmal aber auch vom Rest des Teams - großen Widerstand gab, Änderungen aufgrund des Entwicklungs- und Entwicklungsaufwands vorzunehmen QA-Ressourcen, die zugewiesen werden müssten.

Der "beste" Ansatz kann also wiederum nur situationsabhängig ermittelt werden: Sie müssen Ihr System kennen (dh wie viele Daten und wie die Tabellen und der Code sich alle beziehen), wie das Refactoring durchgeführt werden soll und wie die Mitarbeiter mit denen Sie zusammenarbeiten (Ihr Team und möglicherweise das Management - können Sie sich für ein solches Projekt einkaufen?). Es gibt einige Änderungen, die ich seit 1 - 2 Jahren erwähne und plane, und ich habe mehrere Sprints / Releases durchgeführt, um vielleicht 85% davon zu implementieren. Aber wenn Sie nur <1 Million Zeilen haben und nicht viel Code an diese Tabellen gebunden ist, können Sie wahrscheinlich auf die idealere / "reine" Seite der Dinge gehen.

Denken Sie daran, egal für welchen Weg Sie sich entscheiden, achten Sie darauf, wie das Modell in den nächsten 2 Jahren funktioniert (wenn möglich). Achten Sie darauf, was funktioniert hat und was Schmerzen verursacht hat, auch wenn es zu der Zeit die beste Idee schien (was bedeutet, dass Sie sich auch erlauben müssen, Fehler zu akzeptieren - wir alle tun dies -, damit Sie die Schmerzpunkte ehrlich beurteilen können ). Und achten Sie darauf, warum bestimmte Entscheidungen erfolgreich waren oder nicht, damit Sie Entscheidungen treffen können, die beim nächsten Mal mit größerer Wahrscheinlichkeit "besser" sind :-).


17

Martin Fowler zufolge gibt es drei Ansätze für das Problem der Tabellenvererbung:

  • Einzelne Tabellenvererbung : Eine Tabelle repräsentiert alle Typen. Nicht verwendete Attribute sind NULL.
  • Konkrete Tabellenvererbung : Eine Tabelle pro konkretem Typ, jede Tabellenspalte für jedes Attribut des Typs. Keine Beziehung zwischen Tabellen.
  • Klassentabellenvererbung : Eine Tabelle pro Typ. Jede Tabelle verfügt nur über Attribute für neue, nicht vererbte Attribute. Tabellen sind miteinander verknüpft und spiegeln die tatsächliche Typvererbungshierarchie wider.

Sie können damit als Ausgangspunkt für die Suche nach Vor- und Nachteilen für jeden Ansatz beginnen. Der Kern davon ist, dass alle Ansätze große Nachteile haben und keiner einen überwältigenden Vorteil hat. Besser bekannt als die Fehlanpassung der relationalen Objektimpedanz , muss dieses Problem noch gelöst werden.

Persönlich finde ich , dass die Art von Problemen ein schlechtes relationales Design führen zu Größenordnungen ernster als die Art von Problemen , von einem schlechten entstehen Art Design. Schlechtes Datenbankdesign führt zu langsamen Abfragen, Aktualisierungsanomalien, Datengrößenexplosion, Deadlocks und nicht reagierenden Apps sowie zu Datenmengen von zehn bis hundert Gigabyte, die im falschen Format gespeichert wurden . Schlechtes Schriftdesign führt dazu, dass der Code nur schwer zu warten und zu aktualisieren ist , nicht die Laufzeit. Daher übertrumpft in meinem Buch korrektes relationales Design jede Reinheit des OO-Typs immer und immer wieder.


@AlwaysLearningNewStuff Ich denke, diese Frage ist eine Fortsetzung von dba.stackexchange.com/questions/139092 , richtig? Bei der Umsetzung gibt man tut Tabelle Erbe hat.
Remus Rusanu

Ja, bevor ich diese Frage stellte, wollte ich sicherstellen, dass ich richtig verstanden habe, wie das Typ / Subtyp-Design zuerst implementiert wird. Jetzt habe ich das oben beschriebene Problem, wenn einige (aber nicht alle!) Unterklassen gemeinsame Attribute haben. Ich habe mich gefragt, ob ich in diesem Fall etwas tun kann, um das Datenmodell zu optimieren, anstatt diese Nuance zu ignorieren ...
AlwaysLearningNewStuff

6

Nach meiner Interpretation Ihrer Spezifikationen möchten Sie eine Methode finden, um zwei verschiedene (aber zusammenhängende ) Supertyp-Subtyp- Strukturen zu implementieren .

Um einen Ansatz zur Erreichung der oben genannten Aufgabe aufzuzeigen, füge ich dem fraglichen Szenario die beiden klassischen hypothetischen Entitätstypen hinzu, die als Foound bezeichnet werden und auf Bardie ich unten näher eingehen werde.

Geschäftsregeln

Hier sind einige Anweisungen, die mir beim Erstellen eines logischen Modells helfen:

  • A Foo is either one Bar or one C
  • A Foo is categorized by one FooType
  • A Bar is either one A or one C
  • A Bar is classified by one BarType

Logisches Modell

Das resultierende logische IDEF1X [1] -Modell ist in Abbildung 1 dargestellt (und Sie können es auch als PDF von Dropbox herunterladen ):

Abbildung 1 - Hypothetisches Supertyp-Subtyp-Beziehungsdatenmodell

Der Foo and Bar Zusatz

Ich habe nicht hinzufügen Foound Bardas Modell besser aussehen zu machen, aber es ausdrucksvoller zu machen. Ich halte sie aus folgenden Gründen für wichtig:

  • Wie Aund Bdas Attribut mit dem Namen teilt E, ist diese Funktion legt nahe , dass sie Sub - Entität Arten eines deutlichen (aber verwandte) Art sind Konzept , Event , Person , Messung usw., die ich mit Hilfe des dargestellten Barsuperentity Typ das wiederum ist Ein Subentity-Typ von Foo, der das DAttribut oben in der Hierarchie enthält.

  • Da Cnur ein Attribut mit den übrigen diskutierten Entitätstypen gemeinsam ist, dh Ddieser Aspekt unterstellt, dass es sich um einen Subentitätstyp einer anderen Art von Konzept , Ereignis , Person , Messung usw. handelt, habe ich diesen Umstand anhand von dargestellt der Foosuper Entitätstyp.

Dies sind jedoch nur Annahmen, und da eine relationale Datenbank die Semantik eines bestimmten Geschäftskontexts genau widerspiegeln soll , müssen Sie alle interessanten Dinge in Ihrer spezifischen Domäne identifizieren und klassifizieren , damit Sie genau die Bedeutung erfassen können .

Wichtige Faktoren in der Entwurfsphase

Es ist sehr nützlich, sich der Tatsache bewusst zu sein, dass, abgesehen von der Terminologie, ein exklusiver Supertyp-Subtyp-Cluster eine gewöhnliche Beziehung ist. Beschreiben wir die Situation folgendermaßen:

  • Jedes Auftreten eines exklusiven Superentitätstyps bezieht sich nur auf ein Subentitätstyp- Komplement.

Somit besteht in diesen Fällen eine Übereinstimmung (oder Kardinalität) von eins zu eins (1: 1).

Wie Sie aus Ihren vorangegangenen Beiträgen wissen, spielt das Diskriminatorattribut (Spalte, sofern implementiert) beim Erstellen einer Assoziation dieser Art eine übergeordnete Rolle , da es die richtige Subtypinstanz angibt, mit der der Supertyp verbunden ist . Die Migration des PRIMARY KEY von (i) dem Supertyp zu (ii) den Subtypen ist ebenfalls von vorrangiger Bedeutung.

Konkrete DDL-Struktur

Und dann habe ich eine DDL-Struktur geschrieben, die auf dem oben dargestellten logischen Modell basiert:

CREATE TABLE FooType -- Look-up table.
(
    FooTypeCode     CHAR(2)  NOT NULL,
    Description     CHAR(90) NOT NULL, 
    CreatedDateTime DATETIME NOT NULL,
    CONSTRAINT PK_FooType             PRIMARY KEY (FooTypeCode),
    CONSTRAINT AK_FooType_Description UNIQUE      (Description)
);

CREATE TABLE Foo -- Supertype
(
    FooId           INT      NOT NULL, -- This PK migrates (1) to ‘Bar’ as ‘BarId’, (2) to ‘A’ as ‘AId’, (3) to ‘B’ as ‘BId’, and (4) to ‘C’ as ‘CId’.
    FooTypeCode     CHAR(2)  NOT NULL, -- Discriminator column.
    D               INT      NOT NULL, -- Column that applies to ‘Bar’ (and therefore to ‘A’ and ‘B’) and ‘C’.
    CreatedDateTime DATETIME NOT NULL,
    CONSTRAINT PK_Foo                 PRIMARY KEY (FooId),
    CONSTRAINT FK_from_Foo_to_FooType FOREIGN KEY (FooTypeCode)
        REFERENCES FooType (FooTypeCode)
);

CREATE TABLE BarType -- Look-up table.
(
    BarTypeCode CHAR(1)  NOT NULL,  
    Description CHAR(90) NOT NULL,  
    CONSTRAINT PK_BarType             PRIMARY KEY (BarTypeCode),
    CONSTRAINT AK_BarType_Description UNIQUE      (Description)
);

CREATE TABLE Bar -- Subtype of ‘Foo’.
(
    BarId       INT     NOT NULL, -- PK and FK.
    BarTypeCode CHAR(1) NOT NULL, -- Discriminator column. 
    E           INT     NOT NULL, -- Column that applies to ‘A’ and ‘B’.
    CONSTRAINT PK_Bar             PRIMARY KEY (BarId),
    CONSTRAINT FK_from_Bar_to_Foo FOREIGN KEY (BarId)
        REFERENCES Foo (FooId),
    CONSTRAINT FK_from_Bar_to_BarType FOREIGN KEY (BarTypeCode)
        REFERENCES BarType (BarTypeCode)    
);

CREATE TABLE A -- Subtype of ‘Bar’.
(
    AId INT NOT NULL, -- PK and FK.
    X   INT NOT NULL, -- Particular column.  
    CONSTRAINT PK_A             PRIMARY KEY (AId),
    CONSTRAINT FK_from_A_to_Bar FOREIGN KEY (AId)
        REFERENCES Bar (BarId)  
);

CREATE TABLE B -- (1) Subtype of ‘Bar’ and (2) supertype of ‘A’ and ‘B’.
(
    BId INT NOT NULL, -- PK and FK.
    Y   INT NOT NULL, -- Particular column.  
    CONSTRAINT PK_B             PRIMARY KEY (BId),
    CONSTRAINT FK_from_B_to_Bar FOREIGN KEY (BId)
        REFERENCES Bar (BarId)  
);

CREATE TABLE C -- Subtype of ‘Foo’.
(
    CId INT NOT NULL, -- PK and FK.
    Z   INT NOT NULL, -- Particular column.  
    CONSTRAINT PK_C             PRIMARY KEY (CId),
    CONSTRAINT FK_from_C_to_Foo FOREIGN KEY (FooId)
        REFERENCES Foo (FooId)  
);

Mit dieser Struktur vermeiden Sie das Speichern von NULL-Marken in Ihren Basistabellen (oder -relationen ), was zu Mehrdeutigkeiten in Ihrer Datenbank führen würde.

Integrität, Konsistenz und andere Überlegungen

Wenn Sie Ihre Datenbank implementiert haben, müssen Sie sicherstellen, dass (a) jede exklusive Supertyp- Zeile immer durch das entsprechende Subtyp- Gegenstück ergänzt wird und dass (b) diese Subtyp- Zeile mit dem in der Supertyp- Diskriminator- Spalte enthaltenen Wert kompatibel ist . Daher ist es sehr praktisch, ACID TRANSACTIONSzu verwenden, um sicherzustellen, dass diese Bedingungen in Ihrer Datenbank erfüllt sind.

Sie sollten nicht auf die logische Solidität, Selbstausdruckskraft und Genauigkeit Ihrer Datenbank verzichten. Dies sind Aspekte, die Ihre Datenbank entscheidend solider machen.

Die beiden zuvor veröffentlichten Antworten enthalten bereits relevante Punkte, die beim Entwerfen, Erstellen und Verwalten Ihrer Datenbank und ihrer Anwendungsprogramme unbedingt berücksichtigt werden sollten.

Abrufen von Daten über VIEW-Definitionen

Sie können einige Sichten einrichten, die Spalten der verschiedenen Supertype-Subtype- Gruppen kombinieren , damit Sie die vorliegenden Daten abrufen können, ohne z. B. jedes Mal die erforderlichen JOIN-Klauseln zu schreiben. Auf diese Weise können Sie problemlos direkt AUS DER ANSICHT (eine abgeleitete Beziehung oder Tabelle ) von Interesse AUSWÄHLEN.

Wie Sie sehen, war „Ted“ Codd zweifellos ein Genie. Die Werkzeuge, die er hinterlassen hat, sind ziemlich stark und elegant und natürlich gut miteinander integriert.

Ähnliche Resourcen

Wenn Sie eine umfangreiche Datenbank analysieren möchten, die Supertyp-Subtyp-Beziehungen enthält, sind die von @PerformanceDBA vorgeschlagenen außergewöhnlichen Antworten auf die folgenden Stapelüberlauf- Fragen von Nutzen :


Hinweis

1. Integration Definition für Informationsmodellierung ( IDEF1X ) ist eine sehr empfehlenswerte Datenmodellierungstechnik, die als etabliert wurde Standard im Dezember 1993 von den Vereinigten Staaten National Institute of Standards and Technology ( NIST ). Es basiert auf (a) dem frühen theoretischen Material von Dr. EF Codd; zu (b) der Entity-Relationship- Sicht auf Daten, entwickelt von Dr. PP Chen ; und auch auf (c) der Logical Database Design Technique, erstellt von Robert G. Brown. Es ist erwähnenswert, dass IDEF1X mit Hilfe von Logik erster Ordnung formalisiert wurde.


Meine Arbeitgeber haben die Geschäftslogik geändert und Einsgesamt entfernt! Der Grund für das Akzeptieren der Antwort von Benutzer srutzky ist, dass sie gute Punkte liefert, die mir helfen, meine Entscheidung für die Wahl der effizientesten Route zu treffen. Wenn nicht, würde ich Ihre Antwort akzeptieren. Ich habe Ihre Antwort vorhin positiv bewertet. Danke noch einmal!
AlwaysLearningNewStuff
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.