1

我认为“删除后”意味着直到删除已经发生后才会触发触发器,但这是我的情况......

在 C# 中删除触发器后,我制作了 3 个几乎相同的 SQL CLR,它运行了大约一个月。突然,三个中的一个在运行自动删除工具时停止工作。

通过停止工作,我的意思是,无法通过客户端软件从表中删除记录。禁用触发器导致允许删除,但重新启用它会干扰删除能力。

所以我的问题是“怎么会是这样?” 是否有可能使用它的工具弄乱了内存?似乎即使触发器抛出了异常,如果它是在删除之后,记录不应该消失吗?

所有触发器看起来都是这样的:

ALTER TRIGGER [sysdba].[AccountTrigger] ON [sysdba].[ACCOUNT]  AFTER  DELETE AS 
EXTERNAL NAME [SQL_IO].[SQL_IO.WriteFunctions].[AccountTrigger]
GO

CLR 触发器执行一次选择和一次插入到另一个数据库。我还不知道 SQL Server Mgmt Studio 是否有任何错误,但我会在发现后更新问题。

更新:

好吧,在重新执行上面相同的触发代码之后,一切都会再次运行,所以我可能永远不知道如果 SSMS 出现任何错误会发生什么。

此外,触发器代码中的任何地方都没有调用回滚。

4

3 回答 3

6

after 表示它只是在事件之后触发,它仍然可以回滚

例子

create table test(id int)
go


create trigger trDelete on test after delete
as

print 'i fired '
rollback

做一个插入

insert test values (1)

现在删除数据

delete test

这是触发器的输出

我解雇了

消息 3609,第 16 层,状态 1,第 1 行

事务在触发器中结束。该批次已中止。

现在检查表,并确认没有任何内容被删除

select * from test

CLR 触发器执行一次选择和一次插入到另一个数据库。我还不知道 SQL Server Mgmt Studio 是否有任何错误,但我会在发现后更新问题。

突然,三个中的一个在运行自动删除工具时停止工作。

触发器按批次/语句而不是按行触发,您的触发器是否可能未针对多行操作进行编码,并且自动化工具在批次中删除了超过 1 行?查看最佳实践:为多行操作编写 SQL Server 触发器

这是一个示例,它会在不进行显式回滚的情况下使触发器失败

alter trigger trDelete on test after delete
as

print 'i fired '
declare @id int
select @id = (select id from deleted)
GO

插入一些行

insert test values (1)
insert test values (2)
insert test values (3)

运行这个

delete test

我解雇了 Msg 512, Level 16, State 1, Procedure trDelete, Line 6

子查询返回超过 1 个值。当子查询跟随 =、!=、<、<=、>、>= 或子查询用作表达式时,这是不允许的。

该语句已终止。

检查表格

select * from test

什么都没有被删除

于 2010-05-05T14:46:16.067 回答
1

AFTER DELETE 触发器中的错误将回滚事务。它是在它们被删除之后但在更改提交之前。您为此使用 CLR 触发器有什么特别的原因吗?看起来纯 SQL 触发器应该能够以一种可能更轻量级的方式来完成。

于 2010-05-05T14:45:42.247 回答
1

好吧,您不应该在触发器中进行选择(谁会看到结果),如果您所做的只是插入,那么它也不应该是 CLR 触发器。CLR 在触发器中通常不是一件好事,在触发器中使用 t-SQL 代码要好得多,除非您需要执行 t-sql 无法处理的事情,这在触发器中可能是个坏主意。

您是否已恢复到源代码管理中的最新版本?如果它已经损坏,也许这会解决问题。

于 2010-05-05T14:49:09.360 回答