PostgreSQL массив элементов, каждый из которых является внешним ключом

88

Я пытаюсь создать БД для своего приложения, и я бы хотел найти лучший способ сделать это - создать связь «один ко многим» между моими Usersи Itemsтаблицами.

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

Если PostgreSQL может это сделать, сообщите мне! Если нет, я просто выберу свой третий маршрут за столом.

Зак
источник
3
Для добавления этой функции в Postgres были выпущены патчи, см. Blog.2ndquadrant.com/… (2012) и postgresql.org/message-id/… (2017). Они еще не приняты, но, надеюсь, однажды.
Саймон Киссане

Ответы:

71

Нет, это невозможно.

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

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

Патрик
источник
3
Вы можете определить триггер ограничения, который будет это проверять. Но я не уверен, что он работает надежно во всех случаях.
a_horse_with_no_name
@a_horse_with_no_name: не могли бы вы привести пример reliably in all cases? Вы имеете в виду, что иногда триггер может не сработать? Благодарю.
Luan Huynh
1
@LuanHuynh: Я не помню (технических) деталей, но в последний раз, когда это обсуждалось в списке рассылки, кто-то упомянул, что соответствующий триггер ограничения может не улавливать все случаи - но это может больше не соответствовать действительности
a_horse_with_no_name
Спасибо, я думаю, я просто сделаю для них таблицу отношений
Зак
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 09
36
позор, похоже, его не включили :(
Teocali
11
2020, все еще не поддерживается: postgresql.org/docs/13/unsupported-features-sql-standard.html
M Imam Pratama