Oracle 存儲過程異常處理


Oracle提供了三種異常處理方式:

1:預定義異常        用於處理常見的Oracle錯誤
2:非預定義異常     用於處理預定義異常所不能處理的Oracle錯誤
3:自定義異常        用於處理於Oracle錯誤無關的其他情況

語法:
EXCEPTION
  WHEN exception_Name THEN  --exception_Name為異常的名字
       statement1;
  WHEN OTHERS THEN
   statement1;

一、 處理預定義異常,系統預定的21種類型  

命名的系統異常     產生原因
access_into_null     未定義對象
case_not_found        case中若未包含相應的when,並且沒有設置
collection_is_null     集合元素未初始化
curser_already_open     游標已經打開
dup_val_on_index     唯一索引對應的列上有重復的值
invalid_cursor      在不合法的游標上進行操作
invalid_number     內嵌的 sql 語句不能將字符轉換為數字 
no_data_found      使用 select into   未返回行,或應用索引表未初始化的 
too_many_rows      執行 select into   時,結果集超過一行
zero_divide      除數為 0
subscript_beyond_count     元素下標超過嵌套表或varray的最大值
subscript_outside_limit     使用嵌套表或 varray   時,將下標指定為負數
value_error        賦值時,變量長度不足以容納實際數據
login_denied      pl/sql 應用程序連接到   oracle 數據庫時,提供了不正確的用戶名或密碼
not_logged_on      pl/sql   應用程序在沒有連接 oralce 數據庫的情況下訪問數據
program_error       pl/sql   內部問題,可能需要重裝數據字典& pl./sql系統包
rowtype_mismatch       主游標變量與 pl/sql 游標變量的返回類型不兼容
self_is_null      使用對象類型時,在 null   對象上調用對象方法
storage_error      運行 pl/sql   時,超出內存空間
sys_invalid_id      無效的 rowid 字符串
timeout_on_resource     oracle 在等待資源時超時

二、處理非預定義異常

 使用非預定義異常包括三步:
1、在定義部分定義異常名,
2、在異常和Oracle錯誤之間建立關聯,
3、在異常處理部分捕捉並處理異常。 

當定義Oracle錯誤和異常之間的關聯關系時,需要使用偽過程EXCEPTION_INIT。
1、首先的定義部分定義異常,
2、使用progma exception_init(exception_name,exception_number) 在異常和oracle錯誤之間建立關聯,
     這時要求用戶知道可能出現的錯誤號(異常函數sqlcode、sqlerrm和 raise_application_error);
3、最終在異常處理部分捕捉並處理異常。

下面以更新特定雇員的部門號,並處理ORA-02291錯誤為例,說明使用非預定義異常的方法。示例如下:

DECLARE
  e_integrity EXCEPTION; --1、定義部分
  PRAGMA EXCEPTION_INIT (e_integrity, -2291);  --2、建立關聯關系
BEGIN
  UPDATE emp SET deptno= &dno WHERE empno = &eno;
EXCEPTION
  WHEN e_integrity THEN  --3、捕捉處理
    DBMS_OUTPUT.PUT_LINE(‘該部門不存在’);
END;
View Code

三、處理自定義異常
預定義異常和非預定義異常都與Oracle錯誤有關,並且當出現Oracle錯誤時會隱含觸發相應異常;
而自定義異常與Oracle錯誤沒有任何關聯,它是由開發人員為特定情況所定義的異常。 
當使用自定義異常時,
1、需要在定義部分(DECLARE)定義異常,
2、再執行部分(BEGIN)觸發異常(使用RAISE語句),
3、在異常處理部分(EXCEPTION)捕捉並處理異常。 

CREATE TABLE errlog(
  Errcode NUMBER,
  Errtext CHAR(40));

CREATE OR REPLACE FUNCTION get_salary(p_deptno NUMBER)
RETURN NUMBER 
AS
  v_sal NUMBER;
BEGIN
  IF p_deptno IS NULL THEN
    RAISE_APPLICATION_ERROR(-20991, ’部門代碼為空’);
  ELSIF p_deptno<0 THEN
    RAISE_APPLICATION_ERROR(-20992, ’無效的部門代碼’);
  ELSE
    SELECT SUM(employees.salary) INTO v_sal FROM employees 
    WHERE employees.department_id=p_deptno;
    RETURN v_sal;
  END IF;
END;

DECLARE 
  V_salary NUMBER(7,2);
  V_sqlcode NUMBER;
  V_sqlerr VARCHAR2(512);
  Null_deptno EXCEPTION;
  Invalid_deptno EXCEPTION;
  PRAGMA EXCEPTION_INIT(null_deptno,-20991);
  PRAGMA EXCEPTION_INIT(invalid_deptno, -20992);
BEGIN
  V_salary :=get_salary(10);
  DBMS_OUTPUT.PUT_LINE('10號部門工資:' || TO_CHAR(V_salary));

  BEGIN
    V_salary :=get_salary(-10);
  EXCEPTION
    WHEN invalid_deptno THEN
      V_sqlcode :=SQLCODE;
      V_sqlerr  :=SQLERRM;
      INSERT INTO errlog(errcode, errtext) 
      VALUES(v_sqlcode, v_sqlerr);
      COMMIT;
  END inner1;

  V_salary :=get_salary(20);
  DBMS_OUTPUT.PUT_LINE('部門號為20的工資為:'||TO_CHAR(V_salary));

  BEGIN
    V_salary :=get_salary(NULL);
  END inner2;

  V_salary := get_salary(30);
  DBMS_OUTPUT.PUT_LINE('部門號為30的工資為:'||TO_CHAR(V_salary));

  EXCEPTION
    WHEN null_deptno THEN
      V_sqlcode :=SQLCODE;
      V_sqlerr  :=SQLERRM;
      INSERT INTO errlog(errcode, errtext) VALUES(v_sqlcode, v_sqlerr);
      COMMIT;
    WHEN OTHERS THEN
         DBMS_OUTPUT.PUT_LINE(SQLCODE||'---'||SQLERRM);
END outer;
View Code

 


免責聲明!

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



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