忽略触发器中的错误

Adi*_*Adi 6 sql-server triggers transactions try-catch

我有一个存储过程,在Insert/Update/Delete的触发器内调用.

问题是该SP内部存在某个代码块并不重要.因此,我想忽略此代码块产生的任何错误.

我在TRY CATCH块中插入了这个代码块.但令我惊讶的是我收到了以下错误:

当前事务无法提交,也无法支持写入日志文件的操作.回滚交易.

然后我尝试使用SAVE&ROLLBACK TRANSACTION和TRY CATCH,它也因以下错误而失败:

当前事务无法提交,也无法回滚到保存点.回滚整个交易.

我的服务器版本是:Microsoft SQL Server 2008(SP2) - 10.0.4279.0(X64)

样本DDL:

IF OBJECT_ID('TestTrigger') IS NOT NULL
    DROP TRIGGER TestTrigger
GO
IF OBJECT_ID('TestProcedure') IS NOT NULL
    DROP PROCEDURE TestProcedure
GO
IF OBJECT_ID('TestTable') IS NOT NULL
    DROP TABLE TestTable
GO

CREATE TABLE TestTable (Data VARCHAR(20))
GO

CREATE PROC TestProcedure       
AS      
BEGIN 

    SAVE TRANSACTION Fallback
    BEGIN TRY
        DECLARE @a INT = 1/0
    END TRY
    BEGIN CATCH
        ROLLBACK TRANSACTION Fallback
    END CATCH
END
GO

CREATE TRIGGER TestTrigger
ON TestTable
FOR INSERT, UPDATE, DELETE 
AS
BEGIN
    EXEC TestProcedure   
END
GO
Run Code Online (Sandbox Code Playgroud)

用于复制错误的代码:

BEGIN TRANSACTION
INSERT INTO TestTable VALUES('data')
IF @@ERROR > 0
    ROLLBACK TRANSACTION
ELSE
    COMMIT TRANSACTION
GO
Run Code Online (Sandbox Code Playgroud)

小智 12

我经历了同样的折磨,我刚解决了!只需在TRIGGER的第一步添加这一行,您就可以了:

SET XACT_ABORT OFF;
Run Code Online (Sandbox Code Playgroud)

就我而言,我正在处理错误,该错误为导致错误的批处理和SQL中的错误变量提供了特定的表.

为默认值XACT_ABORTON,所以即使你正在处理一个try catch块(就像我做的)内部错误的整个交易将不被COMMITED.将其值设置为OFF将导致即使发生错误也会提交事务.

但是,当没有处理错误时我没有测试它...

欲了解更多信息:


Dam*_*ver 1

我建议重新构建它,以便您不会毒害原始事务 - 也许让事务发送服务代理消息(或者只是将相关数据插入某种形式的队列表中),以便“非关键”部分可以在完全独立的交易中进行。

例如你的触发器变成:

CREATE TRIGGER TestTrigger
ON TestTable
FOR INSERT, UPDATE, DELETE 
AS
BEGIN
    INSERT INTO QueueTable (Col1,Col2)
    SELECT COALESCE(i.Col1,d.Col1),COALESCE(i.Col2,d.Col2) from inserted i,deleted d
END
GO
Run Code Online (Sandbox Code Playgroud)

不应该在触发器内执行任何可能失败的操作,除非您确实希望强制启动触发器操作的事务也失败。