一、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;
若您发现我侵犯了您的版权,请及时与我联系。