程序执行过程中出现错误情况被称为在PL/SQL异常。 PL/SQL支持程序员在程序中使用异常块捕获这样的条件并采取适当的动作应对错误情况。有两种类型的异常:
-
系统定义的异常
-
用户定义的异常
异常处理语法
一般异常处理的语法如下。在这里可以列出下来很多,要处理异常。默认的异常将使用WHEN others THEN处理:
DECLARE
<declarations section>
BEGIN
<executable command(s)>
EXCEPTION
<exception handling goes here >
WHEN exception1 THEN
exception1-handling-statements
WHEN exception2 THEN
exception2-handling-statements
WHEN exception3 THEN
exception3-handling-statements
........
WHEN others THEN
exception3-handling-statements
END;
示例
写一些简单的代码来说明这个概念。将使用我们已经创建,并在前面的章节中使用的CUSTOMERS表:
DECLARE
c_id customers.id%type := 8;
c_name customers.name%type;
c_addr customers.address%type;
BEGIN
SELECT name, address INTO c_name, c_addr
FROM customers
WHERE id = c_id;
DBMS_OUTPUT.PUT_LINE (‘Name: ‘|| c_name);
DBMS_OUTPUT.PUT_LINE (‘Address: ‘ || c_addr);
EXCEPTION
WHEN no_data_found THEN
dbms_output.put_line(‘No such customer!‘);
WHEN others THEN
dbms_output.put_line(‘Error!‘);
END;
/
当上述代码在SQL提示符执行时,它产生了以下结果:
No such customer! PL/SQL procedure successfully completed.
上述程序显示一个客户的ID给出的名字和地址。由于在我们的数据库没有ID值为8的客户,该程序运行时引发一个异常NO_DATA_FOUND,这是捕获异常EXCEPTION块。
引发异常
异常是数据库服务器自动在内部数据库错误,但异常可以明确地提出由程序员使用命令RAISE。以下是引发异常的简单的语法:
DECLARE
exception_name EXCEPTION;
BEGIN
IF condition THEN
RAISE exception_name;
END IF;
EXCEPTION
WHEN exception_name THEN
statement;
END;
可以在引发Oracle的标准异常或任何用户定义的异常使用上述语法。下一节会显示如何引发用户定义异常,引发Oracle标准异常以及类似的方法的例子。
用户自定义异常
PL/SQL允许根据程序的需要定义自己的异常。用户定义的异常必须声明,然后明确地提出使用一个RAISE语句或程序DBMS_STANDARD.RAISE_APPLICATION_ERROR。
声明一个异常的语法是:
DECLARE
my-exception EXCEPTION;
示例:
下面的例子说明了这个概念。该程序需要一个客户ID,当用户输入了一个无效的ID,异常invalid_id引发。
DECLARE
c_id customers.id%type := &cc_id;
c_name customers.name%type;
c_addr customers.address%type;
-- user defined exception
ex_invalid_id EXCEPTION;
BEGIN
IF c_id <= 0 THEN
RAISE ex_invalid_id;
ELSE
SELECT name, address INTO c_name, c_addr
FROM customers
WHERE id = c_id;
DBMS_OUTPUT.PUT_LINE (‘Name: ‘|| c_name);
DBMS_OUTPUT.PUT_LINE (‘Address: ‘ || c_addr);
END IF;
EXCEPTION
WHEN ex_invalid_id THEN
dbms_output.put_line(‘ID must be greater than zero!‘);
WHEN no_data_found THEN
dbms_output.put_line(‘No such customer!‘);
WHEN others THEN
dbms_output.put_line(‘Error!‘);
END;
/
当上述代码在SQL提示符执行时,它产生了以下结果:
Enter value for cc_id: -6 (let‘s enter a value -6) old 2: c_id customers.id%type := &cc_id; new 2: c_id customers.id%type := -6; ID must be greater than zero! PL/SQL procedure successfully completed.
预定义异常
PL/SQL提供许多预先定义的异常,这是在被执行时的任何数据库规则由程序引发。例如,预定义异常NO_DATA_FOUND时引发一个SELECT INTO语句返回数据行。下表列出了一些重要的预先定义的异常:
Exception | Oracle Error | SQLCODE | 描述 |
---|---|---|---|
ACCESS_INTO_NULL | 06530 | -6530 | 当一个空对象会自动分配一个值引发此异常 |
CASE_NOT_FOUND | 06592 | -6592 | 当没有任何选择,在当选择一个CASE语句的子句,并且没有ELSE子句时被引发 |
COLLECTION_IS_NULL | 06531 | -6531 | 当程序试图申请其他收集方法不是存在未初始化的嵌套表或VARRAY,或程序试图值分配给未初始化的嵌套表或变长数组的元素时被引发 |
DUP_VAL_ON_INDEX | 00001 | -1 | 当重复值试图被存储在具有唯一索引的列时被引发 |
INVALID_CURSOR | 01001 | -1001 | 当尝试以使这是不允许的,如关闭一个未打开的游标的游标操作时被引发 |
INVALID_NUMBER | 01722 | -1722 | 当一个字符的字符串转换成一个数失败,因为字符串不表示一个有效的数据被引发 |
LOGIN_DENIED | 01017 | -1017 | 当程序试图登录到数据库使用无效的用户名或密码被引发 |
NO_DATA_FOUND | 01403 | +100 | 它被引发当一个SELECT INTO语句无任何行返回 |
NOT_LOGGED_ON | 01012 | -1012 | 在不连接到数据库发出数据库调用它被引发 |
PROGRAM_ERROR | 06501 | -6501 | 它被引发当PL/SQL有一个内部问题 |
ROWTYPE_MISMATCH | 06504 | -6504 | 当游标取值有不兼容的数据类型的变量被引发 |
SELF_IS_NULL | 30625 | -30625 | 它被引发,当对象的成员方法被调用,但对象类型的实例没有被初始化。 |
STORAGE_ERROR | 06500 | -6500 | 它被引发当PL/SQL内存不足或内存已损坏 |
TOO_MANY_ROWS | 01422 | -1422 | 它被引发当SELECT INTO语句返回多行 |
VALUE_ERROR | 06502 | -6502 | 当算术,转换,截短,或大小约束错误时引发 |
ZERO_DIVIDE | 01476 | 1476 | 它被引发当一个数试图除以零。 |