如何找出导致错误的语句Msg 3609, Level 16, State 1, Line 4
The transaction ended in the trigger. The batch has been aborted.
?
代码看起来很简单:
-- 1. Check 1
IF (EXISTS (
... check ...
))
BEGIN
RAISERROR('Does not allow 1', 16, 1);
IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION;
RETURN;
END;
-- 2. Check 2
IF (EXISTS (
... check ...
))
BEGIN
RAISERROR('Does not allow 2', 16, 1);
IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION;
RETURN;
END;
我检查了事务是否存在,所以在引发错误后我一定看不到该错误。
编辑:
我同意你的看法@gbn。我知道中的操作TRIGGER
是一笔交易。
问题是在我们的代码(由我和一位同事编写)中,有一种情况RAISERROR
不会触发回滚。我在实践中看到了 - 触发器引发了错误,但插入了新数据。那里的语法是相反的 - firstROLLBACK
然后RAISERROR
。我发现切换位置可以解决问题(我不知道为什么它只能以这种方式工作)。
我决定玩一点@@TRANCOUNT
。但是当我插入几个转录时,触发器开始给我 3609。删除@@TRANCOUNT
并没有解决问题。因为我有ROLLBACK
检查是否有未结交易 3609 对我来说很奇怪。还有另一个触发器,但即使我禁用它,我仍然会收到 3609。
如果您在调用代码和触发器中使用 TRY/CATCH,则错误处理过程变得更加可预测和可靠。
没有这个,触发器中的错误(这里由 RAISERROR 引起)中止批处理。所以你永远不会看到来自 RAISERROR 的错误。
有关更多信息,请参阅为什么 TRY CATCH 不会抑制触发器中的异常
注意:触发器总是在事务中,因为它是 DML 的一部分。当然,任何触发代码/操作都必须是 DML 的原子。