Нужны советы по иностранным ключам для альтернативных таблиц - PullRequest
1 голос
/ 10 февраля 2012

У меня есть таблица с именем Message.Каждое сообщение может быть связано с таблицей Invoice или таблицей Rfp, но не с обоими.Я борюсь с лучшим способом реализации этого:

  1. Один из подходов состоит в том, чтобы таблица Message имела внешние ключи для таблиц Invoice и Rfp.Один FK будет действительным, а другой должен быть NULL.(Наследование за одним столом.) Но это кажется довольно неловким.В дополнение к неиспользуемому столбцу мне нужно найти способы предотвращения случаев, когда FK либо оба используются, либо оба имеют значение NULL.И это нужно будет повторять для каждого отдельного сообщения.

  2. Другой подход заключается в создании объединяющей таблицы.В этом случае моя таблица Message будет иметь FK для таблицы присоединения, а таблицы Invoice и Rfp также будут иметь FK для таблицы присоединения.Однако проблема здесь заключается в том, что, учитывая ссылку на присоединяющуюся таблицу, неудобно находить связанную таблицу Invoice или Rfp, потому что я не знаю, где находится FK.Итак, здесь мне нужно прибегнуть к другим шагам, чтобы узнать, как найти связанную таблицу, например, добавить столбец, чтобы указать, к какой таблице относится, для которой сложно создать ограничение.

  3. Наконец, я мог бы создать два типа Message таблиц.Это решает проблемы, описанные выше, но это вызывает проблемы для нашего приложения, потому что у нас есть логика в местах, где нужно добавлять сообщения, не зная, какого они типа.(Мы можем иметь только FK для соответствующей таблицы.)

Может кто-нибудь предложить несколько советов здесь.Ни один из этих способов не идеален, но, возможно, есть аспекты, которые я не учел при выборе между ними.Или, возможно, есть лучший подход в целом.

1 Ответ

2 голосов
/ 10 февраля 2012

В варианте 1 можно использовать проверочное ограничение, чтобы убедиться, что установлен только один FK ...

CREATE TABLE [dbo].[Rfp] (Id int IDENTITY(1,1) NOT NULL, PRIMARY KEY CLUSTERED (Id))
CREATE TABLE [dbo].[Invoice] (Id int IDENTITY(1,1) NOT NULL, PRIMARY KEY CLUSTERED (Id))

CREATE TABLE dbo.[Message] (Id int IDENTITY(1,1) NOT NULL, RfpId int, InvoiceId  int, 
   PRIMARY KEY CLUSTERED (Id),
   FOREIGN KEY (RfpId) REFERENCES [dbo].[Rfp] (Id),
   FOREIGN KEY (InvoiceId) REFERENCES [dbo].[Invoice] (Id),
   )

ALTER TABLE dbo.[Message] 
   ADD CONSTRAINT CK_FK CHECK (   (RfpId IS NULL AND InvoiceId IS NOT NULL) 
                                     OR (RfpId IS NOT NULL AND InvoiceId IS NULL));
...