目錄
PL/SQL異常
即運行時發生的錯誤。
異常的觸發:
- 發生一個oracle錯誤時
- 使用RAISE子句顯式觸發
處理異常:
- 處理機截獲
- 在調用環境中異常傳播
例子:
DECLARE
v_ename emp.ename%TYPE;
v_empno NUMBER(4) := 7369;
BEGIN
select ename
into v_ename
from emp
where empno=v_empno;
dbms_output.put_line(v_ename);
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line('others');
END;
正常運行,輸出SMITH
當修改爲不存在的員工號時
DECLARE
v_ename emp.ename%TYPE;
v_empno NUMBER(4) := 736;
BEGIN
select ename
into v_ename
from emp
where empno=v_empno;
dbms_output.put_line(v_ename);
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line('others');
END;
沒有這個數據,輸出others;如果沒有異常處理的話,程序則會終止掉。
異常類型
異常 | 描述 | 處理 |
Oracle服務器預定義異常 | Oracle中有名字的錯誤 | 不需聲明,可以由Oracle服務器隱式地觸發 |
Oracle 服務器非預定義的異常 | 其它所有非標準的Oracle服務器錯誤 | 在聲明部分聲明,可以由Oracle服務器隱式地觸發 |
用戶定義異常 | 由開發者決定的異常情形 | 在聲明部分聲明,由程序顯式地觸發 |
語法:
EXCEPTION
WHEN exception1 [or exception2...] THEN
statement;statement;...
WHEN exception3 [or exception4...]THEN
statement;statement;...
[WHEN OTHERS THEN
statement;statement;...]
注意:
- 在異常部分WHEN子句沒有數量限制
- WHEN OTHERS 是最後一 個子句
- 異常處理部分從關鍵字EXCEPTION開始
- 當異常拋出後,控制無條件轉到異常處理部分
- 在離開塊之前只能執行一種異常處理
當程序出了異常的時候,程序正常的流程就不再走了。
預定義異常
異常情況名 | 錯誤代碼 | 描述 |
DUP_VAL_ON_INDEX | 0RA-00001 | 試圖更新或插入重複記錄 |
INVALID_CURSOR | 0RA-01001 | 非法遊標操作 |
INVALID_NUMBER | 0RA-01722 | 字符串向數字轉換失敗 |
NO_DATA_FOUND | ORA-01403 | 執行的SELECT沒有查到數據 |
TOO_MANY_ROWS | ORA-01427 | 未使用遊標,SELECT語句返回了多行數據 |
VALUE_ERROR | 0RA-06502 | 出現數字、數據轉換、字符串或限制型錯誤 |
ZERO_DIVIDE | ORA-01476 | 被零除 |
非預定義異常
Oracle錯誤但是隻有代碼沒有名字。
DECLARE
e_emp_cons EXCPTION;
PRAGMA EXCEPTION_ INIT(e_emp_cons,-00001);
捕獲異常的函數
- SQLCODE:返回錯誤代碼
- SQLERRM:返回錯誤值相關聯的信息
例子
DECLARE
v_ename emp.ename%TYPE;
v_empno NUMBER(4) := 736;
BEGIN
select ename
into v_ename
from emp
where empno=v_empno;
dbms_output.put_line(v_ename);
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line(SQLCODE);
dbms_output.put_line(SQLERRM);
END;
但是在實際中,不會這樣輸出錯誤,而是會使用一個異常表來記錄
CREAT TABLE ERRORS(
objname VARCAHR2(100),
eDATE DATE,
SQLCODE NUMBER(6),
SQLERRM VARCHAR2(200)
)
那麼代碼可以改成
DECLARE
v_ename emp.ename%TYPE;
v_empno NUMBER(4) := 736;
verrcode NUMBER(6);
v_errmsg VARCHAR2(200);
BEGIN
select ename
into v_ename
from emp
where empno=v_empno;
dbms_output.put_line(v_ename);
EXCEPTION
WHEN OTHERS THEN
verrcode := SQLCODE;
v_errmsg := SQLERRM
dbms_output.put_line(SQLCODE);
dbms_output.put_line(SQLERRM);
VALUES('',sysdate,verrcode,v_errmsg)
END;
這樣就可以把初始值放在一個表中。
用戶定義的異常
在oracle中不算錯誤但是我們覺得是錯誤。需要手動用RAISE子句觸發。
例子
DECLARE
e_ too_ many EXCEPTION;
BEGIN
update emp
set sal= 5000
where deptno=&xp_ deptno;
if SOL %ROWCOUNT >2 then
RAISE e_ too_ many;
end if;
EXCEPTION
when e_ too_ many then
dbms_ output.put_ line('漲工資人數'|| SQL%ROWCOUNT||'人,太多了);
rollback;
End;
異常傳遞
異常如果沒有做處理,會向上一次傳。
Raise_Application_Error過程
模擬出現一個錯誤,產生一個類似於異常的對話框並終止程序,錯誤編號在-20000~-20999之間,錯誤消息長度最大爲2048字節
DECLARE
e_ name exception;
pragma exception_ init(e_ name, 20202);
BEGIN
delete from emp where deptno=90;
if SQL%NOTFOUND then
Raise_ Application_ Error(- 20202,’部門不存在);
end if;
EXCEPTION
when e_ name then
dbms_ output. put line(sqlcode);
dbms_ output.put line(sqlerrm);
END;
這個代碼的作用是刪除人員時發現沒有這個部門,會彈出一個對話框並終止程序,提示部門不存在。