【问题标题】:2 foreign key to the same table may cause cycles or multiple cascade paths同一张表的2个外键可能会导致循环或多个级联路径
【发布时间】:2014-01-12 16:46:06
【问题描述】:

圣诞快乐,

我正在寻找一种替代数据库设计来避免这种 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 中测试它

【问题讨论】:

  • 你想达到什么目的?当您删除 People 记录时,您希望删除该 People.Id 的所有具有 Person.Id 或 FamiliarId = 的 FamilyRelative 记录?
  • @Vland,是的,这正是我想要实现的目标。
  • 我建议你从业务角度看问题。您遇到的情况是自我引用多对多的结果,这在商业上很奇怪。一个人属于多个家庭,一个家庭有很多人,不够详细,无法建模。
  • @EmmadKareem 如果您愿意,我们可以在生产环境中使用像 材料清单 这样不那么奇怪的示例作为组件列表:{FinishMaterialId, RawMaterialId, RawQuantity}。任何 ERP 都有一个这样的表!

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


【解决方案1】:

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

然后,当您想先删除人员记录时,您

DELETE FROM FamilyRelative 
WHERE FamiliarId = @PeopleId

然后你

DELETE FROM People
WHERE Id = @PeopleId

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

【讨论】:

  • 这就是我现在正在做的,但我想知道是否有任何设计替代方案。
  • 我觉得这个设计很完美。所有的人/亲戚都是人,所以他们应该留在你的 People 表中。我会保持良好的设计并保留引用并在我的删除查询和/或使用触发器中处理问题
【解决方案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,因为当您更新主键时,您会丢失触发器中插入和删除表之间的链接。

【讨论】:

    猜你喜欢
    • 2020-12-26
    • 2016-03-26
    • 2010-10-25
    • 2012-09-21
    • 2022-01-05
    相关资源
    最近更新 更多