1、异常的申明:
1、语法如下:
exception_name EXCEPTION;
2、异常名称与错误代码绑定
使用编译指示 PRAGMA EXCEPTION_INIT 将异常名称与 一个 Oracle错误绑定,语法为:
PRAGMA EXCEPTION_INIT(exception_name,error_code)
其中, error_code 为错误代码,是一个负的 5 位数, 如-02292 。其中 -20999~-20000 为用户定义错误的保留号。
如“违反唯一约束”代码为“00001”
2、异常捕获:
语法如下:
EXCEPTION
WHEN ex_name_1
THEN statements_1
WHEN ex_name_2 OR ex_name_3
THEN statements_2
WHEN OTHERS
THEN statements_n;
END;
其中,ex_name_n为异常的名称,而statements_n为对应异常发生时的处理语句。当PL/SQL块执行部分发生错误时,抛出异常,执行部分停止运行,程序流程转移到异常处理部分。如果异常名称为ex_name_1,则执行statements_1;如果异常名称为ex_name_2或ex_name_3,则执行statements_2;否则将执行statements_3。
进行异常捕获时需要注意下列事项:
一个异常处理器可以捕获多个异常,只需在WHEN子句 中用OR连接即可。
一个异常只能被一个异常处理器捕获,并进行处理。
OTHERS异常处理器
OTHERS异常处理器是一个特殊的异常处理器,可以捕获所有错误抛出的异常。通常,OTHERS异常处理器总是作为异 常处理部分的最后一个异常处理器,负责处理那些没有被其他 异常处理器捕获的异常。
虽然OTHERS异常处理器可以捕获各种异常,但并不返回 相关错误信息,无法判断到底是哪个错误产生了异常。为此, PL/SQL提供了SQLCODE和SQLERRM两个函数来获取错误相 关信息。
SQLCODE
在异常处理器中调用SQLCODE函数时,将返回当前异常 处理器捕获的异常对应的错误代码。如果当前捕获的异常 是“NO_DATA_FOUND”,SQLCODE函数的返回值为100;如 果是用户定义异常,则SQLCODE函数的返回值为1,或者是使 用EXCEPTION_INIT时为用户定义异常绑定的代码。 如果在异常处理器外部调用SQLCODE函数,则返回值为 0。
SQLERRM
SQLERRM根据特定的错误代码返回错误的描述信息,最 大长度为512字节。调用形式为:
SQLERRM[(error_code)]
其中,参数error_code为错误代码。根据参数值不同, SQLERRM函数有如下返回值。
1、不带参数的SQLERRM函数只在异常处理器内部有用,返 回当前SQLCODE函数返回的错误代码对应的错误描述。
2、如果在异常处理器外部使用无参数的SQLERRM函数或函 数参数为0,则函数返回信息为“ORA-0000:normal, successful completion”。
3、如果参数error_code值为100,函数返回值为“ORA- 01403”。·如果参数error_code值为非100的正数,函数返回值的形式为:“-error_code:non-ORACLE exception”。
4、如果参数error_code值为一个负数,并与Oracle的某个错 误代码相同,函数返回相应的Oracle错误描述。
5、如果参数error_code值是一个负数,但没有相应的Oracle 错误代码,则函数返回值的形式为:“ORA-error_code: Message error_code not found;product=RDBMS; facility=ORA”。
如以下程序:
-- Created on by Hj
declare
test number ;
e_test exception;--申明异常
PRAGMA EXCEPTION_INIT(e_test,-2292);
i integer;
begin
dbms_output.put_line('SQLERRM:'||SQLERRM);
dbms_output.put_line('SQLERRM(0):'||SQLERRM(0));
dbms_output.put_line('SQLERRM(+100):'||SQLERRM(100));
dbms_output.put_line('SQLERRM(+200):'||SQLERRM (200));
dbms_output.put_line('SQLERRM(-6511):'||SQLERRM(-6511)) ;
dbms_output.put_line('SQLERRM(-50000):'||SQLERRM(-50000));
end;
输出结果如下:
需要注意的是 ,不能在 SQL 语句中直接调用 SQLCODE 函数和SQLERRM函数,可以先将这两个函数的返回值赋予局部变量,然后在SQL语句中使用局部变量。也可以结合dbms_utility.format_error_backtrace()函数查看存储过程详细报错在哪一行,类似于java中e.printStackTrace();
3、抛出异常
由于系统可以自动识别Oracle内部错误,因此当Oracle错 误产生时系统会隐式抛出与之对应的内部定义异常或预定义异 常。但是,系统无法识别用户定义错误,因此当用户定义错误 产生时,需要用户显式抛出与之对应的异常。对于内部定义异 常或预定义异常,用户也可以根据需要显式抛出。 显式抛出异常使用RAISE语句,语法为:
RAISE [exception];
4、案例
-- Created on by Hj
declare
v_code NUMBER(6);
v_text VARCHAR2(200);
test number ;
e_test exception;--申明异常
PRAGMA EXCEPTION_INIT(e_test,-2292);--ORA-02292 违反完整约束条件、已找到子记录
i integer;
begin
i:=0;
if i<=0 then
raise e_test; --抛出异常
end if ;
test:=9/i;
exception --捕获异常
when e_test then
dbms_output.put_line('输入除数为0错误');
begin
i:=0;
test:=9/i;
exception --捕获异常
when others then
v_code:=SQLCODE;
v_text:=SQLERRM;
dbms_output.put_line('错误代码为'||v_code||'错误信息为'||v_text);
end;
end;
输出结果如下: