Масив елементів PostgreSQL, кожен із яких є зовнішнім ключем


89

Я намагаюся створити БД для мого додатка, і одне, що я хотів би знайти найкращим способом, це створення взаємозв'язку "один до багатьох" між моїм Usersі Itemsтаблицями.

Я знаю , що може зробити третю таблицю, ReviewedItemsі є стовпці бути Userідентифікатором і Itemідентифікатор, але я хотів би знати , якщо це можливо зробити стовпець Users, скажімо reviewedItems, який являє собою масив цілих чисел , що містить зовнішні ключі , Itemsякі Userрозглянув.

Якщо PostgreSQL може це зробити, будь ласка, дайте мені знати! Якщо ні, я просто піду моїм третім столом.


3
Були виправлення для додавання цієї функції до Postgres, див. Blog.2ndquadrant.com/… (2012) та postgresql.org/message-id/… (2017). Їх ще не прийняли, але, сподіваюся, одного разу.
Simon Kissane

Відповіді:


71

Ні, це неможливо.

PostgreSQL - це реляційна СУБД, яка найбільш ефективно працює на правильно нормалізованих моделях даних. Масиви - за визначенням, це впорядковані набори - не реляційні структури даних, і, отже, стандарт SQL не підтримує визначення зовнішніх ключів для елементів масиву, як і PostgreSQL.

Однак ви можете створити абсолютно точну базу даних з елементами масиву, що посилаються на первинні ключі в інших таблицях. Однак ці елементи масиву не можна оголосити зовнішніми ключами, і тому СУБД не буде підтримувати цілісність посилань.


3
Ви можете визначити тригер обмеження, який перевіряв би це. Але я не впевнений, чи працює він надійно у всіх випадках.
a_horse_with_no_name

@a_horse_with_no_name: чи можете ви навести приклад про reliably in all cases? Ви маєте на увазі, що іноді тригер може бути невдалим? Дякую.
Luan Huynh

1
@LuanHuynh: Я не згадую (технічні) деталі, але востаннє це обговорювалось у списку розсилки, коли хтось згадував, що відповідний тригер обмеження може не
охоплювати

Дякую, мабуть, я просто складу для них таблицю стосунків
Зак

1
@a_horse_with_no_name чи можете ви опублікувати відповідь із прикладом такого обмеження?
OrangeDog

69

Можливо, незабаром це стане можливим: https://commitfest.postgresql.org/17/1252/ - Марк Рофайл провів чудову роботу над цим патчем!

Патч (після завершення) дозволить

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

Однак автору в даний час потрібна допомога щодо перебазування виправлення (за межами моїх власних можливостей), тому будь-хто, хто читає це, хто знає внутрішні матеріали Postgres, будь ласка, допоможіть, якщо зможете.


8
справді дуже ГАРЯЧЕ ...CREATE TABLE FKTABLEFORARRAY ( ftest1 int[], FOREIGN KEY (EACH ELEMENT OF ftest1) REFERENCES PKTABLEFORARRAY, ftest2 int )
Віктор,

1
Патч очікує від автора подальших дій. Поки функція не стане доступною, вам доведеться використовувати тригер для перевірки цілісності, яка може бути повільною.
yoonghm

36
ганьба, здається, не було включено :(
Теокалі

11
2020, досі не підтримується: postgresql.org/docs/13/unsupported-features-sql-standard.html
M Imam Pratama
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.