当需要检查@@ trancount>在try catch块中为0?

时间:2012-12-21 02:23:11

标签: sql-server sql-server-2008 tsql transactions try-catch

有时我看到以下代码段。 if @@trancount > 0需要begin try的时间是什么时候?他们都?或者它是一种安全的方法(最佳实践),以便在检查之前回滚时始终检查它?

begin tran
begin try
  ... just several lines of sql ...
  if @@trancount > 0 commit tran
end try
begin catch
  if @@trancount > 0 rollback tran
end catch

4 个答案:

答案 0 :(得分:8)

在处理@@trancount时,我可以考虑一些需要考虑的方案:

  1. 当前事务是从另一个存储过程调用的 自己的交易
  2. 当前的事务由一些.NET代码调用 交易
  3. 当前交易是唯一的交易
  4. 我相信Remus Rusanu的Exception handling and nested transactions处理所有这些可能性。

答案 1 :(得分:0)

当您不使用@@ trancount时,嵌套事务存储过程的错误消息不会返回错误的确切原因,只是返回“回滚事务请求没有相应的开始事务”,否则它将给出错误的确切原因,因此使用正确的语法很容易处理错误。

答案 2 :(得分:0)

检查的原因是,如果在@@ trancount = 0时提交trans或回滚它,则会出现此错误消息的异常: COMMIT TRANSACTION请求没有相应的BEGIN TRANSACTION。

答案 3 :(得分:0)

要回答这个问题-进行@@ trancount的时间是中间的代码是否可能已经执行了您启动的事务的提交或回滚。因此,例如,如果您要调用存储过程-请在最后执行检查。

顺便说一句,而不是执行if @@ trancount> 0,我建议最好在代码块的开头检查@@ trancount,然后查看计数是否在结束时增加了,其中进行提交或回滚的情况,具体取决于try / catch。

尤其是在触发器中,因为@@ trancount在那里始终为1,所以仅执行@@ trancount> 0可能会导致错误。

但是,即使您的代码只是在存储过程中,假设它被另一个本身具有开放事务的过程调用,如果您的代码出错并回滚,则外部存储过程也将使其事务回滚(参见https://www.sqlskills.com/blogs/paul/a-sql-server-dba-myth-a-day-2630-nested-transactions-are-real/)。

所以

BEGIN TRAN 打印@@ TRANCOUNT

BEGIN TRAN 打印@@ TRANCOUNT

回滚TRAN 打印@@ TRANCOUNT

显示 1个 2 0

所以基本上-如果中间的代码正在调用其他过程,则需要执行IF @@ TRANCOUNT检查。