拋出異常編程
Oracle有三種類型的異常錯誤:服務器
1. 預約義(Predefined)異常app
ORACLE預約義的異常狀況大約有24個。對這種異常狀況的處理,無需在程序中定義,由ORACLE自動將其引起。測試
2. 非預約義(Predefined)異常rem
即其餘標準的ORACLE錯誤。對這種異常狀況的處理,須要用戶在程序中定義,而後由ORACLE自動將其引起。it
3. 用戶定義(User_define)異常io
程序執行過程當中,出現編程人員認爲的非正常狀況。對這種異常狀況的處理,須要用戶在程序中定義,而後顯式地在程序中將其引起。服務器端
在PL/SQL中有三種方式拋出異常date
經過PL/SQL運行時引擎——拋出Oracle異常exception
使用RAISE語句——拋出用戶定義異常
調用RAISE_APPLICATION_ERROR存儲過程——拋出用戶定義異常
非預約義異常
由於非預約義異常只有編號,沒有名稱,因此不能直接處理。
一、在PL/SQL 塊的定義部分定義異常狀況:
<異常狀況> EXCEPTION;
二、將其定義好的異常狀況,與標準的ORACLE錯誤聯繫起來,使用EXCEPTION_INIT語句:
PRAGMA EXCEPTION_INIT(<異常狀況>, <錯誤代碼>);
三、在PL/SQL 塊的異常狀況處理部分對異常狀況作出相應的處理。
INSERT INTO departments VALUES(50, 'FINANCE', 'CHICAGO');
DECLARE
v_deptno departments.department_id%TYPE := &deptno;
deptno_remaining EXCEPTION; --一、定義異常
PRAGMA EXCEPTION_INIT(deptno_remaining, -2292); --二、關聯
-- -2292 是違反一致性約束的錯誤代碼
BEGIN
DELETE FROM departments WHERE department_id = v_deptno;
EXCEPTION
WHEN deptno_remaining THEN --三、處理
DBMS_OUTPUT.PUT_LINE('違反數據完整性約束!');
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(SQLCODE||'---'||SQLERRM);
END;
用戶自定義異常處理
用戶定義的異常錯誤是經過顯式使用 RAISE 語句來觸發。
一、在PL/SQL 塊的定義部分定義異常狀況 ;
二、RAISE <異常狀況>;
三、在PL/SQL 塊的異常狀況處理部分對異常狀況作出相應的處理。
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
RAISE no_result; --二、拋出
END IF;
EXCEPTION
WHEN no_result THEN --三、處理
DBMS_OUTPUT.PUT_LINE('你的數據更新語句失敗了!');
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(SQLCODE||'---'||SQLERRM);
END;
RAISE_APPLICATION_ERROR
調用DBMS_STANDARD(ORACLE提供的包)包所定義的RAISE_APPLICATION_ERROR過程,能夠從新定義異常錯誤消息,將應用程序專有的錯誤從服務器端轉達到客戶端應用程序。它爲應用程序提供了一種與ORACLE交互的方法。
語法以下:
RAISE_APPLICATION_ERROR(error_number, error_message, [keep_errors] );
error_number 是從 –20,000 到 –20,999 之間的參數,這樣就不會與 ORACLE 的任何錯誤代碼發生衝突
error_message 是相應的提示信息(< 2048 字節),
keep_errors 爲可選,若是keep_errors =TRUE ,則新錯誤將被添加到已經引起的錯誤列表中。若是keep_errors=FALSE(缺省),則新錯誤將替換當前的錯誤列表。
There are two uses for RAISE_APPLICATION_ERROR.
The first is to replace generic Oracle exception messages with our own, more meaningful messages.
The second is to create exception conditions of our own, when Oracle would not throw them.
create or replace procedure new_emp
( p_name in emp.ename%type
, p_sal in emp.sal%type
, p_job in emp.job%type
, p_dept in emp.deptno%type
, p_mgr in emp.mgr%type
, p_hired in emp.hiredate%type := sysdate )
is
invalid_manager exception; --一、定義
PRAGMA EXCEPTION_INIT(invalid_manager, -2291); --二、關聯
dummy varchar2(1);
begin
if trunc(p_hired) > trunc(sysdate)
then
raise_application_error
(-20000, 'NEW_EMP::hiredate cannot be in the future'); --三、拋出自定義異常
end if;
insert into emp
( ename
, sal
, job
, deptno
, mgr
, hiredate )
values
( p_name
, p_sal
, p_job
, p_dept
, p_mgr
, trunc(p_hired) );
exception
when dup_val_on_index then
raise_application_error
(-20001, 'NEW_EMP::employee called '||p_name||' already exists', true); --三、包裝Oracle異常
when invalid_manager then
raise_application_error
(-20002, 'NEW_EMP::'||p_mgr ||' is not a valid manager'); --三、包裝自定義異常
end;
/
客戶端調用時會提示詳細異常信息:
-- 測試RAISE_APPLICATION_ERROR自定義異常
SQL> exec new_emp ('DUGGAN', 2500, 'SALES', 10, 7782, sysdate+1)
BEGIN new_emp ('DUGGAN', 2500, 'SALES', 10, 7782, sysdate+1); END;
*
ERROR at line 1:
ORA-20000: NEW_EMP::hiredate cannot be in the future --ORA-20000
ORA-06512: at "APC.NEW_EMP", line 16
ORA-06512: at line 1
-- 測試RAISE_APPLICATION_ERROR包裝自定義異常
SQL> exec new_emp ('DUGGAN', 2500, 'SALES', 10, 8888, sysdate)
BEGIN new_emp ('DUGGAN', 2500, 'SALES', 10, 8888, sysdate); END;
*
ERROR at line 1:
ORA-20002: NEW_EMP::8888 is not a valid manager
ORA-06512: at "APC.NEW_EMP", line 42
ORA-06512: at line 1
-- 測試RAISE_APPLICATION_ERROR包裝Oracle異常
SQL> exec new_emp ('DUGGAN', 2500, 'SALES', 10, 7782, sysdate)
PL/SQL procedure successfully completed.
SQL>
SQL> exec new_emp ('DUGGAN', 2500, 'SALES', 10, 7782, sysdate)
BEGIN new_emp ('DUGGAN', 2500, 'SALES', 10, 7782, sysdate); END;
*
ERROR at line 1:
ORA-20001: NEW_EMP::employee called DUGGAN already exists
ORA-06512: at "APC.NEW_EMP", line 37
ORA-00001: unique constraint (APC.EMP_UK) violated --同時打印原始堆棧
ORA-06512: at line 1