【发布时间】:2019-05-14 14:51:01
【问题描述】:
我有一个有两列的表。它们中的每一个都是同一个第二个表的外键:
CREATE TABLE [dbo].[TBL_TOGETHER]
(
[ID1] [int] NULL FOREIGN KEY REFERENCES [TBL_ANOTHER_TABLE](ID),
[ID2] [int] NULL FOREIGN KEY REFERENCES [TBL_ANOTHER_TABLE](ID)
)
但现在我不能再从TBL_ANOTHER_TABLE 中删除实体了:
DELETE 语句与 REFERENCE 约束“FK__TBL_ASD__4DE98D56”冲突。
我的问题是:在TBL_TOGETHER 实施ON DELETE CASCADE 的最佳解决方案是什么?
我尝试在外键上添加ON DELETE SET NULL或ON DELETE CASCADE,但由于循环或多个级联路径,它不起作用。
我曾尝试在TBL_ANOTEHR_TABLE 上添加删除触发器,但仍与外键冲突:
ALTER TRIGGER REMOVE_FORENGKEY
ON TBL_ANOTHER_TABLE
FOR DELETE
AS
BEGIN
UPDATE TBL_TOGETHER
SET TBL_TOGETHER.ID1 = NULL
FROM TBL_TOGETHER
JOIN deleted ON TBL_TOGETHER.ID1 = deleted.ID;
UPDATE TBL_TOGETHER
SET TBL_TOGETHER.ID2 = NULL
FROM TBL_TOGETHER
JOIN deleted ON TBL_TOGETHER.ID2 = deleted.ID;
END
我尝试了INSTEAD OF DELETE-trigger,但这种方法也不起作用,因为引用的表还包含具有级联约束的外键。
ALTER TRIGGER REMOVE_FORENGKEY
ON TBL_ANOTHER_TABLE
INSTEAD OF DELETE
AS
BEGIN
UPDATE TBL_TOGETHER
SET TBL_TOGETHER.ID1 = NULL
FROM TBL_TOGETHER
JOIN deleted ON TBL_TOGETHER.ID1 = deleted.ID;
UPDATE TBL_TOGETHER
SET TBL_TOGETHER.ID2 = NULL
FROM TBL_TOGETHER
JOIN deleted ON TBL_TOGETHER.ID2 = deleted.ID;
DELETE TBL_ANOTHER_TABLE
FROM TBL_ANOTHER_TABLE
JOIN deleted ON TBL_ANOTHER_TABLE.ID = deleted.ID
WHERE TBL_ANOTHER_TABLE.ID = deleted.ID;
END
错误:
无法更改表 'TBL_ANOTHER_TABLE' 上的 INSTEAD OF DELETE 或 INSTEAD OF UPDATE TRIGGER 'REMOVE_FORENGKEY'。这是因为该表有一个 FOREIGN KEY 和级联 DELETE 或 UPDATE。
【问题讨论】:
-
SQL Server 仅支持单个级联。如果两者都很重要,则需要以与使用
CASCADE不同的方式来处理此问题,例如代替触发器,或强制用户使用 SP 完成删除,从而优雅地处理删除语句。 -
如果你想在一个而不是触发器中管理删除,你应该从外键中删除级联。
-
我不想从引用的 TBL_ANOTHER_TABLE 中删除级联,因为它也会在级联时自动删除。
-
但是您正试图在而不是触发器中处理级联部分。你不能两者都做。这就是错误消息清楚地告诉您的内容。
-
如果你想使用
CASCADE,那么你必须选择1个键来处理级联,然后不允许人们删除会影响另一个“树”的行;可能会使键上的级联点无效。如果您想使用INSTEAD OF触发器,那么就像@SeanLange 所说,您必须对所有事情都使用触发器;你不能混合这两种解决方案。如果您可以控制用户,那么我个人会选择 SP 路线,否则将采用代替触发器的方式。
标签: sql-server foreign-keys ddl