考虑这个触发器:

ALTER TRIGGER myTrigger
   ON someTable
   AFTER INSERT
AS BEGIN
  DELETE FROM someTable
         WHERE ISNUMERIC(someField) = 1
END

我有一个表,someTable,我正在努力防止人们插入不良记录。出于这个问题的目的,一个坏记录有一个字段“someField”,它全是数字。

当然,正确的方法不是使用触发器,但我不控制源代码……只是 SQL 数据库。所以我不能真正阻止插入坏行,但我可以立即删除它,这足以满足我的需要。

触发器可以工作,但有一个问题……当它触发时,它似乎永远不会删除刚刚插入的坏记录……它会删除任何旧的坏记录,但不会删除刚刚插入的坏记录。因此,经常有一个不好的记录四处飘散,直到其他人出现并执行另一个 INSERT 时才会删除。

这是我对触发器的理解有问题吗?触发器运行时新插入的行是否尚未提交?

最佳答案

触发器无法修改更改的数据( InsertedDeleted ),否则您可能会在更改再次调用触发器时获得无限递归。一种选择是触发器回滚事务。

编辑: 原因是SQL 的标准是插入和删除的行不能被触发器修改。其根本原因是修改可能导致无限递归。在一般情况下,此评估可能涉及相互递归级联中的多个触发器。让系统智能地决定是否允许此类更新在计算上是难以处理的,本质上是 halting problem. 的变体

对此的公认解决方案是不允许触发器更改更改的数据,尽管它可以回滚事务。

create table Foo (
       FooID int
      ,SomeField varchar (10)
)
go

create trigger FooInsert
    on Foo after insert as
    begin
        delete inserted
         where isnumeric (SomeField) = 1
    end
go


Msg 286, Level 16, State 1, Procedure FooInsert, Line 5
The logical tables INSERTED and DELETED cannot be updated.

像这样的事情会回滚事务。
create table Foo (
       FooID int
      ,SomeField varchar (10)
)
go

create trigger FooInsert
    on Foo for insert as
    if exists (
       select 1
         from inserted
        where isnumeric (SomeField) = 1) begin
              rollback transaction
    end
go

insert Foo values (1, '1')

Msg 3609, Level 16, State 1, Line 1
The transaction ended in the trigger. The batch has been aborted.

关于sql-server - SQL Server "AFTER INSERT"触发器没有看到刚刚插入的行,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/405288/

10-17 01:13