Ich habe eine Tabelle, in der die Zeilen miteinander in Beziehung gesetzt werden können, und logischerweise verläuft die Beziehung zwischen den beiden Zeilen in beide Richtungen (im Grunde genommen richtungslos). (Und wenn Sie sich fragen, ja, dies sollte wirklich eine Tabelle sein. Es sind zwei Dinge von genau derselben logischen Entität / demselben logischen Typ.) Ich kann mir ein paar Möglichkeiten vorstellen, dies darzustellen:
- Speichern Sie die Beziehung und ihre Umkehrung
- Speichern Sie die Beziehung in eine Richtung, beschränken Sie die Datenbank daran, sie in die andere Richtung zu speichern, und haben Sie zwei Indizes mit entgegengesetzter Reihenfolge für die FKs (ein Index ist der PK-Index).
- Speichern Sie die Beziehung auf eine Weise mit zwei Indizes und lassen Sie die zweite trotzdem einfügen (klingt irgendwie glücklich, aber hey, Vollständigkeit)
- Erstellen Sie eine Art Gruppierungstabelle und haben Sie eine FK in der Originaltabelle. (Wirft viele Fragen auf. Die Gruppierungstabelle würde nur eine Zahl haben. Warum überhaupt die Tabelle? FK NULLable machen oder Gruppen mit einer einzelnen Zeile zuordnen?)
Was sind einige wichtige Vor- und Nachteile dieser Wege, und gibt es natürlich einen Weg, an den ich nicht gedacht habe?
Hier ist eine SQLFiddle zum Spielen: http://sqlfiddle.com/#!12/7ee1a/1/0 . (Scheint PostgreSQL zu sein, da ich das verwende, aber ich denke nicht, dass diese Frage sehr spezifisch für PostgreSQL ist.) Derzeit werden sowohl die Beziehung als auch die Umkehrung nur als Beispiel gespeichert.
quelle
Antworten:
Was Sie entworfen haben, ist gut. Was hinzugefügt werden muss, ist eine Einschränkung, um die Beziehung richtungslos zu machen. Sie können also keine
(1,5)
Zeile haben, ohne dass auch eine(5,1)
Zeile hinzugefügt wird.Dies kann * mit einer selbstreferenzierenden Einschränkung für die Brückentabelle erreicht werden.
*: Dies kann in Postgres, Oracle, DB2 und allen DBMS durchgeführt werden, die Fremdschlüsseleinschränkungen implementiert haben, wie im SQL-Standard beschrieben (verzögert, z. B. am Ende der Transaktion überprüft). Eine verzögerte Überprüfung ist ohnehin nicht wirklich erforderlich, wie in SQL- Server, der sie am Ende der Anweisung überprüft und diese Konstruktion funktioniert weiterhin. Sie können dies in MySQL nicht tun, da "InnoDB die Einschränkungen für EINZIGARTIGE und AUSLÄNDISCHE SCHLÜSSEL zeilenweise überprüft" .
In Postgres entspricht Folgendes Ihren Anforderungen:
Getestet bei: SQL-Fiddle
Wenn Sie versuchen, eine Zeile hinzuzufügen
(1,5)
:Es schlägt fehl mit:
Darüber hinaus können Sie eine
CHECK
Einschränkung hinzufügen , wenn Sie(y,y)
Zeilen verbieten möchten :Wie Sie bereits erwähnt haben, gibt es andere Möglichkeiten, dies zu implementieren, z. B. das Speichern nur einer Richtung der Beziehung (in einer Zeile, nicht in zwei), indem die niedrigere ID
x_id1
und die höhere ID in derx_id2
Spalte erzwungen werden. Es sieht einfacher zu implementieren aus, führt aber normalerweise später zu komplexeren Abfragen:quelle