Oracle異常錯誤處理


一、ORACLE 提供異常情況(EXCEPTION)和異常處理(EXCEPTION HANDLER)來實現錯誤處理。

1.異常處理的概念。

異常情況處理(EXCEPTION)是用來處理正常執行過程中未預料的事件,程序塊的異常處理預定義的錯誤和自定義錯誤,由於PL/SQL程序塊一旦產生異常而沒有指出如何處理時,程序就會自動終止整個程序運行.

2.異常處理的類型。

  預定義 ( Predefined )錯誤:ORACLE預定義的異常情況大約有24個。對這種異常情況的處理,無需在程序中定義,由ORACLE自動將其引發。

  非預定義 ( Predefined )錯誤:即其他標准的ORACLE錯誤。對這種異常情況的處理,需要用戶在程序中定義,然后由ORACLE自動將其引發。

  用戶定義(User_define) 錯誤:程序執行過程中,出現編程人員認為的非正常情況。對這種異常情況的處理,需要用戶在程序中定義,然后顯式地在程序中將其引發。

3.異常處理的語句。

異常處理部分一般放在 PL/SQL 程序體的后半部,結構為:

EXCEPTION
   WHEN first_exception THEN  <code to handle first exception >
   WHEN second_exception THEN  <code to handle second exception >
   WHEN OTHERS THEN  <code to handle others exception >
END;

4.24個預定義的異常處理。

 

錯誤號

異常錯誤信息名稱

說明

ORA-0001

Dup_val_on_index

違反了唯一性限制

ORA-0051

Timeout-on-resource

在等待資源時發生超時

ORA-0061

Transaction-backed-out

由於發生死鎖事務被撤消

ORA-1001

Invalid-CURSOR

試圖使用一個無效的游標

ORA-1012

Not-logged-on

沒有連接到ORACLE

ORA-1017

Login-denied

無效的用戶名/口令

ORA-1403

No_data_found

SELECT INTO沒有找到數據

ORA-1422

Too_many_rows

SELECT INTO 返回多行

ORA-1476

Zero-divide

試圖被零除

ORA-1722

Invalid-NUMBER

轉換一個數字失敗

ORA-6500

Storage-error

內存不夠引發的內部錯誤

ORA-6501

Program-error

內部錯誤

ORA-6502

Value-error

轉換或截斷錯誤

ORA-6504

Rowtype-mismatch

宿主游標變量與 PL/SQL變量有不兼容行類型

ORA-6511

CURSOR-already-OPEN

試圖打開一個已處於打開狀態的游標

ORA-6530

Access-INTO-null

試圖為null 對象的屬性賦值

ORA-6531

Collection-is-null

試圖將Exists 以外的集合( collection)方法應用於一個null pl/sql 表上或varray上

ORA-6532

Subscript-outside-limit

對嵌套或varray索引得引用超出聲明范圍以外

ORA-6533

Subscript-beyond-count

對嵌套或varray 索引得引用大於集合中元素的個數.

    

 
   

二、三種異常的處理的基本介紹和語法。

假如實例表如下:

-- Create table
create table G_TEST_SAL
(
  sid    NUMBER,
  sname  CHAR(5),
  salary BINARY_FLOAT,
  time   TIMESTAMP(6)
)
tablespace TBS_RPT
  pctfree 10
  initrans 1
  maxtrans 255
  storage
  (
    initial 64K
    minextents 1
    maxextents unlimited
  );


-- 插入數據
insert into G_Test_SAL values(1,'gal1',3000,to_timestamp('2000-1-1 0:0:0.0', 'syyyy-mm-dd hh24:mi:ss.ff'));
insert into G_Test_SAL values(2,'gal2',3050,to_timestamp('2000-1-1 0:0:0.0', 'syyyy-mm-dd hh24:mi:ss.ff'));
commit;

 

1.預定義的異常處理。

預定義的異常情況的處理,只需在PL/SQL塊的異常處理部分,直接引用相應的異常情況名,並對其完成相應的異常錯誤處理即可。

----異常處理
---例1:更新指定員工工資,如工資小於1500,則加100;
DECLARE
   v_empno G_Test_SAL.Sid%TYPE := &empno;  ----%TYpe  此句的含義是定義一個變量v_empno,變量類型為G_Test_SAL.Sid的字段類型,而且一旦G_Test_SAL.Sid類型變化,v_empno的類型也變化
                                           ----:=  是賦值的含義
                                           ----&的含義是empno變量由外部手動錄入
   v_sal   G_Test_SAL.Salary%TYPE;
BEGIN
   SELECT Salary INTO v_sal FROM G_Test_SAL WHERE Sid = v_empno;  -- select into
   IF v_sal<=1500 THEN 
        UPDATE G_Test_SAL SET Salary = Salary + 100 WHERE Sid=v_empno; 
        DBMS_OUTPUT.PUT_LINE('編碼為'||v_empno||'員工工資已更新!');     --||字符串連接符
   ELSE
        DBMS_OUTPUT.PUT_LINE('編碼為'||v_empno||'員工工資已經超過規定值!');
   END IF;
   
EXCEPTION
   WHEN NO_DATA_FOUND THEN  
      DBMS_OUTPUT.PUT_LINE('數據庫中沒有編碼為'||v_empno||'的員工');
   WHEN TOO_MANY_ROWS THEN
      DBMS_OUTPUT.PUT_LINE('程序運行錯誤!請使用游標');
   WHEN OTHERS THEN
      DBMS_OUTPUT.PUT_LINE(SQLCODE||'---'||SQLERRM);
END; 

 

執行上面的語句,並輸入異常empno 如下圖:

 

  

2. 非預定義的異常處理。

對於這類異常情況的處理,首先必須對非定義的ORACLE錯誤進行定義。步驟如下:

1. 在PL/SQL 塊的定義部分定義異常情況:

<異常情況>  EXCEPTION;

 

2. 將其定義好的異常情況,與標准的ORACLE錯誤聯系起來,使用EXCEPTION_INIT語句:

PRAGMA EXCEPTION_INIT(<異常情況>, <錯誤代碼>);

 

3. 在PL/SQL 塊的異常情況處理部分對異常情況做出相應的處理。

--非預定義異常處理
--例2:刪除指定員工的記錄信息

DECLARE
    v_empno G_Test_SAL.Sid%TYPE := &empno;
    empno_remaining EXCEPTION;
   PRAGMA EXCEPTION_INIT(empno_remaining, -2292);
   /* -2292 是違反一致性約束的錯誤代碼 */
BEGIN
   DELETE FROM G_Test_SAL WHERE Sid = v_empno;
EXCEPTION
   WHEN empno_remaining THEN 
      DBMS_OUTPUT.PUT_LINE('違反數據完整性約束!');
   WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(SQLCODE||'---'||SQLERRM); END;

 3.用戶自定義的異常處理

當與一個異常錯誤相關的錯誤出現時,就會隱含觸發該異常錯誤。用戶定義的異常錯誤是通過顯式使用 RAISE 語句來觸發。當引發一個異常錯誤時,控制就轉向到 EXCEPTION塊異常錯誤部分,執行錯誤處理代碼。

對於這類異常情況的處理,步驟如下:

1. 在PL/SQL 塊的定義部分定義異常情況:

<異常情況>  EXCEPTION;

2. RAISE <異常情況>;

3. 在PL/SQL 塊的異常情況處理部分對異常情況做出相應的處理。

 

---------------------------自定義的異常處理--------------------------------
--例3:更新指定員工工資,增加100;


DECLARE
   v_empno employees.employee_id%TYPE :=&empno;
   no_result  EXCEPTION;
BEGIN
   UPDATE employees SET salary = salary+100 WHERE employee_id = v_empno;
   IF SQL%NOTFOUND THEN        -----------SQL%NOTFOUND 是一個布爾值。與最近的sql語句(update,insert,delete,select)發生交互,當最近的一條sql語句沒有涉及任何行的時候,則返回true。否則返回false。
      RAISE no_result;
   END IF;
EXCEPTION
   WHEN no_result THEN 
      DBMS_OUTPUT.PUT_LINE('你的數據更新語句失敗了!');
   WHEN OTHERS THEN
      DBMS_OUTPUT.PUT_LINE(SQLCODE||'---'||SQLERRM);
END;

 

三、在 PL/SQL 中使用 SQLCODE, SQLERRM異常處理函數。

SQLCODE  返回遇到的Oracle錯誤號。

SQLERRM  返回遇到的Oracle錯誤信息.

目前項目中遇到的各種處理信息,我們都放在了一張日志表中。

1.第一種直接寫入日志表。

-------------------第一種-----------------------------
----日志表:
R_SQLRunLog(err_time char(19),err_code number,err_msg varchar2(200),info varchar2(200))
----異常處理:
WHEN OTHERS THEN
  v_ErrCode   = SQLCODE
  v_ErrTxt  = SUBSTR(SQLERRM,1,200);
  INSERT INTO R_SqlRunLog(err_time,err_code,err_msg,info)
    values(to_char(sysdate,'yyyy-mm-dd HH24:MI:SS'),v_ErrCode,v_ErrTxt,'用戶加入存儲過程或函數名稱');

 

2.第二種調用存儲過程,當我們每次執行一個操作的時候,都會調用此過程來將錯誤信息添加到一個日志表中。

--------------------------------第二種---------------------------------------------
CREATE
OR REPLACE PROCEDURE PETL.P_ETL_LOG_WRT (v_txdate IN VARCHAR2, v_serialno IN NUMBER, v_stepnum IN NUMBER, v_dealtype IN VARCHAR2, v_dealtab IN VARCHAR2, v_errcode IN NUMBER, v_errstate IN VARCHAR2, v_rcount IN NUMBER, v_dealprc IN VARCHAR2) AS ---------------------------------------------------------------------------------------- -- 名 稱:日志記錄存儲過程 -- 功能說明:記錄日志 -- 源表信息: -- 目 標 表:PETL.ETL_JOB_LOG -- 創建信息: -- 修改項1 : -- 修改項2 : ---------------------------------------------------------------------------------------- BEGIN INSERT INTO PETL.ETL_JOB_LOG VALUES(v_txdate,v_serialno,v_stepnum,v_dealtype,v_dealtab,TO_CHAR(SYSDATE,'YYYY-MM-DD HH24:MI:SS'),v_errcode,v_errstate,v_rcount,0,v_dealprc); COMMIT; END;

 

若您發現我侵犯了您的版權,請及時與我聯系。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM