Внешние ключи + наследование таблиц в PostgreSQL?

У меня есть три таблицы: organization, organization_teams и org_users. Здесь organization_teams наследуется от organization. Предположим, что если запись добавлена ​​в organizations_teams, она получит таблицу organization id как значение для столбца id в organization_teams.

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

insert or update on table "org_users" violates foreign key constraint "org_users_organizations"
DETAIL:  Key (org_id)=(12) is not present in table "organizations"

Почему?

Ответы

Ответ 1

Это в руководстве пользователя.

Короткий вариант: вы можете использовать внешние ключи или наследование таблицы, но не оба. Это по своей сути невозможно, просто так сложно технически реализовать уникальные индексы, которые быстро и надежно охватывают унаследованные таблицы в PostgreSQL. Без этого у вас не может быть полезного внешнего ключа. Никто не успешно реализовал его достаточно хорошо, чтобы патч добавил поддержку, которая будет принята в PostgreSQL.

Внешний ключ может указывать на таблицу, которая является частью иерархии наследования, но она точно найдет строки в этой таблице. Не в каких-либо родительских или дочерних таблицах. Чтобы увидеть, какие строки видит внешний ключ, выполните SELECT * FROM ONLY thetable. Ключевое слово ONLY означает "игнорирование наследования" и то, что будет искать внешний ключ.

Ответ 2

Единственное обходное решение, которое я нашел:

  • создать функцию, возвращающую триггер для проверки существования некоторого id в унаследованной таблице
  • создать триггер ограничения вместо FK

Ответ 3

Полностью согласен с @Craig Ringer, мы не можем использовать внешние ключи вместе с наследованием.

Но если мы уверены, что собираемся вставить правильные данные и хотим использовать внешний ключ в org_users, мы можем сделать одну вещь.

Мы можем создать дочернюю таблицу org_users, скажем org_users_child (без внешнего ключа), как показано ниже

CREATE TABLE org_users_child () INHERITS (org_users);

Теперь мы можем вставить данные в эту дочернюю таблицу.

Теперь, если мы запросим таблицу org_users, мы сможем найти желаемые результаты.