PL SQL異常處理.
PL/SQL程式執行過程中出現的錯誤,稱之為異常。
PL/SQL程式的錯誤可分為兩類:
一類是PL/SQL語法錯誤,它由PL/SQL編譯器發現並給出錯誤資訊,
另一類是執行時錯誤,由PL/SQL執行時引擎發現並給出錯誤資訊。
異常分類:
PL/SQL語言的異常分為兩大類
一類是ORACLE系統異常
ORACLE系統異常又分為兩種,一種是預定義異常,另一種是非預定義異常。
另一類是自定義異常
(1)預定義異常
預定義異常是ORACLE系統異常中的一種,用於處理常見的ORACLE錯誤。ORACLE預定義異常的特點是,
ORACLE系統定義了它們的錯誤編號與異常名字。當執行PL/SQL程式碼產生預定義錯誤時,與錯誤對應的
預定義異常被自動丟擲,通過預定義異常名字捕獲該異常。
預定義異常與ORACLE錯誤編號之間的對應關係如下所示:
預定義異常 Oracle錯誤 錯誤程式碼 描述
ACCESS_INTO_NULL ORA-06530 -6530 試圖給一個沒有初始化(為NULL)的物件賦值
CASE_NOT_FOUND ORA-06592 -6592 在CASE語句中沒有WHEN子句被選擇,並且沒
有ELSE子句
COLLECTION_IS_NULLORA-06531 -6531 試圖將EXISTS以外的集合(collection)方法
應用到一個沒有被初始化(為NULL)的巢狀表
(nested table)和變長陣列(varray)中,
或者試圖給沒有初始化的巢狀表
(nested table)或變長陣列()varray中的
元素賦值
CURSOR_ALREADY_OPENORA-06511 -6511 試圖開啟一個已經開啟的遊標,一個遊標在它
重新開啟前必須被關閉。一個遊標FOR迴圈會
自動地開啟所涉及的遊標,所以在遊標迴圈裡
不能開啟遊標
DUL_VAL_ON_INDEX ORA-00001 -1 試圖在一個有惟一性約束的資料庫列中儲存重複的值
INVALID_CURSOR ORA-01001 -1001 試圖執行一個無效的遊標操作
INVALID_NUMBER ORA-01722 -1722 試圖將一個看起來不像是一個有效的數字的字
符串轉換成數字失敗時,而在過程性語句中,
將會引發VALUE_ERROR錯誤,代替
INVALID_NUMBER錯誤
LOGIN_DENIED ORA-01017 -1017 用一個無效的使用者名稱或口令去登陸Oracle
NO_DATA_FOUND ORA-01403 100 一個SELECT INTO語句沒有返回資料或者程式
引用一個巢狀表中被刪除的元素或索引表中一
個沒有被初始化的元素
NOT_LOGGED_ON ORA-01012 -1012 釋出一個資料庫呼叫指令而沒有連線到資料庫
PROGRAM_ERROR ORA-06501 -6501 Oracle內在錯誤,通常是由PL/SQL本身造成
的,這種情況下應該通知Oracle公司技術部門
ROWTYPE_MISMATCH ORA-06504 -6504 宿主遊標變數和PL/SQL遊標變數相關的作業有
著不相容的型別
SELF_IF_NULL ORA-30625 -30625 程式試圖呼叫一個空的例項的成員方法
STORAGE_ERROR ORA-06500 -6500 PL/SQL執行時記憶體不夠或者記憶體是有問題的
SUBSCRIPT_BEYOND_COUNT ORA-06533 -6533 引用一個巢狀表(nested table)或變長數
組(varray)的元素時索引值大於集合中元素
的數量
SUBSCRIPT_OUTSIDE_LIMIT ORA-06532 -6532 引用一個巢狀表(nested table)或變長數
組(varray)的元素時使用的索引值(例如
-1)超出了規定的範圍
SYS_INVALID_ROWID ORA-01410 -1410 試圖將一個看起來不像是一個有效的ROWID的字
符串轉換成一個ROWID時
TIMEOUT_ON_RESOURCE ORA-00051 -51 Oracle在等待資源時發生超時現象
TOO_MANY_ROWS ORA-01422 -1422 SELECT INTO語句返回了多行資料
VALUE_ERROR ORA-06502 -6502 一個演算法、轉換、截斷或者大小約束錯誤發生,
如果在SQL語句中發生錯誤則會引發
INVALID_ERROR錯誤,替代了VALUE_ERROR錯誤
ZERO_DIVIDE ORA-01476 -1476 發生被零除
(2)非預定義異常
也是ORACLE系統異常中的一種,用於處理預定義以外的ORACLE系統錯誤。ORACLE非預定義異常的特點
是,ORACLE系統定義了它們的錯誤編號,但沒有定義異常名字。這些ORACLE系統錯誤沒有預定義異
常(異常名字)與其關聯,需要在PL/SQL塊的宣告部分定義一個異常名字,然後通過偽過程
PRAGMA EXCEPTION_INIT 將該異常名字與一個ORACLE 錯誤編號相關聯。這樣,當執行PL/SQL程式碼
產生非預定義錯誤時,與錯誤程式碼對應的非預定義異常被自動丟擲,通過定義的異常名字捕獲該異常,
並對錯誤進行處理。
(3)自定義異常
自定義異常用於處理使用者定義錯誤,即處理與ORACLE系統錯誤無關的其錯誤。自定義異常是指有些操
作不會產生ORACLE系統錯誤,但是程式設計師從業務規則角度考慮,認為是一種錯誤。例如,執行UPDATE
操作沒有更新任何記錄行時,不會引發ORACLE系統錯誤,也不會發生異常。但是,有時需要開發人員
為此操作產生一個異常,以便進行處理,這就是使用者定義異常。
異常處理
PL/SQL程式中,異常處理按以下3個步驟進行:
定義異常
丟擲異常
捕獲及處理異常
(1)定義異常
如前所述,ORACLE中的異常分為預定義異常、非預定義異常和自定義異常,其中預定義異常
由系統隱式定義,而後兩種異常則需要使用者定義。定義異常的方法是在PL/SQL程式的宣告
部分定義一個EXCEPTION型別的變數,其格式為:
exception_name EXCEPTION;
其中exception_name 為異常名,如果 是非預定義異常,還需要使用偽過程,在編譯階段將
異常名與一個ORACLE錯誤程式碼相關聯,其語句格式為:
PRAGMA EXCEPTION_INIT(exception_name,error_number);
其中,exception_name為異常名,error_number為ORACLE系統內部錯誤號,用一個負位數
表示,-20999~-20000為使用者定義錯誤的保留號。
(2)丟擲異常
由於系統不能自動識別使用者定義錯誤,因此當產生自定義錯誤時,需要程式設計師使用特定的PL/SQL
程式碼丟擲相應的自定義異常。自定義異常的丟擲語句格式為:
RAISE exception_name;
(3)捕獲及處理異常
異常處理的基本格式為:
EXCEPTION
WHEN e_name1 [OR e_name2...] THEN
sequence of statements1;
WHEN e_name3 [OR e_name4...] THEN
sequence of statements2;
......
[WHEN OTHERS THEN
sequence of statementsn;]
END;
異常處理例項
處理預定義異常
例1:
DECLARE
v_dividend NUMBER:=50;
v_divisor NUMBER:=0;
v_quotient NUMBER;
BEGIN
v_quotient:=v_dividend/v_divisor;
EXCEPTION
WHEN ZERO_DIVIDE THEN
DBMS_OUTPUT.PUT_LINE('divisor is 0');
END;
/
例2:輸入員工編號,如果員工不存在,則提示錯誤
SQL> SET SERVEROUTPUT ON
DECLARE
v_id emp.empno%TYPE;
v_name emp.ename%TYPE;
BEGIN
v_id:=&inputid;
select ename INTO v_name FROM emp WHERE empno=v_id;
DBMS_OUTPUT.PUT_LINE('EMPNO = '||v_name);
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('NOT FOUND RECORD!');
END;
/
例3:使用兩種異常處理,避免找不到記錄和找到多條記錄而賦給一個變數的錯誤
DECLARE
v_job emp.job%TYPE;
v_name emp.ename%TYPE;
BEGIN
v_job:='&inputjob';
select ename INTO v_name FROM emp WHERE job=v_job;
DBMS_OUTPUT.PUT_LINE('EMPNO = '||v_name);
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('NOT FOUND RECORD!');
WHEN TOO_MANY_ROWS THEN
DBMS_OUTPUT.PUT_LINE('FOUND RECORD TOO MANY!');
END;
/
非預定義異常
也是ORACLE系統異常中的一種,用於處理預定義以外的ORACLE系統錯誤。ORACLE非預定義異常的特點
是,ORACLE系統定義了它們的錯誤編號,但沒有定義異常名字。這些ORACLE系統錯誤沒有預定義異
常(異常名字)與其關聯,需要在PL/SQL塊的宣告部分定義一個異常名字,然後通過偽過程
PRAGMA EXCEPTION_INIT 將該異常名字與一個ORACLE 錯誤編號相關聯。這樣,當執行PL/SQL程式碼
產生非預定義錯誤時,與錯誤程式碼對應的非預定義異常被自動丟擲,通過定義的異常名字捕獲該異常,
並對錯誤進行處理。
非預定義異常需要使用者定義異常名,而且還要使用偽過程,在編譯階段將異常名與一個ORACLE
錯誤程式碼相關聯。
例1:在dept刪除10號部門,試驗引用完整性約束異常
SQL> DECLARE
2 e_deptid EXCEPTION;
3 PRAGMA EXCEPTION_INIT(e_deptid,-2292);
4 BEGIN
5 DELETE FROM DEPT WHERE DEPTNO=&e_deptid ;
6 EXCEPTION
7 WHEN e_deptid THEN
8 DBMS_OUTPUT.PUT_LINE('at sub table have record!');
9 END;
10 /
輸入 e_deptid 的值: 20
原值 5: DELETE FROM DEPT WHERE DEPTNO=&e_deptid ;
新值 5: DELETE FROM DEPT WHERE DEPTNO=20 ;
at sub table have records !
PL/SQL 過程已成功完成。
SQL> DECLARE
2 e_deptid EXCEPTION;
3 PRAGMA EXCEPTION_INIT(e_deptid,-2292);
4 BEGIN
5 DELETE FROM DEPT WHERE DEPTNO=&e_deptid ;
6 EXCEPTION
7 WHEN e_deptid THEN
8 DBMS_OUTPUT.PUT_LINE('at sub table have record!');
9 END;
10 /
輸入 e_deptid 的值: 40
原值 5: DELETE FROM DEPT WHERE DEPTNO=&e_deptid ;
新值 5: DELETE FROM DEPT WHERE DEPTNO=40 ;
PL/SQL 過程已成功完成。
例2:在emp表中插入記錄,部門號為80,試驗參照完整性約束異常
DECLARE
e_deptid EXCEPTION;
PRAGMA EXCEPTION_INIT(e_deptid,-2291);
BEGIN
INSERT INTO EMP (EMPNO,DEPTNO) VALUES (8001,80);
EXCEPTION
WHEN e_deptid THEN
DBMS_OUTPUT.PUT_LINE('deptno 80 at table dept no exist !');
END;
/
deptno 80 at table dept no exist !
PL/SQL 過程已成功完成。
例3:在emp表中插入一條EMPNO存在的記錄
DECLARE
e_deptid EXCEPTION;
PRAGMA EXCEPTION_INIT(e_deptid,-0001);
BEGIN
INSERT INTO EMP (EMPNO,DEPTNO) VALUES (7788,10);
EXCEPTION
WHEN e_deptid THEN
DBMS_OUTPUT.PUT_LINE('record is exist !');
END;
/
SQL> select empno,deptno from emp where empno=7788;
EMPNO DEPTNO
---------- ----------
7788 10
自定義異常處理
自定義異常不僅需要使用者定義異常名字,還要程式設計師安排何時丟擲異常及對異常的處理。
例1:在emp中插入一條工資為負數的記錄。
DECLARE
e_sal EXCEPTION;
v_sal emp.sal%TYPE;
BEGIN
v_sal:=&inputsal;
IF v_sal<0 THEN
RAISE e_sal;
END IF;
INSERT INTO emp(empno,ename,sal) values (8002,'TEST',v_sal);
EXCEPTION
WHEN e_sal THEN
DBMS_OUTPUT.PUT_LINE('sal not < 0 !');
END;
/
輸入 inputsal 的值: -1000
原值 5: v_sal:=&inputsal;
新值 5: v_sal:=-1000;
sal not < 0 !
PL/SQL 過程已成功完成。
例2:帶有WHEN OTHERS THEN的異常處理
DECLARE
e_sal EXCEPTION;
v_sal emp.sal%TYPE;
BEGIN
v_sal:=&inputsal;
INSERT INTO emp(empno,ename,sal) values (8002,'TEST',v_sal);
IF v_sal<0 THEN
RAISE e_sal;
END IF;
EXCEPTION
WHEN e_sal THEN
DBMS_OUTPUT.PUT_LINE('sal not < 0 !');
rollback;
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('other error !');
rollback;
END;
/
使用異常函式
在PL/SQL程式碼執行出現錯誤時,通過使用異常函式可以獲得錯誤程式碼及相關的錯誤描述,
其中函式SQLCODE用於獲得ORACLE錯誤程式碼,而SQLERRM則用於獲得與之相應 的錯誤描述。
DECLARE
e_sal EXCEPTION;
v_sal emp.sal%TYPE;
v_empno emp.empno%TYPE;
v_deptno emp.deptno%TYPE;
BEGIN
v_sal:=&inputsal;
v_empno:=&inputempno;
v_deptno:=&inputdeptno;
INSERT INTO emp(empno,deptno,sal) values (v_empno,v_deptno,v_sal);
IF v_sal<0 THEN
RAISE e_sal;
END IF;
EXCEPTION
WHEN e_sal THEN
DBMS_OUTPUT.PUT_LINE('sal not < 0 !');
rollback;
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('error code:'||SQLCODE);
DBMS_OUTPUT.PUT_LINE('error desc:'||SQLERRM);
END;
/
第一種情況:
輸入 inputsal 的值: 100
原值 7: v_sal:=&inputsal;
新值 7: v_sal:= 100;
輸入 inputempno 的值: 100
原值 8: v_empno:=&inputempno;
新值 8: v_empno:=100;
輸入 inputdeptno 的值: 10
原值 9: v_deptno:=&inputdeptno;
新值 9: v_deptno:=10;
PL/SQL 過程已成功完成。
第二種情況:
輸入 inputsal 的值: -1000
原值 7: v_sal:=&inputsal;
新值 7: v_sal:= -1000;
輸入 inputempno 的值: 1000
原值 8: v_empno:=&inputempno;
新值 8: v_empno:=1000;
輸入 inputdeptno 的值: 20
原值 9: v_deptno:=&inputdeptno;
新值 9: v_deptno:=20;
sal not < 0 !
PL/SQL 過程已成功完成。
PL/SQL程式的錯誤可分為兩類:
一類是PL/SQL語法錯誤,它由PL/SQL編譯器發現並給出錯誤資訊,
另一類是執行時錯誤,由PL/SQL執行時引擎發現並給出錯誤資訊。
異常分類:
PL/SQL語言的異常分為兩大類
一類是ORACLE系統異常
ORACLE系統異常又分為兩種,一種是預定義異常,另一種是非預定義異常。
另一類是自定義異常
(1)預定義異常
預定義異常是ORACLE系統異常中的一種,用於處理常見的ORACLE錯誤。ORACLE預定義異常的特點是,
ORACLE系統定義了它們的錯誤編號與異常名字。當執行PL/SQL程式碼產生預定義錯誤時,與錯誤對應的
預定義異常被自動丟擲,通過預定義異常名字捕獲該異常。
預定義異常與ORACLE錯誤編號之間的對應關係如下所示:
預定義異常 Oracle錯誤 錯誤程式碼 描述
ACCESS_INTO_NULL ORA-06530 -6530 試圖給一個沒有初始化(為NULL)的物件賦值
CASE_NOT_FOUND ORA-06592 -6592 在CASE語句中沒有WHEN子句被選擇,並且沒
有ELSE子句
COLLECTION_IS_NULLORA-06531 -6531 試圖將EXISTS以外的集合(collection)方法
應用到一個沒有被初始化(為NULL)的巢狀表
(nested table)和變長陣列(varray)中,
或者試圖給沒有初始化的巢狀表
(nested table)或變長陣列()varray中的
元素賦值
CURSOR_ALREADY_OPENORA-06511 -6511 試圖開啟一個已經開啟的遊標,一個遊標在它
重新開啟前必須被關閉。一個遊標FOR迴圈會
自動地開啟所涉及的遊標,所以在遊標迴圈裡
不能開啟遊標
DUL_VAL_ON_INDEX ORA-00001 -1 試圖在一個有惟一性約束的資料庫列中儲存重複的值
INVALID_CURSOR ORA-01001 -1001 試圖執行一個無效的遊標操作
INVALID_NUMBER ORA-01722 -1722 試圖將一個看起來不像是一個有效的數字的字
符串轉換成數字失敗時,而在過程性語句中,
將會引發VALUE_ERROR錯誤,代替
INVALID_NUMBER錯誤
LOGIN_DENIED ORA-01017 -1017 用一個無效的使用者名稱或口令去登陸Oracle
NO_DATA_FOUND ORA-01403 100 一個SELECT INTO語句沒有返回資料或者程式
引用一個巢狀表中被刪除的元素或索引表中一
個沒有被初始化的元素
NOT_LOGGED_ON ORA-01012 -1012 釋出一個資料庫呼叫指令而沒有連線到資料庫
PROGRAM_ERROR ORA-06501 -6501 Oracle內在錯誤,通常是由PL/SQL本身造成
的,這種情況下應該通知Oracle公司技術部門
ROWTYPE_MISMATCH ORA-06504 -6504 宿主遊標變數和PL/SQL遊標變數相關的作業有
著不相容的型別
SELF_IF_NULL ORA-30625 -30625 程式試圖呼叫一個空的例項的成員方法
STORAGE_ERROR ORA-06500 -6500 PL/SQL執行時記憶體不夠或者記憶體是有問題的
SUBSCRIPT_BEYOND_COUNT ORA-06533 -6533 引用一個巢狀表(nested table)或變長數
組(varray)的元素時索引值大於集合中元素
的數量
SUBSCRIPT_OUTSIDE_LIMIT ORA-06532 -6532 引用一個巢狀表(nested table)或變長數
組(varray)的元素時使用的索引值(例如
-1)超出了規定的範圍
SYS_INVALID_ROWID ORA-01410 -1410 試圖將一個看起來不像是一個有效的ROWID的字
符串轉換成一個ROWID時
TIMEOUT_ON_RESOURCE ORA-00051 -51 Oracle在等待資源時發生超時現象
TOO_MANY_ROWS ORA-01422 -1422 SELECT INTO語句返回了多行資料
VALUE_ERROR ORA-06502 -6502 一個演算法、轉換、截斷或者大小約束錯誤發生,
如果在SQL語句中發生錯誤則會引發
INVALID_ERROR錯誤,替代了VALUE_ERROR錯誤
ZERO_DIVIDE ORA-01476 -1476 發生被零除
(2)非預定義異常
也是ORACLE系統異常中的一種,用於處理預定義以外的ORACLE系統錯誤。ORACLE非預定義異常的特點
是,ORACLE系統定義了它們的錯誤編號,但沒有定義異常名字。這些ORACLE系統錯誤沒有預定義異
常(異常名字)與其關聯,需要在PL/SQL塊的宣告部分定義一個異常名字,然後通過偽過程
PRAGMA EXCEPTION_INIT 將該異常名字與一個ORACLE 錯誤編號相關聯。這樣,當執行PL/SQL程式碼
產生非預定義錯誤時,與錯誤程式碼對應的非預定義異常被自動丟擲,通過定義的異常名字捕獲該異常,
並對錯誤進行處理。
(3)自定義異常
自定義異常用於處理使用者定義錯誤,即處理與ORACLE系統錯誤無關的其錯誤。自定義異常是指有些操
作不會產生ORACLE系統錯誤,但是程式設計師從業務規則角度考慮,認為是一種錯誤。例如,執行UPDATE
操作沒有更新任何記錄行時,不會引發ORACLE系統錯誤,也不會發生異常。但是,有時需要開發人員
為此操作產生一個異常,以便進行處理,這就是使用者定義異常。
異常處理
PL/SQL程式中,異常處理按以下3個步驟進行:
定義異常
丟擲異常
捕獲及處理異常
(1)定義異常
如前所述,ORACLE中的異常分為預定義異常、非預定義異常和自定義異常,其中預定義異常
由系統隱式定義,而後兩種異常則需要使用者定義。定義異常的方法是在PL/SQL程式的宣告
部分定義一個EXCEPTION型別的變數,其格式為:
exception_name EXCEPTION;
其中exception_name 為異常名,如果 是非預定義異常,還需要使用偽過程,在編譯階段將
異常名與一個ORACLE錯誤程式碼相關聯,其語句格式為:
PRAGMA EXCEPTION_INIT(exception_name,error_number);
其中,exception_name為異常名,error_number為ORACLE系統內部錯誤號,用一個負位數
表示,-20999~-20000為使用者定義錯誤的保留號。
(2)丟擲異常
由於系統不能自動識別使用者定義錯誤,因此當產生自定義錯誤時,需要程式設計師使用特定的PL/SQL
程式碼丟擲相應的自定義異常。自定義異常的丟擲語句格式為:
RAISE exception_name;
(3)捕獲及處理異常
異常處理的基本格式為:
EXCEPTION
WHEN e_name1 [OR e_name2...] THEN
sequence of statements1;
WHEN e_name3 [OR e_name4...] THEN
sequence of statements2;
......
[WHEN OTHERS THEN
sequence of statementsn;]
END;
異常處理例項
處理預定義異常
例1:
DECLARE
v_dividend NUMBER:=50;
v_divisor NUMBER:=0;
v_quotient NUMBER;
BEGIN
v_quotient:=v_dividend/v_divisor;
EXCEPTION
WHEN ZERO_DIVIDE THEN
DBMS_OUTPUT.PUT_LINE('divisor is 0');
END;
/
例2:輸入員工編號,如果員工不存在,則提示錯誤
SQL> SET SERVEROUTPUT ON
DECLARE
v_id emp.empno%TYPE;
v_name emp.ename%TYPE;
BEGIN
v_id:=&inputid;
select ename INTO v_name FROM emp WHERE empno=v_id;
DBMS_OUTPUT.PUT_LINE('EMPNO = '||v_name);
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('NOT FOUND RECORD!');
END;
/
例3:使用兩種異常處理,避免找不到記錄和找到多條記錄而賦給一個變數的錯誤
DECLARE
v_job emp.job%TYPE;
v_name emp.ename%TYPE;
BEGIN
v_job:='&inputjob';
select ename INTO v_name FROM emp WHERE job=v_job;
DBMS_OUTPUT.PUT_LINE('EMPNO = '||v_name);
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('NOT FOUND RECORD!');
WHEN TOO_MANY_ROWS THEN
DBMS_OUTPUT.PUT_LINE('FOUND RECORD TOO MANY!');
END;
/
非預定義異常
也是ORACLE系統異常中的一種,用於處理預定義以外的ORACLE系統錯誤。ORACLE非預定義異常的特點
是,ORACLE系統定義了它們的錯誤編號,但沒有定義異常名字。這些ORACLE系統錯誤沒有預定義異
常(異常名字)與其關聯,需要在PL/SQL塊的宣告部分定義一個異常名字,然後通過偽過程
PRAGMA EXCEPTION_INIT 將該異常名字與一個ORACLE 錯誤編號相關聯。這樣,當執行PL/SQL程式碼
產生非預定義錯誤時,與錯誤程式碼對應的非預定義異常被自動丟擲,通過定義的異常名字捕獲該異常,
並對錯誤進行處理。
非預定義異常需要使用者定義異常名,而且還要使用偽過程,在編譯階段將異常名與一個ORACLE
錯誤程式碼相關聯。
例1:在dept刪除10號部門,試驗引用完整性約束異常
SQL> DECLARE
2 e_deptid EXCEPTION;
3 PRAGMA EXCEPTION_INIT(e_deptid,-2292);
4 BEGIN
5 DELETE FROM DEPT WHERE DEPTNO=&e_deptid ;
6 EXCEPTION
7 WHEN e_deptid THEN
8 DBMS_OUTPUT.PUT_LINE('at sub table have record!');
9 END;
10 /
輸入 e_deptid 的值: 20
原值 5: DELETE FROM DEPT WHERE DEPTNO=&e_deptid ;
新值 5: DELETE FROM DEPT WHERE DEPTNO=20 ;
at sub table have records !
PL/SQL 過程已成功完成。
SQL> DECLARE
2 e_deptid EXCEPTION;
3 PRAGMA EXCEPTION_INIT(e_deptid,-2292);
4 BEGIN
5 DELETE FROM DEPT WHERE DEPTNO=&e_deptid ;
6 EXCEPTION
7 WHEN e_deptid THEN
8 DBMS_OUTPUT.PUT_LINE('at sub table have record!');
9 END;
10 /
輸入 e_deptid 的值: 40
原值 5: DELETE FROM DEPT WHERE DEPTNO=&e_deptid ;
新值 5: DELETE FROM DEPT WHERE DEPTNO=40 ;
PL/SQL 過程已成功完成。
例2:在emp表中插入記錄,部門號為80,試驗參照完整性約束異常
DECLARE
e_deptid EXCEPTION;
PRAGMA EXCEPTION_INIT(e_deptid,-2291);
BEGIN
INSERT INTO EMP (EMPNO,DEPTNO) VALUES (8001,80);
EXCEPTION
WHEN e_deptid THEN
DBMS_OUTPUT.PUT_LINE('deptno 80 at table dept no exist !');
END;
/
deptno 80 at table dept no exist !
PL/SQL 過程已成功完成。
例3:在emp表中插入一條EMPNO存在的記錄
DECLARE
e_deptid EXCEPTION;
PRAGMA EXCEPTION_INIT(e_deptid,-0001);
BEGIN
INSERT INTO EMP (EMPNO,DEPTNO) VALUES (7788,10);
EXCEPTION
WHEN e_deptid THEN
DBMS_OUTPUT.PUT_LINE('record is exist !');
END;
/
SQL> select empno,deptno from emp where empno=7788;
EMPNO DEPTNO
---------- ----------
7788 10
自定義異常處理
自定義異常不僅需要使用者定義異常名字,還要程式設計師安排何時丟擲異常及對異常的處理。
例1:在emp中插入一條工資為負數的記錄。
DECLARE
e_sal EXCEPTION;
v_sal emp.sal%TYPE;
BEGIN
v_sal:=&inputsal;
IF v_sal<0 THEN
RAISE e_sal;
END IF;
INSERT INTO emp(empno,ename,sal) values (8002,'TEST',v_sal);
EXCEPTION
WHEN e_sal THEN
DBMS_OUTPUT.PUT_LINE('sal not < 0 !');
END;
/
輸入 inputsal 的值: -1000
原值 5: v_sal:=&inputsal;
新值 5: v_sal:=-1000;
sal not < 0 !
PL/SQL 過程已成功完成。
例2:帶有WHEN OTHERS THEN的異常處理
DECLARE
e_sal EXCEPTION;
v_sal emp.sal%TYPE;
BEGIN
v_sal:=&inputsal;
INSERT INTO emp(empno,ename,sal) values (8002,'TEST',v_sal);
IF v_sal<0 THEN
RAISE e_sal;
END IF;
EXCEPTION
WHEN e_sal THEN
DBMS_OUTPUT.PUT_LINE('sal not < 0 !');
rollback;
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('other error !');
rollback;
END;
/
使用異常函式
在PL/SQL程式碼執行出現錯誤時,通過使用異常函式可以獲得錯誤程式碼及相關的錯誤描述,
其中函式SQLCODE用於獲得ORACLE錯誤程式碼,而SQLERRM則用於獲得與之相應 的錯誤描述。
DECLARE
e_sal EXCEPTION;
v_sal emp.sal%TYPE;
v_empno emp.empno%TYPE;
v_deptno emp.deptno%TYPE;
BEGIN
v_sal:=&inputsal;
v_empno:=&inputempno;
v_deptno:=&inputdeptno;
INSERT INTO emp(empno,deptno,sal) values (v_empno,v_deptno,v_sal);
IF v_sal<0 THEN
RAISE e_sal;
END IF;
EXCEPTION
WHEN e_sal THEN
DBMS_OUTPUT.PUT_LINE('sal not < 0 !');
rollback;
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('error code:'||SQLCODE);
DBMS_OUTPUT.PUT_LINE('error desc:'||SQLERRM);
END;
/
第一種情況:
輸入 inputsal 的值: 100
原值 7: v_sal:=&inputsal;
新值 7: v_sal:= 100;
輸入 inputempno 的值: 100
原值 8: v_empno:=&inputempno;
新值 8: v_empno:=100;
輸入 inputdeptno 的值: 10
原值 9: v_deptno:=&inputdeptno;
新值 9: v_deptno:=10;
PL/SQL 過程已成功完成。
第二種情況:
輸入 inputsal 的值: -1000
原值 7: v_sal:=&inputsal;
新值 7: v_sal:= -1000;
輸入 inputempno 的值: 1000
原值 8: v_empno:=&inputempno;
新值 8: v_empno:=1000;
輸入 inputdeptno 的值: 20
原值 9: v_deptno:=&inputdeptno;
新值 9: v_deptno:=20;
sal not < 0 !
PL/SQL 過程已成功完成。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/28894640/viewspace-1061167/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- SQL Server 異常程式碼處理SQLServer
- 異常篇——異常處理
- 異常處理
- 在 SQL Server 中使用 Try Catch 處理異常SQLServer
- JSP 異常處理如何處理?JS
- 異常-throws的方式處理異常
- 異常的處理
- golang - 異常處理Golang
- 異常處理2
- 異常處理1
- oracle異常處理Oracle
- Java 異常處理Java
- Python——異常處理Python
- Python異常處理Python
- ThinkPHP 異常處理PHP
- JavaScript 異常處理JavaScript
- JAVA異常處理Java
- Abp 異常處理
- JAVA 異常處理Java
- 08、異常處理
- SpringMVC異常處理SpringMVC
- React 異常處理React
- JS異常處理JS
- 異常處理機制(二)之異常處理與捕獲
- Java 異常表與異常處理原理Java
- restframework 異常處理及自定義異常RESTFramework
- springboot下新增全域性異常處理和自定義異常處理Spring Boot
- 14. 異常處理
- 異常處理機制
- 異常處理全面解析
- 異常處理方式throws
- 處理多個異常
- Spring Boot 異常處理Spring Boot
- SpringBoot中異常處理Spring Boot
- Python Selenium異常處理Python
- PHP 核心 - 異常處理PHP
- GRpc異常處理FilterRPCFilter
- python異常捕捉處理Python
- 【SpringMVC】 4.2 異常處理SpringMVC