SQL Server:自引用FK,触发而不是ON DELETE CASCADE

时间:2009-11-23 15:09:15

标签: sql sql-server foreign-keys triggers cascade

我需要在名为CATEGORY的表上执行ON DELETE CASCADE,该表具有以下columls CAT_ID(BIGINT) NAME(VARCHAR) PARENT_CAT_ID(BIGINT)

PARENT_CAT_ID是CAT_ID上的FK。显然,可爱的SQL Server不允许我使用ON DELETE CASCADE声明循环或多个路径删除。

我经常提出的解决方案是触发器。我做了以下触发器:

USE [ma]
GO
/****** Object:  Trigger [dbo].[TRG_DELETE_CHILD_CATEGORIES]    Script Date: 11/23/2009 16:47:59 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER TRIGGER [dbo].[TRG_DELETE_CHILD_CATEGORIES] ON [dbo].[CATEGORY] FOR DELETE AS
SET NOCOUNT ON
/* * CASCADE DELETES TO '[Tbl B]' */
DELETE CATEGORY FROM deleted, CATEGORY WHERE deleted.CAT_ID = CATEGORY.PARENT_CAT_ID

当我手动删除具有子类别的类别时,我得到以下异常:

exception

知道我的触发器有什么问题吗?

更新 抱歉编辑,但我有另一列CATEGORY.CAT_SCH_ID,这是另一个表CAT_SCH.ID的FK。此FK也有一个CASCADE DELETE,这意味着一旦我删除了CAT_SCH,它的CATEGOR也必须被删除。因此,当我定义触发器时,我收到此错误:

无法在表'CATEGORY'上创建INSTEAD OF DELETE或INSTEAD OF UPDATE TRIGGER'TRG_DEL_CATEGORY_WITH_CHILDREN'。这是因为该表有一个带有级联DELETE或UPDATE的FOREIGN KEY。

有什么想法吗?

1 个答案:

答案 0 :(得分:12)

在执行原始DELETE之后,引发FOR DELETE触发器。要递归删除,您需要编写INSTEAD OF DELETE触发器。

算法是这样的:

  • 将已删除的PK插入临时表

  • 查找临时表

  • 中记录的详细记录
  • 循环,直到找不到更多记录

通过加入临时表来删除表中的记录。

我描述了递归删除in my blog

<强>更新

我猜你只需要从类别中的递归外键中删除ON DELETE CASCADE标志。来自CAT_SCH的外键上的CASCADE标志无关紧要。