删除后触发器仅在删除后触发?

发布于 2024-08-31 02:23:27 字数 645 浏览 4 评论 0原文

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

我在 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 是否会给出任何错误。

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

I thought "after delete" meant that the trigger is not fired until after the delete has already taken place, but here is my situation...

I made 3, nearly identical SQL CLR after delete triggers in C#, which worked beautifully for about a month. Suddenly, one of the three stopped working while an automated delete tool was run on it.

By stopped working, I mean, records could not be deleted from the table via client software. Disabling the trigger caused deletes to be allowed, but re-enabling it interfered with the ability to delete.

So my question is 'how can this be the case?' Is it possible the tool used on it futzed up the memory? It seems like even if the trigger threw an exception, if it is AFTER delete, shouldn't the records be gone?

All the trigger looks like is this:

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

The CLR trigger does one select and one insert into another database. I don't yet know if there are any errors from SQL Server Mgmt Studio, but will update the question after I find out.

UPDATE:

Well after re-executing the same trigger code above, everything works again, so I may never know what if any error SSMS would give.

Also, there is no call to rollback anywhere in the trigger's code.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

深海里的那抹蓝 2024-09-07 02:23:27

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

这是触发器的输出

我触发了

Msg 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

我触发的 操作
消息 512,级别 16,状态 1,过程 trDelete,第 6

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

该声明已终止。

检查表

select * from test

没有删除任何内容

after means it just fires after the event, it can still be rolled back

example

create table test(id int)
go


create trigger trDelete on test after delete
as

print 'i fired '
rollback

do an insert

insert test values (1)

now delete the data

delete test

Here is the output from the trigger

i fired

Msg 3609, Level 16, State 1, Line 1

The transaction ended in the trigger. The batch has been aborted.

now check the table, and verify that nothing was deleted

select * from test

The CLR trigger does one select and
one insert into another database. I
don't yet know if there are any errors
from SQL Server Mgmt Studio, but will
update the question after I find out.

Suddenly, one of the three stopped
working while an automated delete tool
was run on it.

triggers fire per batch/statement not per row, is it possible that your trigger wasn't coded for multi-row operations and the automated tool deleted more than 1 row in the batch? Take a look at Best Practice: Coding SQL Server triggers for multi-row operations

Here is an example that will make the trigger fail without doing an explicit rollback

alter trigger trDelete on test after delete
as

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

insert some rows

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

run this

delete test

i fired
Msg 512, Level 16, State 1, Procedure trDelete, Line 6

Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.

The statement has been terminated.

check the table

select * from test

nothing was deleted

你没皮卡萌 2024-09-07 02:23:27

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

An error in the AFTER DELETE trigger will roll-back the transaction. It is after they are deleted but before the change is committed. Is there any particular reason you are using a CLR trigger for this? It seems like something that a pure SQL trigger ought to be able to do in a possibly more lightweight manner.

猫烠⑼条掵仅有一顆心 2024-09-07 02:23:27

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

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

Well you shouldn't be doing a select in trigger (who will see the results) and if all you are doing is an insert it shouldn't be a CLR trigger either. CLR is not generally a good thing to have in a trigger, far better to use t-SQL code in a trigger unless you need to do something that t-sql can't handle which is probably a bad idea in a trigger anyway.

Have you reverted to the last version you have in source control? Perhaps that would clear the problem if it has gotten corrupted.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文