PL/SQL 异常处理
什么是异常
在程序执行过程中发生的错误在PL/SQL中称为异常。
PL/SQL有助于程序员使用程序中的异常块来捕获此类条件,并针对错误条件采取适当的措施。
有两种例外类型:
系统定义的异常
用户定义的异常
PL/SQL异常处理
异常处理的语法:
以下是异常的通用语法处理:
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表。
SELECT * FROM COUSTOMERS;
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('No such customer!');
WHEN others THEN
dbms_output.put_line('Error!');
END;
/
在SQL Prompt上执行上述代码后,它会产生以下结果:
No such customer!
PL/SQL procedure successfully completed.
上面的程序应显示给出ID的结果的客户名称和地址。但是我们的数据库中没有ID值为8的客户,因此程序会引发运行时异常NO_DATA_FOUND,该异常在EXCEPTION块中捕获。
注意: 您会得到"没有这样的客户"的结果,因为在上例中使用的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 ('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提示符下执行上述代码后,您将获得以下结果:
Name: alex
Address: paris
PL/SQL procedure successfully completed.
引发异常
如果发生内部数据库错误,则数据库服务器会自动引发异常。但是程序员也可以使用命令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,或者程序尝试将值分配给未初始化的嵌套表或varray的元素时,会引发该错误。 |
DUP_VAL_ON_INDEX |
00001 |
-1 |
当尝试将重复值存储在具有唯一索引的列中时引发。 |
INVALID_CURSOR |
01001 |
-1001 |
在尝试进行不允许的光标操作(例如关闭未打开的光标)时引发。 |
INVALID_NUMBER |
01722 |
-1722 |
由于字符串不能代表有效数字而导致无法将字符串转换为数字时引发。 |
LOGIN_DENIED |
01017 |
-1017 |
当s程序尝试使用无效的用户名或密码登录数据库时引发。 |
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 |
尝试将数字除以零时引发。 |