EXECUTE 后的事务计数指示 BEGIN 和 COMMIT 语句的数目不匹配。上一计数 = 0,当前计数 = 1。 – yjc2629498 – 博客园

来源: EXECUTE 后的事务计数指示 BEGIN 和 COMMIT 语句的数目不匹配。上一计数 = 0,当前计数 = 1。 – yjc2629498 – 博客园

出现这种错误有两种情况

情况一:

设置了事务开始而没有对事务进行提交或回滚 例如:

Begin  Tran

Declare @i int

if(@i>10)

Begin

Return ‘Error’

End

Commit Tran

Return ‘Ok’

当@i>10时 则会报 EXECUTE 后的事务计数指示 BEGIN 和 COMMIT 语句的数目不匹配。上一计数 = 0,当前计数 = 1。

情况二:

发生在嵌套事务里 如果子存储过程进行了子事务的回滚

 

  1. declare @trancount int –commit,rollback只控制本存储过程 
  2.     set @trancount = @@trancount;
  3.     if (@trancount=0) /*判断事务记数,根据情况确定使用保存点或者新建一个事务*/
  4.         begin tran current_tran–当前事务点,rollback、commit都从这里开始  
  5.     else
  6.         save tran current_tran
declare @trancount int --commit,rollback只控制本存储过程
    set @trancount = @@trancount;
    
	if (@trancount=0) /*判断事务记数,根据情况确定使用保存点或者新建一个事务*/ 
		begin tran current_tran--当前事务点,rollback、commit都从这里开始 
	else
		save tran current_tran

…….

….做事去了

…….

 

  1. if @error_code != 0 or @logErrorCode != 1
  2.         begin
  3.             rollback tran current_tran
  4.             set @error_code = -1; — 失败 
  5.         end
  6.     else
  7.         begin
  8.             commit tran current_tran
  9.             set @error_code = 1; — 成功 
  10.          end
if @error_code != 0 or @logErrorCode != 1
		begin
			rollback tran current_tran
			set @error_code = -1; -- 失败
		end
	else
		begin
			commit tran current_tran
			set @error_code = 1; -- 成功
		 end

有没有问题?(current_tran是保存点哈,不明白的,后面有比较详细的介绍)

我用了好久了(在一个项目里面),可是突然有一天,也就是今天,它出事了。原因嘛,虽然写的是嵌套的,之前都没有嵌套调到过。

我在外围开了一个事务,再来调这个存储过程,当它 commit tran current_tran 时(rollback tran current_tran是不会有事的),会出什么错误?如果你不能很明确的告诉我,说明你还没有理解得深刻。做个选择吧?

1.”…BEGIN 和 COMMIT 语句的数目不匹配。上一计数 = 0,当前计数 = 1。”

2.”…BEGIN 和 COMMIT 语句的数目不匹配。上一计数 = 1,当前计数 = 0。

 

答案:【2】。

线索分析:我是在外部开了一个事务的,所以在未进入该存储过程以前@@trancount的值应该为1;进入时,save tran current_tran, @@trancount值没有变;完事的,执行commit tran current_tran,@@trancount的值应该为0;--所以,进入前,出来后,@@trancount值发生了改变,SQLServer不干了(原因,自己去想吧:拆散了begin tran 配对)。

怎么解决

1.进入子事务前先记录@@trancount,我们用变量@trancount来记录。

2. 提交子事务前,先判断之前的@trancount是否为0;为0表示”该事务”前没有事务调用,可以直接提交事务;不为0,表明进入该事务前已经有一个事务,该事务是子事务,不能提交。

  1. — 如果当前计数为0,则提交.  
  2.          — 因为Commit tran ,@@TRANCOUNT会减1。嵌套事务时,调用该存在过程(作为子过程,此时@@TRANCOUNT > 0), 
  3.          — 只是保存了tran, @@TRANCOUNT没有发生改变;直接Commit会使@@TRANCOUNT减1,会打破事务对(Begin Tran) 
  4.         if(@trancount = 0)
  5.         begin
  6.             commit tran current_tran
  7.         end
  8.         set @error_code = 1; — 成功
 -- 如果当前计数为0,则提交. 
			 -- 因为Commit tran ,@@TRANCOUNT会减1。嵌套事务时,调用该存在过程(作为子过程,此时@@TRANCOUNT > 0),
			 -- 只是保存了tran, @@TRANCOUNT没有发生改变;直接Commit会使@@TRANCOUNT减1,会打破事务对(Begin Tran)
			if(@trancount = 0)
			begin
			    commit tran current_tran
			end
			set @error_code = 1; -- 成功
分享到:更多 ()