出現這種錯誤有兩種情況
情況一:
設置了事務開始而沒有對事務進行提交或回滾 例如:
Begin Tran
Declare @i int
if(@i>10)
Begin
Return 'Error'
End
Commit Tran
Return 'Ok'
當@i>10時 則會報 EXECUTE 后的事務計數指示 BEGIN 和 COMMIT 語句的數目不匹配。上一計數 = 0,當前計數 = 1。
情況二:
發生在嵌套事務里 如果子存儲過程進行了子事務的回滾
- declare @trancount int --commit,rollback只控制本存儲過程
- set @trancount = @@trancount;
- if (@trancount=0) /*判斷事務記數,根據情況確定使用保存點或者新建一個事務*/
- begin tran current_tran--當前事務點,rollback、commit都從這里開始
- else
- 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
.......
....做事去了
.......
- 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
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,表明進入該事務前已經有一個事務,該事務是子事務,不能提交。
- -- 如果當前計數為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; -- 成功
-- 如果當前計數為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; -- 成功