Warum benötigen zusammengesetzte Fremdschlüssel eine separate eindeutige Einschränkung?

10

Hier ist eine einfache Tabelle, in der Datensätze auf übergeordnete Datensätze in derselben Tabelle verweisen können:

CREATE TABLE foo (
    id         SERIAL  PRIMARY KEY,
    parent_id  INT     NULL,
    num        INT     NOT NULL,
    txt        TEXT    NULL,
    FOREIGN KEY (parent_id) REFERENCES foo(id)
);

Mit der zusätzlichen Anforderung, dass einer der anderen Feldwerte ( num) zwischen übergeordneten und untergeordneten Datensätzen identisch sein muss, dachte ich, dass ein zusammengesetzter Fremdschlüssel den Trick machen sollte. Ich habe die letzte Zeile in geändert

    FOREIGN KEY (parent_id, num) REFERENCES foo(id, num)

und ERROR erhalten: Es gibt keine eindeutige Einschränkung, die den angegebenen Schlüsseln für die referenzierte Tabelle "foo" entspricht .

Ich kann diese Einschränkung leicht hinzufügen, verstehe aber nicht, warum dies erforderlich ist, wenn eine der referenzierten Spalten ( id) bereits eindeutig ist. So wie ich es sehe, wäre die neue Einschränkung überflüssig.

Zilk
quelle

Antworten:

11

Es ist eine Einschränkung des DBMS - soweit ich weiß in allen. Und das nicht nur beim Hinzufügen einer Spalte, sondern auch beim Neuanordnen von Spalten. Wenn wir eine UNIQUEEinschränkung haben (a1, a2), können wir keine hinzufügen FOREIGN KEY, es REFERENCES (a2, a1)sei denn , es gibt eine eindeutige Einschränkung für diese (a2, a1), die im Wesentlichen redundant ist.

Es wäre nicht besonders schwierig, dies als Feature hinzuzufügen:

Wenn es eine UNIQUEBeschränkung auf (a), dann ist jede (a, b, c, ..., z)oder (b,c, ...a, ...z)Kombination ist ebenfalls gewährleistet UNIQUE.

oder die Verallgemeinerung:

Wenn es eine UNIQUEEinschränkung gibt, ist auch (a1, a2, ..., aN)jede (a1, a2, ..., aN, b1, b2, ..., bM)Kombination oder Umlagerung garantiert UNIQUE.

Es scheint, dass es nicht gefragt wurde oder nicht als hoch genug eingestuft wurde, um implementiert zu werden.

Sie können jederzeit - im jeweiligen Kanal - eine Anfrage für die zu implementierende Funktion stellen. Oder implementieren Sie es sogar selbst, wenn das DBMS Open Source ist, wie Postgres.

ypercubeᵀᴹ
quelle
Ich bin mir nicht sicher, ob es so einfach wäre. Was ist mit Teilindizes oder NULL-Werten? etc .. NULL könnte immer noch gut funktionieren, wenn Sie zufrieden sind NULL != NULL. Wie auch immer .. :)
Joishi Bodio
@ JoishiBodio Ich glaube nicht, dass Nullen ein Problem sind. EINZIGARTIGE Einschränkungen können auch definierte oder nullfähige Spalten sein. Standardmäßig wird die Einschränkung übergeben und die Zeile akzeptiert, wenn eine Spalte NULL enthält.
Ypercubeᵀᴹ
Wenn jedoch a1, a2, ... aN nicht nullbar sind und b1, b2, bM, können Probleme auftreten. Aber die Funktion könnte sicherlich für nicht nullfähige Spalten implementiert werden. Was wahrscheinlich besorgniserregend ist, sind die Auswirkungen auf die Effizienz.
Ypercubeᵀᴹ
Ich weiß, UNIQUE INDEXwo sich Spalten befinden NULLABLE. Deshalb habe ich es erwähnt. :) Aber ich stimme zu - für den Fall, dass es keine NULL-Werte gibt (und auch keinen Teilindex), ist dies wahrscheinlich ziemlich einfach.
Joishi Bodio
5

Fremdschlüssel im Allgemeinen (nicht nur zusammengesetzt) ​​MÜSSEN auf einen EINZIGARTIGEN SCHLÜSSEL in einer anderen Tabelle verweisen. Andernfalls würde es keine relationale Datenintegrität geben.

Dies ist eine Beschwerde, weil Sie zwar einen eindeutigen Schlüssel für (id) haben, aber keinen eindeutigen Schlüssel für (id, num). Für die Datenbank ist das Paar (id, num) also nicht GARANTIERT, einzigartig zu sein. Wir Menschen können herausfinden, dass es einzigartig sein wird, aber ich bin sicher, dass es eine Menge zusätzlichen Code geben würde, den sie hinzufügen müssten, um Postgres klug genug zu machen, um zu sehen, dass "oh hey ... id soll einzigartig sein." , also id, num sollte auch eindeutig sein "..

Ich wäre sehr überrascht, wenn sie diesen Code hinzufügen würden, wenn Sie lediglich einen weiteren eindeutigen Index für die beiden Spalten erstellen müssten, um das Problem zu beheben.

Um ganz klar zu sein, der Code, den sie hinzufügen müssten, wäre nicht nur dieser einfache Fall ... er müsste alle Fälle behandeln, auch solche, bei denen sich der Fremdschlüssel in mehr als 4 Spalten befindet usw. Ich bin sicher Die Logik wäre ziemlich komplex.

Joishi Bodio
quelle