Условный внешний ключ в SQL - PullRequest
10 голосов
/ 23 декабря 2010

у меня есть одна таблица, называемая PartyChannel, имеющая следующие столбцы

 ID, ChannelID, ChannelType

ChannelID хранит MailID или PhoneID или EmailID в зависимости от ChannelType.

так как я могу создать внешний ключ между PartyChannel и всеми тремя таблицами (Mail, Email и Phone) в зависимости от channelType.

Ответы [ 3 ]

13 голосов
/ 23 декабря 2010

Вы можете использовать PERSISTED COMPUTED столбцы с оператором case, но в итоге он ничего не покупает, кроме накладных расходов.

Лучшим решением было бы смоделировать их как три различных значения для начала.

CREATE TABLE Mails (MailID INTEGER PRIMARY KEY)
CREATE TABLE Phones (PhoneID INTEGER PRIMARY KEY)
CREATE TABLE Emails (EmailID INTEGER PRIMARY KEY)

CREATE TABLE PartyChannel (
  ID INTEGER NOT NULL
  , ChannelID INTEGER NOT NULL
  , ChannelType CHAR(1) NOT NULL
  , MailID AS (CASE WHEN [ChannelType] = 'M' THEN [ChannelID] ELSE NULL END) PERSISTED REFERENCES Mails (MailID)
  , PhoneID AS  (CASE WHEN [ChannelType] = 'P' THEN [ChannelID] ELSE NULL END) PERSISTED REFERENCES Phones (PhoneID)
  , EmailID AS  (CASE WHEN [ChannelType] = 'E' THEN [ChannelID] ELSE NULL END) PERSISTED REFERENCES Emails (EmailID)
)

Отказ от ответственности

только потому, что вы можете, не означает, что вы должны.

4 голосов
/ 23 декабря 2010

Подтип Email, Mail, Phone к Channel.

alt text

4 голосов
/ 23 декабря 2010

AFAIK, вы не можете сделать это со стандартными внешними ключами.Однако вы можете реализовать что-то, что поможет обеспечить целостность данных с помощью триггеров.По сути, триггер будет проверять наличие «внешнего ключа» в ссылочной таблице - значение, которое должно присутствовать - всякий раз, когда происходит вставка или обновление в ссылочной таблице.Аналогичным образом, удаление из ссылочной таблицы может иметь триггер, который проверяет записи в ссылочной таблице, в которых используется удаляемый ключ.

Обновление: хотя я получил право на "ответ", я согласен с оставленным комментарием@oneday, когда это на самом деле проблема, вызванная дизайном, которая, вероятно, заставит вас пересмотреть свой дизайн.То есть у вас должно быть три разных столбца, а не один столбец, ссылающийся на три таблицы.Вы просто оставите два других столбца пустыми при заполнении одного, что, в свою очередь, позволит вам использовать стандартные внешние ключи.Любое беспокойство, что это "использовало бы слишком много места", глупо;это серьезный случай преждевременной оптимизации - это просто не имеет значения.

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