SQL中的条件外键

Khu*_*aal 11 sql-server database-design sql-server-2008

我有一个名为PartyChannel的表,其中包含以下列

 ID, ChannelID, ChannelType
Run Code Online (Sandbox Code Playgroud)

ChannelID商店MailIDPhoneIDEmailID取决于ChannelType.

那么我如何在PartyChannel和所有三个表(邮件,电子邮件和电话)之间创建一个外键,具体取决于channelType.

Lie*_*ers 13

您可以将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)
)
Run Code Online (Sandbox Code Playgroud)

放弃

只因为你不能意味着你应该这样做.


Dam*_*vic 8

子类型Email, Mail, PhoneChannel.

替代文字


Mar*_*ham 4

AFAIK,你不能使用标准外键来做到这一点。但是,您可以通过使用触发器来实施一些措施来帮助确保数据完整性。本质上,每当引用表上有插入或更新时,触发器都会检查引用表上是否存在“外键”(必须存在的值)。类似地,从引用表中删除可能有一个触发器,用于检查引用表上使用被删除键的记录。

更新:虽然我直接寻找“答案”,但我同意@onedaywhen 留下的评论,这实际上是一个设计引起的问题,可能会让你重新考虑你的设计。也就是说,您应该拥有三个不同的列,而不是一列引用三个表。当其中一列被填充时,您只需将其他两列保留为空,这反过来又允许您使用标准外键。任何担心这会“占用太多空间”的想法都是愚蠢的。它代表了过早优化的严重情况 - 这并不重要。