一、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個預定義的異常處理。
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
二、三種異常的處理的基本介紹和語法。
假如實例表如下:
-- 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 塊的定義部分定義異常情況:
2. 將其定義好的異常情況,與標准的ORACLE錯誤聯系起來,使用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 塊的定義部分定義異常情況:
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;
若您發現我侵犯了您的版權,請及時與我聯系。