外键引用的表是否可以依赖于另一个字段的内容?

时间:2013-12-02 11:31:05

标签: sql sql-server foreign-keys

暂时搁置这是否是一个好主意的理智,我想知道是否有可能建立一个链接到两个以上表并且仍然能够强制执行参照完整性的字段?< / p>

e.g。我希望能够创建这样的外键定义:

create table TestTable
(
    Id int identity not null primary key,
    SourceId int not null,
    SourceTable varchar(100) not null
    /* some other common data goes here */

    constraint FK_TestTable_TableA foreign key (SourceId) references TableA(Id) when TestTable(SourceTable) = 'TableA'
    constraint FK_TestTable_TableB foreign key (SourceId) references TableB(Id) when TestTable(SourceTable) = 'TableB'
)

是否存在实现这种行为的模式,或者如果我沿着这条路走下去,我只是注定了一种缺乏参照完整性的悄悄恐怖?

1 个答案:

答案 0 :(得分:1)

不,如果没有@ Damien的

之类的解决方法,这是不可能的

另一种解决方法是使用触发器来检查完整性。

以下是INSTEAD OF触发器实现 - SqlFiddle here

CREATE TRIGGER t_TestTable ON TestTable INSTEAD OF INSERT
AS
    BEGIN
        SET NOCOUNT ON;
        INSERT INTO TestTable(SourceID, SourceTable)
            SELECT i.SourceID, i.SourceTable --, + i.Other field values
            FROM INSERTED i
                WHERE (i.SourceTable = 'TableA' AND EXISTS (SELECT * FROM TableA where ID = i.SourceID))
                OR (i.SourceTable = 'TableB' AND EXISTS (SELECT * FROM TableB where ID = i.SourceID));
        -- IF @@ROWCOUNT = 0 THROW /  RAISERROR ?
    END;
GO

您还需要在UPDATES上涵盖TestTable,并在UPDATES / DELETES上涵盖TableATableB,以及确定在发生FK违规事件时该怎么做(可能因为我做的事情而忽略了数据不是一个好策略)

更好的设计IMO不是重新发明轮子,而是使用表继承 - 例如make TableATableB继承自公共基本祖先表,该表具有两个表共有的唯一主键(并将SourceTable`表类型限定符添加到基表)。这将允许直接RI。