PL/SQL有两种 类型的异常:内置异常和用户定义异常。
异常处理部分的语法结构如下 :
EXCEPTION
WHEN EXCEPTION_NAME THEN
ERROR-PROCESSING STATEMENTS;
在PL/SQL中,把一些常见的Oracle运行时错误预定义为异常。
一些常见以及抛出它们的方式:
NO_DATA_FOUND :当没有调用分组函数(例如SUM或者COUNT等)时SELECT INTO 语句没有返回任何数据行,此时就会抛出这个异常。当SELECT INTO 语句调用某分组函数,例如COUNT时,结果信永远不会为空,因为,如果没有数据,COUNT函数会返回0。
TOO_MANY_ROWS : 当SELECT INTO 语句返回多个数据行时,就会抛出这个异常。
ZERO_DIVIDE : 当程序中除法运算的除数是0时,会抛出这个异常。
LOGIN_DENIED : 当用户尝试使用无效的用户名或者密码登录Oracle时,就会抛出这个异常。
PROGRAM_ERROR : 当PL/SQL 程序存在 某个内部 问题时,就会抛出这个异常。
VALUE_ERROR : 当出现转换或者大小匹配错误时,就会抛出这个异常。
DUP_VALUE_ON_INDEX :当程序尝试在定义唯一性索引的数据列中保存重复值时,会抛出这个异常。
当有一些异常无法预测到时,可以 使用一种名为OTHERS的特殊异常处理程序 。所有预定义的Oracle错误(异常)都只可以借助于OTHERS处理程序来处理。
如:EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('EXCEPTION');
用户定义异常: 在使用该异常之前,必须首先进行声明 。 自定义异常必须 显式抛出。
如:
DECLARE
exception_name EXCEPTION;
BEGIN
...
IF CONDITION THEN
RAISE exception_name;
ELSE
...
END IF;
EXCEPTION
WHEN exception_name THEN
ERROR-PROCESSING STATEMENTS;
END;
在这种结构中,必须借助于IF-THEN-ELSE语句来决定是否抛出用户定义异常。
当PL/SQL 语句块的声明部分出现运行时错误时,该语句块的异常处理部分不能捕获此项错误。
如:DECLARE
v_test_var CHAR(3) :='ABCD';
BEGIN
DBMS_OUTPUT.PUT_LINE('This is a test');
EXCEPTION
WHEN INVALID_NUMBER OR VALUE_ERROR THEN
DBMS_OUTPUT.PUT_LINE('An error has occurred.');
END; //这个异常是不能被捕获的。
当内部语句块的 声明部分 和 异常处理部分 发生 运行时错误时,该异常会立即传播到外语句块。可以在外部语句块中捕获该异常。
Oracle提供了两个内置函数---SQLCODE 和 SQLERRM ---- 用于实现 OTHERS异常处理程序。SQLCODE 函数会返回Oracle 错误编号,SQLERRM 函数会返回错误消息,返回消息的最大长度是512字节。
如:
DECLARE
v_zip VARCHAR2(5) :='&sv_zip';
v_city VARCHAR2(15);
v_state CHAR(2);
v_err_code NUMBER;
v_err_msg VARCHAR2(200);
BEGIN
SELECT city, state INTO v_city,v_state FROM zipcode WHERE zip=v_zip;
BMS_OUTPUT.PUT_LINE(v_city || ' , ' || v_state);
EXCEPTION
WHEN OTHERS THEN
v_err_code := SQLCODE;
v_err_msg := SUBSTR(SQLERRM,1,200);
END;