【问题标题】:Trying to implement cascade deletes on link table with 2 FK relationships to parent尝试在具有 2 个与父级的 FK 关系的链接表上实现级联删除
【发布时间】:2014-05-19 21:51:03
【问题描述】:

我有 2 个代表的表

parent -

LibraryItem- Parent -< LibraryItemLink(StdLibraryItemId_Parent)
           - Child  -< LibraryItemLink(StdLibraryItemId_Child)

我想在 FK 上进行级联删除,以便如果从 LibraryItem 中删除父记录,则所有关联的 LibraryItemLink 记录都将被删除,并且如果任何子 libraryItem 记录被删除,同样适用。

添加约束的 T-SQL 是:

ALTER TABLE dbo.StdLibraryItemLink
ADD
  CONSTRAINT FK_StdLibraryItemLink_StdLibraryItem_Child FOREIGN KEY (StdLibraryItemId_Child) REFERENCES dbo.StdLibraryItem (Id) ON DELETE CASCADE,
  CONSTRAINT FK_StdLibraryItemLink_StdLibraryItem_Parent FOREIGN KEY (StdLibraryItemId_Parent) REFERENCES dbo.StdLibraryItem (Id) ON DELETE CASCADE
GO 

我得到的错误是:

Msg 1785, Level 16, State 0, Line 1
Introducing FOREIGN KEY constraint 'FK_StdLibraryItemLink_StdLibraryItem_Parent' on table 
'StdLibraryItemLink' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or 
ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.
Msg 1750, Level 16, State 0, Line 1
Could not create constraint. See previous errors.

我猜这是关键:

may cause cycles or multiple cascade paths

关于如何对两种关系实施级联删除的建议将不胜感激,因为它在逻辑上似乎是正确的,即父删除和子删除,两者都需要独立删除关联的链接记录。

提前致谢。

【问题讨论】:

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


    【解决方案1】:

    你的 FK 约束声明应该是

    ALTER TABLE dbo.StdLibraryItemLink
    ADD
      CONSTRAINT FK_StdLibraryItemLink_StdLibraryItem_Child FOREIGN KEY 
      (StdLibraryItemId_Child) REFERENCES dbo.StdLibraryItem (Id) ON DELETE CASCADE
    GO 
    

    编辑:

    是的,SQL Server 不允许这样做。而且想一想,你会发现它没有任何意义;因为即使您只有一个引用列,也会级联删除,并且子/派生表行将被删除。多列引用同一个表的同一列有什么意义(没有好处)?

    此外,如果允许的话;你会得到一个不想要的结果。为了证明这一点,我在MySQL 中尝试了相同的场景(供您参考,如果您想尝试,可以使用以下查询)。

    父表

    create table t(id int not null auto_increment primary key, `name` varchar(10));
    insert into t(`name`) values('heeli'),('holi'),('heelda'); 
    

    子表

    create table t1(id1 int,id2 int, col varchar(10),
    constraint fk1 foreign key (id1) references t(id) on delete cascade,
    constraint fk2 foreign key (id2) references t(id) on delete cascade); 
    
    insert into t1 values(1,1,'holi'),(2,2,'holi'),(2,3,'holi');
    
    select * from t1
    
     id1, id2, col
    '1', '1', 'holi'
    '2', '2', 'holi'
    '2', '3', 'holi'
    

    现在从 t 中删除一行

    delete from t where id = 2
    

    因为在t1 id1 和id2 都指向t id 列;第 2 行和第 3 行都将被删除,这在许多情况下是不希望出现的结果。

    select * from t1
    

    在父表中删除后t1中的结果数据

     id1, id2, col
    '1', '1', 'holi'
    

    【讨论】:

    • 谢谢。只有 2 个表,LibraryItem 和 LibraryItemLink。 FK“StdLibraryItemId_Child”引用了 LibraryItem 上的 Id,“StdLibraryItemId_Parent”也是如此,但我得到了循环错误。我也很困惑为什么添加一个额外的 ID 列引用回 LibraryItem 的 ID 会产生任何影响,因为这是其他 FK 所做的。此外,我在 LibraryItemLink 上有一个名为 ID 的 PK。我可能会误解您的综合答案,但我希望您能根据此评论中的信息进一步发表评论。谢谢
    • @SamJolly,在这种情况下,您的LibraryItemLink 表中只有一列引用LibraryItem 表。请参阅编辑后的答案。
    • 再次感谢。仍然有点困惑,因为您的答案中有 2-3 个 FK。你能把不适用的东西删掉吗?谢谢
    • 谢谢。这只会实现一个外键吗?我希望使用 2 个外部关系,一个指向父记录,另一个指向子记录。无论是删除主表中的父表还是子表,都应触发级联删除以删除链接表中的链接记录。但是,由于循环错误,我无法在两个 Fks 上设置级联。这是我问题的核心。目前我正在对我的孩子 FK 进行一次级联删除,因为这是最常见的删除情况。是否可以有 2 个 FK 与级联删除?
    • @SamJolly,是的,你可以拥有,但两个 FK 必须指向不同的表(不同的列)而不是同一个表。在您的情况下,您尝试指向同一个表(id 列),因此导致循环错误。
    猜你喜欢
    • 2011-06-27
    • 2012-01-07
    • 2017-11-17
    • 1970-01-01
    • 2015-02-19
    • 1970-01-01
    • 1970-01-01
    • 2018-01-11
    • 2017-08-10
    相关资源
    最近更新 更多