Ich muss eine Situation modellieren, in der ich eine Tabelle Chequing_Account (die Budget, IBAN-Nummer und andere Details des Kontos enthält) habe, die mit zwei verschiedenen Tabellen Person und Corporation verknüpft sein muss, die beide 0, 1 oder viele Chequing-Konten haben können.
Mit anderen Worten, ich habe zwei 1-zu-viele-Beziehungen mit demselben Tabellen-Chequing-Konto
Ich würde gerne Lösungen für dieses Problem hören, die die Normalisierungsanforderungen berücksichtigen. Die meisten Lösungen, die ich gehört habe, sind:
1) Finden Sie eine gemeinsame Entität, zu der sowohl Person als auch Firma gehören, und erstellen Sie eine Verknüpfungstabelle zwischen dieser und der Tabelle Chequing_Account. Dies ist in meinem Fall nicht möglich, und selbst wenn ich das allgemeine Problem und nicht diese spezifische Instanz lösen möchte.
2) Erstellen Sie zwei Verknüpfungstabellen PersonToChequingAccount und CorporationToChequingAccount, die die beiden Entitäten mit den Kontrollkonten in Beziehung setzen. Ich möchte jedoch nicht, dass zwei Personen dasselbe Chequing-Konto haben, und ich möchte nicht, dass eine natürliche Person und eine Firma ein Chequing-Konto teilen! siehe dieses Bild
3) Erstellen Sie zwei Fremdschlüssel in Chequing Account, die auf Corporation und Natural Person verweisen. Allerdings würde ich damit erzwingen, dass eine Person und eine Firma viele Chequing Accounts haben können. Ich müsste jedoch manuell sicherstellen, dass nicht beide Beziehungen für jede ChequingAccount-Zeile auf verweisen Körperschaft und natürliche Person, weil ein Girokonto entweder eine Körperschaft oder eine natürliche Person ist. siehe dieses Bild
Gibt es eine andere sauberere Lösung für dieses Problem?
quelle
OwnerTypeID
in derChecquingAccount
Tabelle zu haben, mit1=Corporation
und2=NaturalPerson
? Auf diese Weise benötigen Sie nur eineOwnerID
in derChecquingAccount
Tabelle, die Sie zusammen mit der indizieren könnenOwnerTypeID
.CHECK (CorporationID IS NOT NULL AND NaturalPersonID IS NULL OR CorporationID IS NULL AND NaturalPersonID IS NOT NULL)
Ich bevorzuge jedoch Lösung 1 (aber das bin nur ich). Es ist viel "sauberer".ChecquingAccount
einen Datensatz vonOwnerTypeID=1
und in der Tabelle habenOwnerID=123
, der angibt, dass es sich um einen Typ handeltCorporation
, daher ID123
in derCorporation
Tabelle. Die OwnerTypeID gibt Auskunft darüber, welche Tabelle Sie haben, und die OwnerID gibt Auskunft über die ID in dieser Tabelle.Customers
Tisch.Antworten:
Relationale Datenbanken sind nicht dafür ausgelegt, mit dieser Situation perfekt umzugehen. Sie müssen entscheiden, was für Sie am wichtigsten ist, und dann Ihre Kompromisse eingehen. Sie haben mehrere Ziele:
Das Problem ist, dass einige dieser Ziele miteinander konkurrieren.
Subtypisierungslösung
Sie können eine Subtypisierungslösung auswählen, bei der Sie einen Supertyp erstellen, der sowohl Unternehmen als auch Personen umfasst. Dieser Supertyp hätte wahrscheinlich einen zusammengesetzten Schlüssel des natürlichen Schlüssels des Untertyps plus ein Partitionierungsattribut (z
customer_type
. B. ). Dies ist für die Normalisierung in Ordnung und ermöglicht es Ihnen, die referenzielle Integrität sowie die Einschränkung durchzusetzen, dass Unternehmen und Personen sich gegenseitig ausschließen. Das Problem ist, dass dies das Abrufen von Daten erschwert, da Sie immer nach demcustomer_type
Zeitpunkt verzweigen müssen, an dem Sie das Konto dem Kontoinhaber hinzufügen. Dies bedeutet wahrscheinlich,UNION
dass Sie eine Menge sich wiederholender SQL-Anweisungen in Ihrer Abfrage verwenden und verwenden müssen.Zwei Fremdschlüssel Lösung
Sie könnten eine Lösung wählen , wo Sie halten zwei Fremdschlüssel in Ihrem Konto Tisch, ein körperschaft und eine zu Person. Diese Lösung ermöglicht es Ihnen auch, die referenzielle Integrität, Normalisierung und gegenseitige Ausschließlichkeit aufrechtzuerhalten. Es hat auch den gleichen Nachteil beim Abrufen von Daten wie die Subtypisierungslösung. Tatsächlich ist diese Lösung genau wie die Untertypisierungslösung, mit der Ausnahme, dass Sie das Problem haben, Ihre Verknüpfungslogik "früher" zu verzweigen.
Dennoch würden viele Datenmodellierer diese Lösung aufgrund der Art und Weise, in der die gegenseitige Ausschließlichkeitsbeschränkung durchgesetzt wird, als der Subtypisierungslösung unterlegen betrachten. In der Subtypisierungslösung verwenden Sie Schlüssel, um die gegenseitige Exklusivität zu erzwingen. In der Lösung mit zwei Fremdschlüsseln verwenden Sie eine
CHECK
Einschränkung. Ich kenne einige Leute, die eine ungerechtfertigte Voreingenommenheit gegenüber Prüfungsbeschränkungen haben. Diese Leute würden die Lösung bevorzugen, die die Einschränkungen in den Schlüsseln beibehält.Lösung für das Partitionierungsattribut "Denormalized" (Denormalisiert)
Es gibt eine andere Option, bei der Sie eine einzelne Fremdschlüsselspalte in der Tabelle des Prüfkontos behalten und in einer anderen Spalte erfahren, wie die Fremdschlüsselspalte (RoKa's) zu interpretieren ist
OwnerTypeID
Säule). Dadurch wird die Supertyp-Tabelle in der Untertypisierungslösung im Wesentlichen eliminiert, indem das Partitionierungsattribut für die untergeordnete Tabelle denormalisiert wird. (Beachten Sie, dass dies gemäß der formalen Definition keine reine "Denormalisierung" ist, da das Partitionierungsattribut Teil eines Primärschlüssels ist.) Diese Lösung erscheint recht einfach, da keine zusätzliche Tabelle vorhanden ist, um mehr oder weniger dasselbe zu tun Reduziert die Anzahl der Fremdschlüsselspalten auf eins. Das Problem bei dieser Lösung besteht darin, dass das Verzweigen der Abruflogik nicht vermieden wird und darüber hinaus die deklarative referenzielle Integrität nicht aufrechterhalten werden kann . SQL-Datenbanken können keine einzelne Fremdschlüsselspalte für eine von mehreren übergeordneten Tabellen verwalten.Shared Primary Key Domain-Lösung
Eine Möglichkeit, mit diesem Problem umzugehen, besteht manchmal darin, einen einzelnen ID-Pool zu verwenden, damit für eine bestimmte ID nicht verwechselt werden kann, ob sie zu einem Subtyp oder einem anderen gehört. In einem Bankenszenario würde dies wahrscheinlich ganz natürlich funktionieren, da Sie nicht die gleiche Bankkontonummer sowohl für ein Unternehmen als auch für eine natürliche Person vergeben. Dies hat den Vorteil, dass kein Partitionierungsattribut erforderlich ist. Sie können dies mit oder ohne eine Super-Typ-Tabelle tun. Wenn Sie eine Supertyp-Tabelle verwenden, können Sie deklarative Einschränkungen verwenden, um die Eindeutigkeit zu erzwingen. Andernfalls müsste dies verfahrensrechtlich durchgesetzt werden. Diese Lösung ist normalisiert, ermöglicht es Ihnen jedoch nicht, die deklarative referenzielle Integrität beizubehalten, es sei denn, Sie führen die Supertyp-Tabelle. Es wird immer noch nichts unternommen, um eine komplexe Abruflogik zu vermeiden.
Sie sehen also, dass es nicht wirklich möglich ist, ein sauberes Design zu haben, das alle Regeln einhält, und gleichzeitig den Datenabruf einfach zu halten. Sie müssen entscheiden, wo Ihre Kompromisse sein werden.
quelle
corporation_id
undperson_id
dann wären, hätten Sie im Wesentlichen die Untertypisierungslösung, mit der Ausnahme, dass die Supertypentabelle in zwei Teile geteilt und der Fremdschlüssel invertiert worden wäre, sodass die Benutzer nicht über mehrere Konten verfügen könnten. Diese Art der Niederlage den Zweck.RefID
undRefTable
woRefTable
ist eine feste Kennung, identifiziert die Zieltabelle. Es gibt viele Anwendungsfälle für diesen Schlüsseltyp und es ist zu viel, um 10 oder mehr Zuordnungs- / Subtyp-Tabellen zu verwalten, um die Integrität durchzusetzen. Für diese Fälle habe ich daskey
selbst erstellt.