2011-11-22 69 views
3

想知道是否需要回滾時,SQL異常檢測(當別人除外):回滾在PLSQL異常

declare 
cursor c_test is 
    select * 
    from tesing; 
    begin 
     for rec in c_test loop 
     begin 
      update test1 set test1.name=rec.name where test1.id=rec.id; 
      IF sql%rowcount = 1 THEN 
          commit; 
      ELSIF sql%rowcount =0 THEN 
        dbms_output.put_line('No Rows Updated'); 
      else 
        dbms_output.put_line('More than 1 row exists'); 
        rollback; 
      END IF; 
     exception when others then 
        dbms_output.put_line(Exception'); 
        rollback; 
     end;  

end; 
+2

我會在Oracle中閱讀Tom Kyte的[Implicit Rollbacks](http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:43818437682131)。 SQL * Plus是一種不同的動物,您可以專門告訴它自動提交任何一組語句。 –

+0

非常感謝信息 – Arav

回答

15

首先,我假設我們可以忽略語法錯誤(例如,沒有END LOOPdbms_output.put_line呼叫缺少第一個單引號等)

至於是否有必要回滾更改,取決於。

通常,您不會有臨時提交循環。這通常是一個糟糕的架構,因爲它在I/O和經過時間方面成本更高。這也使編寫可重啓代碼變得更加困難。例如,如果您的SELECT語句選擇了10行,則會發出(並提交)5個更新,然後第6個更新失敗?在修復異常之後,能夠重新啓動第6行的唯一方法是在單獨的表中存儲(並更新)代碼的進度。它也爲任何調用這個塊的代碼產生了問題,這個代碼塊必須處理一半的工作已經完成(並且已經提交),另一半沒有完成。

通常,您只會將事務控制語句放在代碼的最外面的塊中。由於過程中的COMMITROLLBACK提交或回滾會話中完成的任何工作,而不管它是否由過程完成,所以您希望對添加事務控制語句非常謹慎。您通常希望讓調用者決定是否提交或回滾。當然,只有這樣才行 - 最終,你將會進入最不受其他程序調用的最外層塊,並且你需要有適當的事務控制 - 但是要非常謹慎關於你是否正在編寫可能被重用的代碼。

在這種情況下,由於您有臨時提交,所以ROLLBACK的唯一影響是如果第一個更新語句失敗,那麼在調用此塊之前在會話中完成的工作將被回滾。如果第一個更新語句成功,臨時提交將會提交以前的更改。這是人們擔心的一種副作用,當他們談論爲什麼臨時提交和可重用塊中的事務控制有問題時。

+0

非常感謝您的信息 – Arav