PostgreSQL-Array von Elementen, die jeweils ein Fremdschlüssel sind

83

Ich versuche, eine Datenbank für meine App zu erstellen, und ich möchte den besten Weg finden, eine Eins-zu-Viele-Beziehung zwischen meiner Usersund meinen ItemsTabellen herzustellen.

Ich weiß , ich kann einen dritten Tisch machen, ReviewedItemsund haben die Säulen sein , UserID und eine ItemID, aber ich würde gerne wissen , ob es möglich ist , in eine Spalte zu machen Users, lassen Sie uns sagen reviewedItems, das ist eine ganze Zahl Array mit Fremdschlüssel zu , Itemsdass das Userhat überprüft.

Wenn PostgreSQL dies kann, lassen Sie es mich bitte wissen! Wenn nicht, gehe ich einfach meine dritte Tischroute entlang.

Zach
quelle
3
Es gab Patches, um diese Funktion zu Postgres hinzuzufügen, siehe blog.2ndquadrant.com/… (2012) und postgresql.org/message-id/… (2017). Sie wurden noch nicht akzeptiert, aber hoffentlich eines Tages.
Simon Kissane

Antworten:

68

Nein das ist nicht möglich.

PostgreSQL ist ein relationales DBMS, das am effizientesten mit ordnungsgemäß normalisierten Datenmodellen arbeitet. Arrays sind - per Definition - geordnete Mengen - keine relationalen Datenstrukturen, und der SQL-Standard unterstützt daher nicht die Definition von Fremdschlüsseln für Array-Elemente und PostgreSQL auch nicht.

Sie können jedoch eine einwandfreie Datenbank mit Array-Elementen erstellen, die mit Primärschlüsseln in anderen Tabellen verknüpft sind. Diese Array-Elemente können jedoch nicht als Fremdschlüssel deklariert werden, und das DBMS behält daher keine referenzielle Integrität bei.

Patrick
quelle
3
Sie können einen Einschränkungsauslöser definieren, der dies überprüft. Ich bin mir aber nicht sicher, ob es in allen Fällen zuverlässig funktioniert.
a_horse_with_no_name
@a_horse_with_no_name: Könnten Sie ein Beispiel geben reliably in all cases? Du meinst manchmal kann der Trigger fehlschlagen? Vielen Dank.
Luan Huynh
1
@LuanHuynh: Ich erinnere mich nicht an die (technischen) Details, aber als dies das letzte Mal auf der Mailingliste besprochen wurde, erwähnte jemand, dass ein entsprechender Einschränkungsauslöser möglicherweise nicht alle Fälle
abfängt
Danke, ich denke, ich mache nur eine Beziehungstabelle für sie
Zach
1
@a_horse_with_no_name können Sie eine Antwort mit einem Beispiel für eine solche Einschränkung posten?
OrangeDog
65

Möglicherweise ist dies bald möglich: https://commitfest.postgresql.org/17/1252/ - Mark Rofail hat hervorragende Arbeit an diesem Patch geleistet!

Der Patch wird (sobald er abgeschlossen ist) zulassen

CREATE TABLE PKTABLEFORARRAY (
    ptest1 float8 PRIMARY KEY,
    ptest2 text
);
CREATE TABLE FKTABLEFORARRAY (
    ftest1 int[],
    FOREIGN KEY (EACH ELEMENT OF ftest1) REFERENCES PKTABLEFORARRAY,
    ftest2 int
);

Derzeit benötigt der Autor jedoch Hilfe, um den Patch neu zu starten (über meine eigenen Fähigkeiten hinaus). Wenn Sie dies lesen und Postgres-Interna kennen, helfen Sie bitte, wenn Sie können.

Jarym
quelle
8
sehr heiß in der Tat ...CREATE TABLE FKTABLEFORARRAY ( ftest1 int[], FOREIGN KEY (EACH ELEMENT OF ftest1) REFERENCES PKTABLEFORARRAY, ftest2 int )
Victor
1
Der Patch wartet darauf, dass der Autor nachverfolgt wird. Bis die Funktion verfügbar ist, müssen Sie den Trigger verwenden, um die Integrität zu überprüfen, die möglicherweise langsam ist.
Yoonghm
34
Schade, es scheint nicht enthalten gewesen zu sein :(
Teocali
6
2020, immer noch nicht unterstützt: postgresql.org/docs/13/unsupported-features-sql-standard.html
M Imam Pratama