Oracle-11g

Oracle 中的回滾

  • December 12, 2014

我在 Oracle 回滾中遇到問題。

在我的儲存過程中,我有多個插入和更新語句。如果一切正常,我將發送成功消息,並將成功狀態跟踪到一個 Z_AUDIT_HISTORY 表中。

現在我在失敗狀態中需要的同樣的東西也首先需要回滾所有語句,然後將失敗狀態跟踪到這個 Z_AUDIT_HISTORY 表中。

我的程序:

create or replace PROCEDURE SPTest
AS 
BEGIN 
 SAVEPOINT sp_sptest;

 insert into emptest(empid,empname,deptno)
 (1,'ravi',10);

 insert into test1(id,name,sal)
 (1,'raju',4444);

 update emptest set empname='hari' where empid=1;

 INSERT INTO Z_AUDIT_HISTORY(AUDIT_HISTORTY_ID,STATUS)
 VALUES(SEQ_AUDIT_HISTORTY_ID.NEXTVAL,'SUCESS');

 DBMS_OUTPUT.PUT_LINE('Sucess');
EXCEPTION
 WHEN OTHERS THEN
   INSERT INTO Z_AUDIT_HISTORY(AUDIT_HISTORTY_ID,ASSET_ID,STATUS)
   VALUES(SEQ_AUDIT_HISTORTY_ID.NEXTVAL,p_asset_id,'FAIL');

   DBMS_OUTPUT.PUT_LINE('Whoops');

   ROLLBACK TO sp_sptest;

   RAISE; 
END;

當我執行我的程序時,我遇到了錯誤。

ORA-06512: at line 1
01438. 00000 -  "value larger than specified precision allowed for this column"
*Cause:    When inserting or updating records, a numeric value was entered
          that exceeded the precision defined for the column.
*Action:   Enter a value that complies with the numeric column's precision,
          or use the MODIFY option with the ALTER TABLE command to expand
          the precision.

這裡發生了三件事。

  1. 處理異常時,您先執行插入操作,然後執行回滾操作。這意味著插入也被回滾。至少,切換語句的順序:
DBMS_OUTPUT.PUT_LINE('Whoops');

ROLLBACK TO sp_sptest;

INSERT INTO Z_AUDIT_HISTORY(AUDIT_HISTORTY_ID,ASSET_ID,STATUS)
VALUES(SEQ_AUDIT_HISTORTY_ID.NEXTVAL,p_asset_id,'FAIL');

RAISE;
  1. 更好的是,處理自治事務中的日誌記錄。這意味著它是一個獨立的事務,不受主事務中發生的任何事情的影響。對於日誌記錄,您需要這個。
CREATE OR REPLACE PROCEDURE log_audit(
  p_asset_id NUMBER,
  p_status VARCHAR
) AS
  PRAGMA AUTONOMOUS TRANSACTION
BEGIN
  INSERT INTO z_audit_history(audit_history_id, asset_id, status)
  VALUES(seq_audit_history_id.NEXTVAL, p_asset_id, p_status);
END;

並稱它為

DBMS_OUTPUT.PUT_LINE('Whoops');

ROLLBACK TO sp_sptest;

log_audit(p_asset_id, 'FAIL');

RAISE;
  1. 你會得到一個錯誤,因為你在回滾後引發了異常。

這是一件好事!

你不希望異常無聲無息地消失,你想知道它。

可以做的是處理您期望的異常。例如,如果您知道ORA-06512可能會發生並且您知道在這種情況下您需要做什麼,您可以為這種情況添加一個特定的處理程序,或者在您的儲存過程中,或者在呼叫它的程式碼中。

引用自:https://dba.stackexchange.com/questions/86011