Tablica PostgreSQL zawierająca elementy, z których każdy jest kluczem obcym

88

Próbuję utworzyć bazę danych dla mojej aplikacji i jedną rzeczą, którą chciałbym znaleźć najlepszym sposobem na zrobienie, jest utworzenie relacji jeden do wielu między moimi Usersa Itemstabelami.

Wiem, że mogę zrobić trzecią tabelę ReviewedItemsi mają kolumny być Userid i Itemid, ale chciałbym wiedzieć, czy to możliwe, aby kolumny w Users, powiedzmy reviewedItems, która jest tablicą całkowitą zawierający klucze obce na Itemsktóre Userdokonała przeglądu.

Jeśli PostgreSQL może to zrobić, daj mi znać! Jeśli nie, po prostu zejdę po mojej trzeciej trasie tabeli.

Zach
źródło
3
Były łaty dodające tę funkcję do Postgres, patrz blog.2ndquadrant.com/… (2012) i postgresql.org/message-id/… (2017). Nie zostały jeszcze zaakceptowane, ale mam nadzieję, że pewnego dnia.
Simon Kissane,

Odpowiedzi:

71

Nie, to niemożliwe.

PostgreSQL to relacyjny DBMS, działający najskuteczniej na odpowiednio znormalizowanych modelach danych. Tablice to - z definicji są to uporządkowane zbiory - nie relacyjne struktury danych, dlatego standard SQL nie obsługuje definiowania kluczy obcych w elementach tablic, podobnie jak PostgreSQL.

Możesz jednak zbudować doskonałą bazę danych z elementami tablic łączącymi się z kluczami podstawowymi w innych tabelach. Jednak te elementy tablicy nie mogą być zadeklarowane jako klucze obce i dlatego DBMS nie będzie zachowywał integralności referencyjnej.

Patrick
źródło
3
Państwo może zdefiniować wyzwalacz wiązania, które sprawdzenia tego. Ale nie jestem pewien, czy działa niezawodnie we wszystkich przypadkach.
a_horse_with_no_name
@a_horse_with_no_name: czy możesz podać przykład na temat reliably in all cases? Masz na myśli, że czasami wyzwalacz może się nie udać? Dzięki.
Luan Huynh
1
@LuanHuynh: Nie pamiętam szczegółów (technicznych), ale ostatnim razem, gdy omawiano to na liście mailingowej, ktoś wspomniał, że odpowiedni wyzwalacz ograniczenia może nie wychwycić wszystkich przypadków - ale to może już nie być prawdą
a_horse_with_no_name
Dzięki, myślę, że po prostu zrobię dla nich tabelę relacji
Zach
1
@a_horse_with_no_name czy możesz opublikować odpowiedź z przykładem takiego ograniczenia?
OrangeDog
69

Wkrótce będzie to możliwe: https://commitfest.postgresql.org/17/1252/ - Mark Rofail wykonał świetną robotę nad tą poprawką!

Łatka pozwoli (po zakończeniu)

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

Jednak autor potrzebuje obecnie pomocy w przebudowaniu łatki (poza moimi własnymi możliwościami), więc każdy, kto to czyta, kto zna wewnętrzne elementy Postgresa, powinien pomóc, jeśli możesz.

Jarym
źródło
8
naprawdę bardzo GORĄCY ...CREATE TABLE FKTABLEFORARRAY ( ftest1 int[], FOREIGN KEY (EACH ELEMENT OF ftest1) REFERENCES PKTABLEFORARRAY, ftest2 int )
Victor,
1
Łatka czeka na autora na dalsze działania. Dopóki ta funkcja nie będzie dostępna, będziesz musiał użyć wyzwalacza, aby sprawdzić integralność, co może być powolne.
yoonghm
36
szkoda, wydaje się, że nie zostało uwzględnione :(
Teocali
10
2020, nadal nieobsługiwany: postgresql.org/docs/13/unsupported-features-sql-standard.html
M Imam Pratama