PL/SQL 异常处理
异常是什么
在PL/SQL中,程序执行过程中发生的错误称为异常。
PL/SQL允许程序员使用异常块捕获这种情况,并针对错误情况采取适当的操作。
有两种类型的异常:
- 系统定义的异常
- 用户定义的异常
PL/SQL异常处理
异常处理的语法:
以下是异常处理的一般语法:
DECLARE
BEGIN
EXCEPTION
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表。
SELECT * FROM CUSTOMERS;
ID | NAME | AGE | ADDRESS | SALARY |
---|---|---|---|---|
1 | Ramesh | 23 | Allahabad | 20000 |
2 | Suresh | 22 | Kanpur | 22000 |
3 | Mahesh | 24 | Ghaziabad | 24000 |
4 | Chandan | 25 | Noida | 26000 |
5 | Alex | 21 | Paris | 28000 |
6 | Sunita | 20 | Delhi | 30000 |
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('没有找到该客户!');
WHEN others THEN
dbms_output.put_line('错误!');
END;
/
在SQL提示符下执行上述代码后,会得到以下结果:
没有找到该客户!
PL/SQL过程成功完成。
上面的程序应该显示客户的名字和地址,作为给定ID的结果。但是在我们的数据库中没有ID为8的客户,因此程序引发运行时异常NO_DATA_FOUND,该异常被捕获在异常块中。
注意:在上面的示例中,由于customer_id使用的是8,并且该表中没有id值为8的客户,所以结果显示为”没有这样的客户”。
如果您使用上面表格中定义的id(即1到6),您将获得一定的结果。例如:在这里,我们使用的是id 5。
DECLARE
c_id customers.id%type := 5;
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 ('姓名:'|| c_name);
DBMS_OUTPUT.PUT_LINE ('地址:' || c_addr);
EXCEPTION
WHEN no_data_found THEN
dbms_output.put_line('没有这样的客户!');
WHEN others THEN
dbms_output.put_line('出错!');
END;
/
在SQL提示符下执行上述代码后,您将获得以下结果:
姓名:alex
地址:paris
PL/SQL过程已成功完成。
引发异常
在任何内部数据库错误的情况下,数据库服务器会自动抛出异常。但是程序员也可以使用RAISE命令显式地抛出异常。
抛出异常的语法:
DECLARE
exception_name EXCEPTION;
BEGIN
IF condition THEN
RAISE exception_name;
END IF;
EXCEPTION
WHEN exception_name THEN
statement;
END;
PL/SQL 用户定义的异常
PL/SQL允许用户根据程序的需要定义自己的异常。可以使用RAISE语句或过程DBMS_STANDARD.RAISE_APPLICATION_ERROR显式地引发用户定义的异常。
用户定义异常的语法
DECLARE
my-exception EXCEPTION;
PL/SQL 预定义的异常
在程序违反任何数据库规则时,PL/SQL中有许多预定义的异常会被触发执行。
例如: NO_DATA_FOUND是一个预定义的异常,在SELECT INTO语句未返回任何行时会引发该异常。
下面是一些重要的预定义异常的列表:
异常 | Oracle错误 | SQL代码 | 描述 |
---|---|---|---|
ACCESS_INTO_NULL | 06530 | -6530 | 当NULL对象自动分配一个值时,会引发此异常。 |
CASE_NOT_FOUND | 06592 | -6592 | 在CASE语句的”WHEN”子句中没有选择任何选项,并且没有else子句时,会引发此异常。 |
COLLECTION_IS_NULL | 06531 | -6531 | 当程序尝试对未初始化的嵌套表或VARRAY应用除exists之外的集合方法,或程序尝试对未初始化的嵌套表或VARRAY的元素赋值时,会引发此异常。 |
DUP_VAL_ON_INDEX | 00001 | -1 | 此错误在尝试将重复值存储在具有唯一索引的列中时引发。 |
INVALID_CURSOR | 01001 | -1001 | 在尝试进行不允许的光标操作时引发,比如关闭未打开的光标。 |
INVALID_NUMBER | 01722 | -1722 | 将字符字符串转换为数字失败时引发,因为字符串不表示有效数字。 |
LOGIN_DENIED | 01017 | -1017 | 当程序使用无效的用户名或密码登录到数据库时引发。 |
NO_DATA_FOUND | 01403 | +100 | 当选择到语句返回0行时引发。 |
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 | 当试图除以零时引发。 |