同一个表的2个外键可能会导致循环或多个级联路径

时间:2013-12-24 12:26:37

标签: sql sql-server sql-server-2008-r2 foreign-keys

圣诞快乐,

我正在寻找替代数据库设计以避免此ULTRA SAFE错误:

在表'%2'上引入FOREIGN KEY约束'%1'可能会导致循环或多个级联路径。指定ON DELETE NO ACTION或ON UPDATE NO ACTION,或修改其他FOREIGN KEY约束。

当同一个表的2个字段指向相同的FK时。例如:

People: {Id, Name, Age, Gender}

FamilyRelative: {PersonId, FamiliarId, Relationship}
            FK: FamilyRelative.PersonId ->People.Id ON DELETE CASCADE ON UPDATE CASCADE
            FK: FamilyRelative.FamiliarId->People.Id ON DELETE CASCADE ON UPDATE CASCADE

在第二个FK上引发错误。

PS:我在SQL Server 2008R2中测试它

2 个答案:

答案 0 :(得分:2)

您可以删除FamilyRelative.FamiliarId上的DELETE CASCADE操作

然后当你想先删除人物记录时

DELETE FROM FamilyRelative 
WHERE FamiliarId = @PeopleId

然后你

DELETE FROM People
WHERE Id = @PeopleId

最后一次删除将使用CASCADE规则处理FamilyRelative.PeopleId = @PeopleId的剩余FamilyRelative记录

答案 1 :(得分:2)

您可以在INSTEAD OF触发器中处理此问题,因此当您尝试从dbo.People中删除时,可以先在dbo.FamilyRelation上执行必要的删除,以避免任何完整性错误:

CREATE TRIGGER dbo.People_Delete ON dbo.People
INSTEAD OF DELETE
AS
BEGIN

    -- PERFORM THE DELETES ON FAMILY RELATIVE
    DELETE  dbo.FamilyRelative
    FROM    dbo.FamilyRelative fr
            INNER JOIN deleted d
                ON d.ID IN (fr.PersonID, fr.FamiliarID);

    -- PERFORM THE DELETES ON PEOPLE
    DELETE  dbo.People
    WHERE   ID IN (SELECT d.ID FROM deleted d);

END
GO

<强> Example on SQL Fiddle

我不知道你将如何处理ON UPDATE CASCADE,因为当您更新主键时,您将失去触发器中已插入表和已删除表之间的链接。