Postgres наследование и внешние ключи или альтернатива - PullRequest
0 голосов
/ 24 октября 2019

Я использую наследование postgres в своем проекте.

Например: у меня есть таблица "user" и "user_child", которые наследуются от таблицы "user".

У меня есть две записи: первая запись создается в пользовательской таблице, вторая запись создается в таблице user_child, а запись из user_child частично сохраняется у пользователя из-за наследования.

У меня также есть третьятаблица - «домашняя работа», в ней есть столбец assign_user - внешний ключ для пользовательской таблицы.

Когда я добавляю запись в таблицу «task», где поле assign_user ссылается на запись из user таблица, тогда все в порядке, но когда я выбираю запись из таблицы user_child, я получаю сообщение об ошибке:

ОШИБКА: вставка или обновление таблицы «домашняя работа» нарушает ограничение внешнего ключа"fk-homework-assign_user" "

ДЕТАЛИ: Ключ (assign_user) = (3) отсутствует в таблице" пользователь ".

Удаление ограничения помогает решить мою проблему,но я хочу использовать каскадное удаление и обновлениетинг записи. Можете ли вы сказать мне, какие есть альтернативы или что я делаю неправильно?

1 Ответ

0 голосов
/ 24 октября 2019

Наследование PostgreSQL работает не совсем так, как вы ожидаете. Да, вы можете видеть информацию из дочерних таблиц при запросе родительской таблицы, но это не распространяется на отношения внешнего ключа. Строка «принадлежит» ребенку, а не родителю. Ссылка на внешний ключ не касается дочернего элемента.

Как правило, плохая идея использовать наследование в PostgreSQL, за исключением особых случаев, таких как создание временной системы или соблюдение соглашений об именах (например, интерфейсы в ООП, а не наследование состояний).

Наследование PostgreSQL может быть очень мощным, но, на мой взгляд, оно обычно используется слишком часто. Уже существует решение (и совместимое с несколькими базами данных), которое более точно следует традиционной реляционной модели.

Лучшая модель, которая будет выполнять то, что вам кажется, выглядит следующим образом:

CREATE TABLE "user" (
  user_id serial PRIMARY KEY, -- Or UUID or generated column in newer versions
  -- other fields that all "children" should share
);

CREATE TABLE user_child (
  user_id integer NOT NULL
    REFERENCES "user" (user_id) ON UPDATE CASCADE ON DELETE CASCADE,
  -- other fields specific to the child
);

CREATE TABLE homework (
  homework_id serial PRIMARY KEY,
  user_id integer NOT NULL
    REFERENCES "user" (user_id) ON UPDATE CASCADE ON DELETE RESTRICT,
  -- other fields specific to homework
);

Эквивалент вашего запроса для user_child:

SELECT u.user_id
FROM "user" AS u
  INNER JOIN user_child AS uc;

И для запроса пользователя родитель и потомок по-прежнему будут

SELECT u.user_id
FROM "user" AS u;

Добавление внутреннего объединения довольно тривиально и может быть скрытоза взглядом. Теперь ссылка на внешний ключ для пользователя будет работать правильно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...