Nicht eindeutiger mehrspaltiger Fremdschlüssel

7

Ich habe eine "Kommentar" -Tabelle, die eine Konversation zu einem Thema wie folgt modelliert:

id serial  
topic_id integer  
parent_comment_id integer
body text

Jeder Kommentar hat also einen Verweis auf sein Thema UND schließlich seinen übergeordneten Kommentar (wenn es nicht der erste Kommentar zum Thema ist).
Ich möchte eine Einschränkung hinzufügen, die das Hinzufügen von Zeilen mit nicht übereinstimmendem Thema / übergeordnetem Element verhindert (z. B. durch Verweisen auf ein Thema, das nicht den erforderlichen Kommentar enthält, oder umgekehrt auf einen Kommentar, der auf das falsche Thema verweist).
Ist das möglich? Ist ein Auslöser erforderlich?

(Für die Aufzeichnung habe ich versucht

ALTER TABLE comments ADD FOREIGN KEY (parent_comment_id, topic_id)
                 REFERENCES comments (id, topic_id)

aber es beschwert sich, dass there is no unique constraint matching given keys for referenced table "comments")

Joril
quelle
Gibt es einen Primärschlüssel in der Tabelle "Kommentare"?
SQLRockstar
Ja, sorry, es ist die ID
Joril
1
Versuchen Sie, einen eindeutigen Index zu erstellen. How_you_want_to_name_this_index für Kommentare (id, topic_id). bevor Sie den Befehl alter table ausgeben, fügen Sie den Fremdschlüssel hinzu.
JP
Oder fügen Sie einfach die eindeutige Zeile (id, topic_id) in Ihren Befehl "Tabelle erstellen" für Kommentare ein.
JP

Antworten:

4

Sie müssen für beide (ID, Topic_ID) einen Superschlüssel (eindeutiger Index / Einschränkung) hinzufügen. Dies gibt Ihnen die "Ziel" -Eindeutigkeit, um Ihren Fremdschlüssel zu erstellen. Dies wirkt in diesem Fall wie eine CHECK-Einschränkung.

ALTER TABLE comments ADD 
    FOREIGN KEY (parent_comment_id, topic_id) REFERENCES comments (id, topic_id)

Hinweis: Die ID bleibt der Primärschlüssel, um das Modell beizubehalten. Selbst wenn id seriell ist, wäre es aus Modellierungssicht falsch, die PK in (id, topic_id) zu ändern.

gbn
quelle
1
Das ist technisch korrekt, aber logischerweise ist dies keine neue Einschränkung. Wenn der Primärschlüssel für id angegeben ist, ist er immer erfüllt. Dh es ist nur eine Behinderung der Implementierung des DBMS.
Bernd_k
@bernd_k: Deshalb habe ich "Super Key" gesagt. Es entkoppelt auch die tatsächliche PK vom Superkey / FK.
gbn
1

Versuchen

ALTER TABLE comments ADD FOREIGN KEY (parent_comment_id, topic_id)
    REFERENCES comments (id)

Wenn Sie möchten, dass dies funktioniert:

ALTER TABLE comments ADD FOREIGN KEY (parent_comment_id, topic_id)
    REFERENCES comments (id, topic_id)

Dann glaube ich, dass Sie Ihre PK so ändern müssen, dass sie sich sowohl in der Spalte id als auch in der Spalte topic_id befindet.

Ich denke auch, dass dieser Link hilft zu erklären, was Sie brauchen: http://www.postgresql.org/docs/8.1/static/ddl-constraints.html

SQLRockstar
quelle
1
Der erste Befehl gibt mir number of referencing and referenced columns for foreign key disagree: / Ich denke, das Problem mit meinem Befehl ist, dass es mehrere Zeilen mit übereinstimmenden Eltern + Thema geben könnte
Joril
OK, können Sie den Primärschlüssel so ändern, dass er zwei Spalten enthält? dann sollte dein ursprünglicher Befehl funktionieren, glaube ich.
SQLRockstar