异常处理:
pl/sql程序错误一般分为两类,一类时变异错误,由pl/sql编译器发出错误报告,另一类时运行时错误。
一、预定义异常:
一般预定义异常是ORA错误,会自动的抛出,通过捕获该异常可以对错误进行处理。
二、非预定义异常: 没有ORALCE错误和它关联,需要在语句块的声明部分声明一个异常名称,然后通过编译指示PRAGMA EXCEPTION_INT 将该异常名称与一个oracle错误相关联,
实例:
delete from emp where deptno=20;
这样的一条删除语句会因为在dept表上有相关的约束而导致无法删除,出现违反完整性约束的错误。所以我们可以为该错误定义异常,然后通过异常来处理相关的错误。
如:
declare
dept_no_fk EXCEPTION;
PRAGMA EXPTION_INT(DEPT_NO_FK,-2292);
BEGIN
..
EXECPTION
..
END;
三、用户定义异常,
用户定义错误是指,在运行时并不会产生oralce错误,但是从业务角度考虑认为他会是一种错误。
比如,在执行update时,没有更新任何数据,虽然这不会产生任何的错误,也不会有任何的异常,但是我们在业务上认为这是一种异常,那么我们就需要为他定义一个异常。
四、异常处理:
异常处理也叫错误处理,通常分为3个步骤:
1、在声明的部分为错误定义异常,包括非预定义异常和用户定义异常。
2、在执行过程中产生错误时抛出异常。
3、在异常处理部分通过异常处理器捕获异常,并进行异常处理。
(1)、异常的定义:ORACLE中有三种异常,其中预定义异常由系统定义,而其他两种异常需要用户定义,定义异常的方法是在pl/sql块的声明部分定义一个EXCEPTION类型的变量,其语法是
变量名 EXCEPTION;
如果是非定义异常,还需要用编译指示PRAGMA_EXCEPTION_INIT将异常与一个ORACLE错误向关联,其语法是:
PRAGMA EXCEPYION_INIT(e_exception,-#####).
注意:ORACLE内部错误号用一个负的5位数表示,如-02292,其中-20999~-20000为用户定义错误保留号。
(2)、由于系统可以自动识别ORACLE的内部错误,因此当错误产生时系统会自动抛出与之对应的预定义错误或者非预定义错误。但是无法识别用户定义的错误,因此当用户定义错误产生时,需要手动抛出与之对应的异常,用户定义异常的抛出语法是:
RAISE user_define_execption;
(3)、异常的捕获和处理
当错误产生之后,程序流程转移到异常处理部分,PL/SQL块的异常处理部分由异常处理器和错误处理器组成,异常处理器的功能就是捕获错误产生时所抛出的异常,为有针对性的处理错误提供可能。
异常处理:
EXCEPTION
WHEN execption1[or execption2...] THEN statement;
WHEN execption3[or execption4...] THEN statement;
WHEN OTHERS TEHN statement;
end;
注意事项:
1、一个异常处理器可以捕获多个异常,只需要在WHERE子句中用OR连接即可。
2、一个异常只能被一个异常处理器捕获,并进行处理。
实例(预定义异常处理):
查询一个员工的工资,如果该员工不存在,则输出there is no such an employee,如果存在多位员工,那么久输出其基本信息。
declare
v_sal emp.sal%TYPE;
begin
select sal into v_sal from emp where empno=1001;
DBMS_OUTPUT.PUT_LINE(v_sal);
EXECPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('there is no such a employee');
WHEN TOO_MANY_ROWS
THEN
FOR V_EMP IN (SELECT * FROM EMP WHERE empno=1001) loop
DBMS_OUTPUT.PUT_LINE(v_emp.empno||v_emp.ename,v_emp.sal);
end loop;
end;
/
2、非预定义异常处理
删除dep表中部门号为50的部门信息,如果不能删除那么提示,there is a subrecode exist.
declare
e_deptno_fk EXCEPTION;
PRAGMA EXCEPTION_INIT(e_deptno_fk,-2299);
begin
delete from scott.emp where dept_id=50;
EXCEPTION
WHEN e_deptno_fk then
DBMS_OUTPUT.PUT_LINE('there is a subrecord');
end;
/
(3)、用户自定义异常处理
如:修改108号员工的工资,保证修改后工资不超过6000元。
declare
e_too_high_sal EXCEPTION;
v_sal scott.emp.sal%type;
begin
update emp set sal=sal+1000 where empno=1001
returning sal into v_sal;
IF v_sal>6000 then
raise e_too_high_sal then
DBMS_OUTPUT.PUT_LINE('the salary is too high');
rollback;
end;
/
(4)、OTHERS异常处理
others 异常处理是一个特殊的异常处理器,可以捕获所有的异常,通常,others异常处理器总是作为异常处理部分的最后一个异常处理器,负责那些没有被其他异常处理器捕获的异常。
如
虽然others异常处理器可以捕获所有的异常,但是并不会返回相关的错误信息,无法确定到底是哪个错误产生了异常,该错误是否有预定义异常等,所以PL/SQL程序提供了下面两个函数来获取相关的信息:
SQLCODE:返回当前错误码,如果是用户定义异常,则返回1,如果是ORA-1403:NO_DATA_FOUND则返回值100,其他内部错误则返回对于的内部错误号。
SQLERRM:返回当前错误的消息文本。如果是ORACLE内部错误,那么则返回对应得内部错误描述,如果是用户定义错误,则返回信息文本user_defined exception.
如:
declare
v_sal scott.emp.sal%type;
e_high_sal EXCEPTION;
v_code number;
v_text varchar2(200);
begin
select sal into v_sal from emp where enam='xulin';
update emp set sal=sal+1000 where empno=1001;
IF v_sal>6000 then
raise e_high_sal;
end if;
EXCEPTION
WHEN e_high_sal then
DBMS_OUTPUT.PUT_LINE('the salary is too high');
rollback;
when OTHERS then
v_code:=SQLCODE;
v_text:=SQLERRM;
DBMS_OUTPUT.PUT_LINE(v_code||v_text);
end;
/
五、异常的传播