標籤:io 使用 ar sp on cti 代碼 bs sql
在處理事務的時候,一般都用RollBack Transaction來復原,但是如果在嵌套事務中這樣使用的話,就會出現錯誤。 在SqlServer裡,嵌套事務的層次是由@@TranCount全域變數反映出來的。每一次Begin Transaction都會引起@@TranCount加1。而每一次Commit Transaction都會使@@TranCount減1,而RollBack Transaction會復原所有的嵌套事務包括已經提交的事務和未提交的事務,而使@@TranCount置0。例如: Begin Transaction -- @@TranCount = 1 BeginTransaction -- @@TranCount = 2 BeginTransaction -- @@TranCount = 3 Commit Transaction -- @@TranCount = 2 Commit Transaction -- @@TranCount = 1 Commit Transaction -- @@TranCount = 0 如果出現錯誤ROLLBACK TRANSACTION 則: Begin Transaction -- @@TranCount = 1 BeginTransaction -- @@TranCount = 2 BeginTransaction -- @@TranCount = 3 ROLLBACK TRANSACTION -- @@TranCount = 0 Commit Transaction -- @@TranCount = 0---出現錯誤 Transaction count after EXECUTE indicates that a COMMIT or ROLLBACK TRANSACTION statement is missing. Previous count = 1, current count = 0. 如果被嵌套的事務中發生錯誤,最簡單的方法應該是無論如何都先將它提交,同時返回錯誤碼(一個正常情況不可能出現的代碼 如 -1)讓上一層事務來處理這個錯誤,從而使@@TranCount 減1。 這樣外層事務在復原或者提交的時候能夠保證外層事務在開始的時候和結束的時候保持一致。由於裡層事務返回了錯誤碼,因此外層事務(最外層)可以復原事務,這樣裡面已經提交的事務也可以被復原而不會出現錯誤。 在項目中應該會常常出現這樣的情況,一個預存程序裡面用了事務,但是不能保證它會被別的帶有事務的預存程序調用,如果單獨調用的話,出現錯誤可以直接復原,但是如果是被別的帶事務的預存程序調用的話,RollBack 就會出錯了。因此需要一種機制來區分,建立一個臨時的變數來區分是否嵌套,和嵌套的層數,如下:
DECLARE @TranCounter INT; SET @TranCounter = @@TRANCOUNT; IF @TranCounter > 0 SAVE TRANSACTION ProcedureSave; ELSE BEGIN TRANSACTION; ………… --事務內要執行的代碼 ………… IF @@ERROR<>0 goto Error Commit Transaction Commit Transaction --下面返回要返回的值0隻是個例子 Return 0 Error: IF @TranCounter = 0 ROLLBACK TRANSACTION; Else ROLLBACK TRANSACTION ProcedureSave;
Return @Error
(轉)@@trancount解析