回滚时触发错误

Posted

技术标签:

【中文标题】回滚时触发错误【英文标题】:Trigger error when rollback 【发布时间】:2013-12-31 11:54:50 【问题描述】:

我有这个触发器,它在回滚时返回错误,错误是“事务在触发器中结束。批处理已中止。”

create trigger trigger1 on payments
for insert
as
set nocount on ;
begin
    if(select COUNT(*) from customers c , inserted i where c.customer_id = i.customer_id) = 0

        begin
            rollback tran;
            print 'Customer not found'
        end
     else

        print 'ok'

end

【问题讨论】:

@NagarajS 好的只是糟糕的编程,但解决方案在哪里 sqlteam.com/forums/topic.asp?TOPIC_ID=179383 使用触发器回滚外部事务并不是一个好主意,IMO 就像 @@Trancount won't balance。建议要么只是从触发器引发错误/抛出,然后调用 proc 应该在假设它有错误处理程序的情况下回滚,或者更好的是,将存在检查添加到插入 proc/代码 - 这将使读者更清楚触发。 是的,正如@StuartLC 已经提到的,您在触发器中的回滚是导致此错误的主要原因。在此处查看另一篇有很好解释的帖子***.com/questions/7310820/… 如果您想确保客户中存在 Payments.customer_id,为什么不添加 FOREIGN KEY 约束?另外,如果你真的不想回滚事务,你想在这里实现什么? 【参考方案1】:

根据评论尝试从触发器引发错误而不是回滚 (OR) 回滚,然后抛出/引发错误并从触发器返回,如下所示

create trigger trigger1 on payments
for insert
as
set nocount on;
begin
    if(select COUNT(*) from customers c join inserted i 
    on c.customer_id = i.customer_id) = 0
        begin
        declare @errmsg VARCHAR(MAX), @sev AS INT, @state AS INT
        SELECT @errmsg = ERROR_MESSAGE(), @sev = ERROR_SEVERITY(), 
        @state = ERROR_STATE()
        print 'Customer not found'
        rollback transaction
        raiserror(@errmsg,@sev,@state);
      return
        end
     else
        print 'ok'
end

【讨论】:

插入不存在的客户编号时出现同样的错误'事务在触发器中结束。该批次已中止。'

以上是关于回滚时触发错误的主要内容,如果未能解决你的问题,请参考以下文章

junit测试事务回滚时遇到的问题

Artisan 回滚,未定义索引(文件丢失)

SQLAlchemy在FlushError之后没有回滚

SQL Server中while循环中的事务

TSQL:触发/回滚事务错误

Oracel和Mysql的相关的错题