我有一个名为PartyChannel的表,其中包含以下列
ID, ChannelID, ChannelType
ChannelID
存储MailID
或PhoneID
或EmailID
,具体取决于ChannelType
。
那么如何在PartyChannel和所有三个表(邮件,电子邮件和电话)之间创建一个外键,具体取决于channelType。
答案 0 :(得分:10)
您可以将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)
)
<强>声明强>
只是因为你并不意味着你应该这样做。
答案 1 :(得分:4)
AFAIK,您无法使用标准外键执行此操作。但是,您可以通过使用触发器实现某些操作来帮助确保数据完整性。本质上,只要引用表上有插入或更新,触发器就会检查引用表上是否存在“外键” - 必须存在的值。同样,从引用的表中删除可能会有一个触发器,用于检查使用要删除的键的引用表上的记录。
更新:虽然我选择了“回答”,但我同意@onedaywhen留下的评论,这实际上是一个设计引起的问题,应该让你重新考虑你的设计。也就是说,您应该有三个不同的列,而不是一个引用三个表的列。当一个填充时,您只需将其他两列保留为null,这反过来会让您使用标准外键。任何担心这会“占用太多空间”都是愚蠢的;它代表了一个过早优化的严重情况 - 它并不重要。
答案 2 :(得分:4)
Email, Mail, Phone
的子类型Channel
。