sql-server - SQL Server "AFTER INSERT"触发器看不到刚刚插入的行

标签 sql-server sql-server-2005 triggers

考虑这个触发器:

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

我有一个表,someTable,我正在努力防止人们插入错误记录。就本问题而言,错误记录有一个全数字的字段“someField”。

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

触发器工作正常,但有一个问题...当它触发时,它似乎永远不会删除刚刚插入的坏记录...它会删除任何旧的坏记录,但不会删除刚刚插入的坏记录。因此,经常会出现一条错误记录,直到其他人出现并执行另一次插入操作后才会将其删除。

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

最佳答案

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

编辑:这样做的原因是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/

相关文章:

sql - 删除反向重复项 - SQL Server

sql-server - 如何在构建时忽略 .sql 文件但将其包含在架构比较中

sql-server-2005 - 将 Enter 替换为空格

javascript - mousedown后触发输入

c# - 如何将特定的 .hbm.xml 文件添加到 nhibernate 配置以在导出模式中使用

MySQL 在 END 附近创建触发器语法错误

sql-server - SQL Server CE 3.5 更新行错误 DB_E_ERRORSOCCURRED 列错误是 DBSTATUS_E_SCHEMAVIOLATION

sql-server - 查询表值函数时增加最大递归深度

sql-server - SQL Server 在(错误地)创建新列后删除了我的表..到底发生了什么?

sql-server-2005 - 索引性能 BigInt 与 VarChar