假设我有三张桌子,[ONE],[ONE_TWO]和[TWO]。 [ONE_TWO]是一个多对多连接表,只有[ONE_ID和[TWO_ID]列。设置了外键以将[ONE]链接到[ONE_TWO]和[TWO]到[ONE_TWO]。 FK使用ON DELETE CASCADE选项,以便在删除[ONE]或[TWO]记录时,相关的[ONE_TWO]记录也将自动删除。
我希望在[TWO]表上有一个触发器,这样当删除[TWO]记录时,它会执行一个以[ONE_ID]为参数的存储过程,传递链接的[ONE_ID]值删除发生前的[TWO_ID]:
DECLARE @Statement NVARCHAR(max)
SET @Statement = ''
SELECT @Statement = @Statement + N'EXEC [MyProc] ''' + CAST([one_two].[one_id] AS VARCHAR(36)) + '''; '
FROM deleted
JOIN [one_two] ON deleted.[two_id] = [one_two].[two_id]
EXEC (@Statement)
显然,我需要一个BEFORE DELETE触发器,但SQL Server 2005中没有这样的东西。由于级联FK,我无法使用INSTEAD OF触发器。
我得到的印象是,如果我使用FOR DELETE触发器,当我将[已删除]加入[ONE_TWO]以查找[ONE_ID]值列表时,FK级联将已删除关联的[ONE_TWO]记录,我永远不会找到任何[ONE_ID]值。这是真的?如果是这样,我怎样才能实现我的目标?
我想我需要将FK加入[TWO]改为[ONE_TWO]以不使用级联并在我手动删除[TWO]之前在触发器中手动执行从[ONE_TWO]删除记录。但如果有更简单的方法,我宁愿不经历所有这些。
答案 0 :(得分:8)
您可以使用INSTEAD OF触发器。它会在(替换)实际删除之前触发,因此[one_two]中的链接记录必须仍然存在。
create table [one] (one_id int not null primary key)
create table [two] (two_id int not null primary key)
create table [one_two] (one_id int, two_id int references two(two_id) on delete cascade)
GO
CREATE trigger t_del_two
on two
instead of delete
as
begin
SET NOCOUNT ON
DECLARE @Statement NVARCHAR(max)
SET @Statement = ''
SELECT @Statement = @Statement + N'EXEC [MyProc] ''' + CAST([one_two].[one_id] AS VARCHAR(36)) + '''; '
FROM deleted
JOIN [one_two] ON deleted.[two_id] = [one_two].[two_id]
PRINT (@Statement)
--EXEC (@Statement)
-- carry out the actual delete
DELETE TWO WHERE two_id in (SELECT two_id from deleted)
end
GO
一些样本值
insert into one select 1
insert into one select 2
insert into one select 3
insert into two select 11
insert into two select 12
insert into two select 13
insert into one_two select 1,11
insert into one_two select 1,13
insert into one_two select 2,13
现在测试一下
delete two where two_id=13