1. 程式人生 > >[儲存過程]中的事務(rollback)回滾

[儲存過程]中的事務(rollback)回滾

在編寫SQL Server 事務相關的儲存過程程式碼時,經常看到下面這樣的寫法:

  1. begin tran   
  2. update statement 1 ...   
  3. update statement 2 ...   
  4. delete statement 3 ...   
  5. commit tran 

這樣編寫的SQL存在很大隱患。請看下面的例子:

  1. create table demo(id int not null)   
  2. go   
  3. begin tran   
  4. insert into demo values (null)  
  5. insert into demo values (2)   
  6. commit tran   
  7. go 

執行時會出現一個違反not null 約束的錯誤資訊,但隨後又提示(1 row(s) affected)。 我們執行select * from demo 後發現insert into demo values(2) 卻執行成功了。 這是什麼原因呢? 原來 SQL Server在發生runtime 錯誤時,預設會rollback引起錯誤的語句,而繼續執行後續語句。

如何避免這樣的問題呢?有三種方法:

1. 在事務語句最前面加上set xact_abort on

  1. set xact_abort on   
  2. begin tran   
  3. update statement 1 ...   
  4. update statement 2 ...   
  5. delete statement 3 ...   
  6. commit tran   
  7. go 

當xact_abort 選項為on 時,SQL Server在遇到錯誤時會終止執行並rollback 整個事務。  這個意思是說,如果該事務中包含子事務,子事務也會回滾。

2. 在每個單獨的DML語句執行後,立即判斷執行狀態,並做相應處理。

  1. begin tran   
  2. update statement 1 ...  
  3. if @@error <> 0   
  4. begin rollback tran   
  5. goto labend   
  6. end   
  7. delete statement 2 ...   
  8. if @@error <> 0  
  9. begin rollback tran   
  10. goto labend   
  11. end   
  12. commit tran   
  13. labend:   
  14. go 

3. 在SQL Server 2005中,可利用 try...catch 異常處理機制。

  1. begin tran   
  2. begin try   
  3. update statement 1 ...   
  4. delete statement 2 ...   
  5. endtry   
  6. begin catch  
  7. if @@trancount > 0   
  8. rollback tran   
  9. end catch  
  10. if @@trancount > 0   
  11. commit tran  
  12. go 

下面是個簡單的儲存過程,演示事務處理過程。

  1. create procedure dbo.pr_tran_inproc as begin set nocount on   
  2. begin tran  
  3. update statement 1 ...   
  4. if @@error <> 0   
  5. begin rollback tran   
  6. return -1 end   
  7. delete statement 2 ...   
  8. if @@error <> 0   
  9. begin rollback tran   
  10. return -1   
  11. end commit tran   
  12. return 0   
  13. end   
  14. go