Eine andere Möglichkeit (ohne Nullen und ohne Zyklen in den FOREIGN KEY
Beziehungen) besteht darin, eine dritte Tabelle zum Speichern der "Lieblingskinder" zu haben. In den meisten DBMS benötigen Sie eine zusätzliche UNIQUE
Einschränkung für TableB
.
@Aaron erkannte schneller, dass die oben genannte Namenskonvention ziemlich umständlich ist und zu Fehlern führen kann. Es ist normalerweise besser (und wird Sie gesund halten), wenn Sie nicht alle Id
Spalten in Ihren Tabellen haben und wenn die Spalten (die verbunden sind) in den vielen Tabellen, die angezeigt werden, den gleichen Namen haben. Also, hier ist eine Umbenennung:
Parent
ParentID INT NOT NULL PRIMARY KEY
Child
ChildID INT NOT NULL PRIMARY KEY
ParentID INT NOT NULL FOREIGN KEY REFERENCES Parent (ParentID)
UNIQUE (ParentID, ChildID)
FavoriteChild
ParentID INT NOT NULL PRIMARY KEY
ChildID INT NOT NULL
FOREIGN KEY (ParentID, ChildID)
REFERENCES Child (ParentID, ChildID)
In SQL-Server (den Sie verwenden) können Sie auch die IsFavorite
erwähnte Bitspalte auswählen. Das eindeutige Lieblingskind pro Elternteil kann über einen gefilterten eindeutigen Index erreicht werden:
Parent
ParentID INT NOT NULL PRIMARY KEY
Child
ChildID INT NOT NULL PRIMARY KEY
ParentID INT NOT NULL FOREIGN KEY REFERENCES Parent (ParentID)
IsFavorite BIT NOT NULL
CREATE UNIQUE INDEX is_FavoriteChild
ON Child (ParentID)
WHERE IsFavorite = 1 ;
Der Hauptgrund dafür, dass Ihre Option 1 nicht empfohlen wird, zumindest nicht in SQL-Server, besteht darin, dass das Muster der kreisförmigen Pfade in den Fremdschlüsselreferenzen einige Probleme aufweist.
Lesen Sie einen ziemlich alten Artikel: SQL By Design: The Circular Reference
Beim Einfügen oder Löschen von Zeilen aus den beiden Tabellen tritt das Problem "Henne und Ei" auf. Welche Tabelle soll ich zuerst einfügen - ohne Einschränkung?
Um dies zu lösen, müssen Sie mindestens eine Spalte definieren, die nullwertfähig ist. (Technisch gesehen müssen Sie das nicht. Sie können alle Spalten haben, NOT NULL
aber nur in DBMS, wie Postgres und Oracle, die aufschiebbare Einschränkungen implementiert haben. Siehe @ Erwins Antwort in einer ähnlichen Frage: Komplexe Fremdschlüssel-Einschränkung in SQLAlchemy, wie Dies kann in Postgres erfolgen. Dennoch fühlt sich dieses Setup an, als würde man auf dünnem Eis Schlittschuh laufen.
Überprüfen Sie auch eine fast identische Frage bei SO (aber für MySQL). Ist es in SQL in Ordnung, wenn zwei Tabellen aufeinander verweisen? wo meine antwort so ziemlich gleich ist. MySQL hat jedoch keine Teilindizes. Die einzigen möglichen Optionen sind die nullbaren FK und die zusätzliche Tabellenlösung.