代码之家  ›  专栏  ›  技术社区  ›  BuschnicK

tsql使触发器自动失败

  •  6
  • BuschnicK  · 技术社区  · 16 年前

    我在after insert触发器中有一些代码可能会失败。这样的失败并不重要,应该 回滚事务。如何在触发器中捕获错误并使事务的其余部分正常执行?

    下面的例子说明了我的意思。触发器故意创建一个错误条件,其结果是原始插入(“1”)从未插入到表中。尝试/抓住似乎没有起到作用。类似的, older stack overflow question 除了“首先防止错误发生”之外,没有给出答案,这并不总是可能/容易的。

    还有其他想法吗?

    create table test 
    (
      a int not null
    );
    go
    
    create trigger testTrigger on test 
    after insert as 
    begin 
      insert into test select null;
    end;
    go
    
    insert into test values ( 1 );
    
    3 回复  |  直到 14 年前
        1
  •  2
  •   Cade Roux    16 年前

    触发器不能失败,并且仍具有事务前滚。有几个选项可以确保触发器不会失败。

    1-您可以通过复制检查约束的逻辑和不尝试违反约束的操作来确保after不会失败:

    INSERT INTO test WHERE val IS NOT NULL
    

    2-您可以使用队列设计模式延迟可能失败的操作,在该模式中,通过将可能失败或不可能失败的操作排队到一个表中,在该表中,排队操作不可能失败。

    INSERT INTO ACTION_QUEUE (action, parameters) VALUES ('INSERT INTO TEST', val)
    
        2
  •  1
  •   Quassnoi    16 年前

    由于触发器的实现方式 SQL Server ,触发器中的所有约束冲突都会导致事务失败。

    这与执行以下操作相同:

    DROP TABLE test
    
    CREATE TABLE test 
    (
            a INT NOT NULL
    )
    
    GO
    
    SET XACT_ABORT ON
    GO
    
    BEGIN TRANSACTION
    
    BEGIN TRY
            INSERT
            INTO    test
            SELECT  NULL
    END TRY
    BEGIN CATCH
            INSERT
            INTO    test
            SELECT  1
    END CATCH
    

    这将导致一个注定失败的事务,除了无法禁用 XACT_ABORT 在扳机里。

    SQL Server 也缺乏自主交易。

    这也是为什么应该将所有逻辑放入存储过程而不是触发器的另一个原因。

        3
  •  0
  •   Mark Sowul    14 年前
    1. 您可以在触发器内关闭xact_abort(使用警告)
    2. 您可以让触发器调用存储过程。(我现在正在处理另一个问题:我希望事务中止,但由于逻辑在从触发器调用的SP中,而不是触发器本身,因此不会发生这种情况。)
    推荐文章