«Многократный» внешний ключ - PullRequest
0 голосов
/ 16 апреля 2020

У меня есть таблицы:

  • МУЗЫКАНТЫ (musician_id, ...)
  • ПРОГРАММИСТЫ (programmer_id, ...)
  • COPS (cop_id, .. .)

Тогда у меня будет специфика c таблица

  • RICH_PEOPLE (rich_person_id, ...)

где rich_person_id равно musician_id, programmer_id или cop_id. (Предположим, что все musician_id s, programmer_id s, cop_id s отличаются .)

Можно ли напрямую создать внешний ключ на поле rich_person_id ?

PS Я бы хотел, чтобы база данных

  • гарантировала наличие записи MUSICIANS, PROGRAMMERS или COPS с тем же идентификатором, что и у нового RICH_PEOPLE запись rich_person_id перед вставкой ее в RICH_PEOPLE
  • удаление из MUSICIANS, PROGRAMMERS или COPS завершится неудачно (или потребует каскадного удаления), если есть RICH_PEOPLE запись с тем же идентификатором

PPS Мне бы не хотелось

  • создание дополнительной таблицы типа POSSIBLY_RICH_PEOPLE с единственным полем possibly_rich_person_id
  • создание триггеров

Ответы [ 2 ]

0 голосов
/ 16 апреля 2020

Вы делаете это несколько иначе:

  • Создайте таблицу people с person_id.
  • Используйте этот ключ в качестве первичного ключа ( и внешний ключ) для каждой из ваших таблиц занятий.
  • Используйте этот ключ в качестве первичного ключа ( и внешний ключ) для вашей таблицы rich_people.

Postgres поддерживает концепцию, называемую "наследование" , которая упрощает конструкцию этого типа. Ваши таблицы занятий могут «наследовать» столбцы от people.

0 голосов
/ 16 апреля 2020

Вы можете создать три внешних ключа, допускающих значение NULL, по одному для каждой внешней таблицы. Затем используйте ограничение CHECK, чтобы гарантировать, что только одно значение не является нулевым в любой момент времени.

Например:

create table rich_people (
  rich_person_id int primary key not null,
  musician_id int references musicians (musician_id),
  programmer_id int references programmers (programmer_id),
  cop_id int references cops (cop_id),
  check (musician_id is not null and programmer_id is null and cop_id is null
      or musician_id is null and programmer_id is not null and cop_id is null
      or musician_id is null and programmer_id is null and cop_id is not null)
);

Таким образом, ссылочная целостность будет обеспечиваться всегда. Для удаления потребуется каскадное удаление или другая стратегия для сохранения целостности данных.

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