如何在SQL Server 2005中模拟删除前触发器 [英] How to emulate a BEFORE DELETE trigger in SQL Server 2005

查看:104
本文介绍了如何在SQL Server 2005中模拟删除前触发器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有三个表,[ONE],[ONE_TWO]和[TWO]。 [ONE_TWO]是仅具有[ONE_ID和[TWO_ID]列的多对多联接表。设置了将[ONE]链接到[ONE_TWO]和将[TWO]链接到[ONE_TWO]的外键。 FK使用ON DELETE CASCADE选项,因此,如果删除[ONE]或[TWO]记录,关联的[ONE_TWO]记录也将被自动删除。

Let's say I have three tables, [ONE], [ONE_TWO], and [TWO]. [ONE_TWO] is a many-to-many join table with only [ONE_ID and [TWO_ID] columns. There are foreign keys set up to link [ONE] to [ONE_TWO] and [TWO] to [ONE_TWO]. The FKs use the ON DELETE CASCADE option so that if either a [ONE] or [TWO] record is deleted, the associated [ONE_TWO] records will be automatically deleted as well.

我想在[TWO]表上有一个触发器,以便在删除[TWO]记录时,它执行一个存储过程,该存储过程将[ONE_ID]作为一个参数,传递在删除发生之前链接到[TWO_ID]的[ONE_ID]值:

I want to have a trigger on the [TWO] table such that when a [TWO] record is deleted, it executes a stored procedure that takes a [ONE_ID] as a parameter, passing the [ONE_ID] values that were linked to the [TWO_ID] before the delete occurred:

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)

很明显,我需要一个DELETE触发器,但SQL Server 2005中没有这样的触发器。我不能使用INSTEAD OF触发器由于FK级联。

Clearly, I need a BEFORE DELETE trigger, but there is no such thing in SQL Server 2005. I can't use an INSTEAD OF trigger because of the cascading FK.

给人的印象是,如果使用FOR DELETE触发器,当我将[deleted]加入[ONE_TWO]来查找[ONE_ID]值列表时,FK级联将已经删除关联的[ONE_TWO]记录,因此我将永远找不到任何[ONE_ID]值。这是真的?如果是这样,我如何实现我的目标?

I get the impression that if I use a FOR DELETE trigger, when I join [deleted] to [ONE_TWO] to find the list of [ONE_ID] values, the FK cascade will have already deleted the associated [ONE_TWO] records so I will never find any [ONE_ID] values. Is this true? If so, how can I achieve my objective?

我想我需要将加入[TWO]的FK更改为[ONE_TWO]以不使用级联,并手动从[ONE_TWO]中删除在触发器中,就在我手动删除[TWO]记录之前。但是,如果有更简单的方法,我宁愿不做所有这些事情。

I'm thinking that I'd need to change the FK joining [TWO] to [ONE_TWO] to not use cascades and to do the delete from [ONE_TWO] manually in the trigger just before I manually delete the [TWO] records. But I'd rather not go through all that if there is a simpler way.

推荐答案

您可以使用INSTEAD OF触发器。它在(代替)实际的删除之前触发,因此[one_two]中的链接记录必须仍然存在。

You can use an INSTEAD OF trigger. It fires before (replaces) the actual delete, therefore the linked record in [one_two] must still exist.

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

这篇关于如何在SQL Server 2005中模拟删除前触发器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆