SQL Server : Self-reference FK, 触发器而不是 ON DELETE CASCADE

标签 sql sql-server foreign-keys triggers cascade

我需要对名为 CATEGORY 的表执行 ON DELETE CASCADE,该表具有以下列 CAT_ID(BIGINT) 名称(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,它的 CATEGORies 也必须被删除。因此,当我定义触发器时,我收到此错误:

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

有什么想法吗?

最佳答案

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

算法是这样的:

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

  • 查找临时表中记录的详细记录

  • 循环直到找不到更多记录

通过连接临时表来删除表中的记录。

我描述了递归删除in my blog .

更新

我想您只需要从类别中的递归外键中删除 ON DELETE CASCADE 标志即可。来自 CAT_SCH 的外键上的 CASCADE 标志应该无关紧要。

关于SQL Server : Self-reference FK, 触发器而不是 ON DELETE CASCADE,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1783700/

相关文章:

mysql - 构建每日销售数据库

sql - 当列类型为 nvarchar 时,将表与列值的总和一起旋转

sql-server - SQL Server 查询优化 : why CPU Time is higher than Elapsed Time ? 它们与设置操作相关吗?

mysql - 无法将外键约束添加到多列 pk

python - 仅当外键存在时才保存内容的标准方法是什么?

sql - 在“代替删除”触发器中删除记录

mysql - 如何编写多年来联合表的通用代码?

c# - 如何使用 ORMlite 将 byte[] 数组插入图像列

c# - 将 SqlDataReader 移至外部函数对性能有何影响?

c# - EF Core 迁移从新的复合索引中删除第一个外键索引