У меня есть несколько функций postgres, которые принимают ряд аргументов для записи в несколько таблиц.
fn_trade
(
_product_id BIGINT[],
_user_id BIGINT[],
_location_id BIGINT
)
Поскольку аргументы поступают от клиента или сервера Node.js, мне нужно проверить, что данные существуют (обрабатываются ограничениями FK, но не в случае BIGINT []), и мне нужно подтвердить, что отношения аргументов действительны. . Например, я должен проверить, что user и product существуют для location, а product принадлежит к user. Сложность этой проверки возрастает с увеличением количества аргументов. Я могу привести более 10 аргументов, и проверка их взаимосвязи будет сложной и дорогостоящей.
Я не знаю, упускаю ли я важную картину, пытаясь проверить аргументы функции. Это правильный подход? Есть ли лучший способ быть уверенным в взаимосвязях аргументов, чтобы заполненные данные всегда были ожидаемыми?
Возможный подход может заключаться в том, чтобы предсказать результат и проверить, записан ли результат после завершения записи (иначе откат)?
Postgres 9.6+
Обновлено: добавлен пример, чтобы прояснить вопрос
Таблицы:
location (id, name) -- e.g. 1, 'Canada'
user (id, name, location_id) -- e.g. 1, Jane, 1
product (id, name, user_id, location_id) -- e.g. 1, 'skates', 1, 1
trade (id, user_id[], product_id[]) -- e.g. 1, [1,2], [1,2,3,4]
Когда происходит сделка, мне нужно подтвердить, что предоставленные данные соответствуют данным в базе данных.
Например, я получаю:
fn_trade
(
[1,2,3,4],
[1,2],
1
)
Таким образом, торговля происходит для пользователей [1,2] на продукты [1,2,3,4] в Канаде. У пользователей могут быть элементы в разных местах, и пользователи могут перемещаться в разные места.
При вставке user_id[] и product_id[] в trade проверка отдельных идентификаторов не выполняется автоматически. Я не знаю, можно ли установить значения в массиве как FK, поэтому проверка здесь выполняется вручную. Мне нужно гарантировать, что все идентификаторы [1,2,3,4] существуют для продукта.
А как насчет отношений? Мне нужно проверить, что идентификаторы также принадлежат пользователям [1,2].
Принадлежать пользователю недостаточно. Товары должны находиться в том же месте, где происходит торговля.
Что касается пользователей, мне нужно знать, можно ли им торговать. Если они живут в разных местах (Канада против Тайваня), то торговля невозможна.
Поскольку данные клиента зависят от БД, а данные, передаваемые в fn_trade, могут быть ненадежными, как следует проверить отношение, чтобы доказать, что данные верны для наших пользователей, продуктов и отношений местоположения?
@klin Я думал, что FK проверяет только то, что ключ существует в таблице, а не то, что product принадлежит user, и они оба живут в location. Не удалось передать ошибочный аргумент, содержащий действительный FK? Я вставляю или обновляю product, не принадлежащий к user, а не тот location. Все идентификаторы существуют для таблиц, но не для правильных отношений.
Я снова прочитал вопрос и ваш комментарий и не уверен, что понял логику. Вроде стоит попробовать поставить Минимальный, полный и проверяемый пример.
@klin Я добавил пример, который, надеюсь, устранит некоторую двусмысленность из моего вопроса. Глядя на проблему, возможно, что хранение массивов может быть нежелательным. Мне все еще не хватает опыта, чтобы сказать.
Модель вашей базы данных не смоделирована должным образом для выполнения проверок FK, как указано @klin. Правильный способ имел бы одну строку для каждого пользователя / продукта в торговой таблице. Для значений массива нет проверки внешнего ключа. Вот лучшее объяснение: stackoverflow.com/questions/41054507/…
Если бы он был правильно смоделирован, вам даже не понадобилась бы функция.
@JorgeCampos Я мог бы в будущем провести рефакторинг схемы, но предлагаемые проверки ограничений в ссылке для массивов сразу же полезны. Нормализация схемы должна упростить проверку, но по-прежнему не может гарантировать, что переданные значения связаны. Предполагая, что я нормализовал продукты, я все равно могу передать продукт, который принадлежит кому-то другому. Чем больше у меня аргументов, тем больше проверка отношения.
Нет, если у вас есть ограничение между пользователем и продуктом, вы создаете таблицу для нормализации этого ограничения, и ваша сделка будет иметь FK для этой таблицы. Это все о нормализации. Опять же, если вы все сделаете правильно, вам не понадобится функция для проверки.


Внешние ключи были изобретены только для того, чтобы вам не приходилось вручную проверять эти отношения. Если внешние ключи неверны при вставке или обновлении строк, сервер вызовет исключение.