Plsql 简明教程
PL/SQL - Exceptions
在本教程中,我们将讨论 PL/SQL 中的 Exceptions。Exception 是程序执行过程中的错误条件。PL/SQL 支持程序员使用程序中的 EXCEPTION 块捕获此类条件,并针对错误条件采取适当措施。Exceptions 有两种:
-
System-defined exceptions
-
User-defined exceptions
Syntax for Exception Handling
Exception 处理的常规语法如下。在这里,你可以列出尽可能多的异常进行处理。默认异常将使用 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;
Example
我们编写一个程序来说明概念。我们将使用在前面教程中创建和使用的 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 的客户,因此程序引发了在 EXCEPTION block 中捕获的运行时异常 NO_DATA_FOUND 。
Raising Exceptions
当数据库服务器有任何内部错误时,它将自动引发异常,但是程序员也可以通过使用 RAISE 命令显式引发异常。以下是在引发异常的简单语法 -
DECLARE
exception_name EXCEPTION;
BEGIN
IF condition THEN
RAISE exception_name;
END IF;
EXCEPTION
WHEN exception_name THEN
statement;
END;
您可以在引发 Oracle 标准异常或任何用户定义的异常时使用上述语法。在下一部分中,我们将为您提供一个引发用户定义异常的示例。您可以以类似方式引发 Oracle 标准异常。
User-defined Exceptions
PL/SQL 允许您根据程序的需要定义自己的异常。必须声明用户定义的异常,然后使用 RAISE 语句或 DBMS_STANDARD.RAISE_APPLICATION_ERROR 过程显式引发异常。
声明异常的语法是 -
DECLARE
my-exception EXCEPTION;
Example
以下示例说明了该概念。此程序询问客户 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.
Pre-defined Exceptions
PL/SQL 提供了许多预定义的异常,当程序违反任何数据库规则时,这些异常将被执行。例如,当 SELECT INTO 语句不返回任何行时,将引发预定义的异常 NO_DATA_FOUND。下表列出了几个重要的预定义异常 -
Exception |
Oracle Error |
SQLCODE |
Description |
ACCESS_INTO_NULL |
06530 |
-6530 |
当将空对象自动分配了一个值时,将引发该异常。 |
CASE_NOT_FOUND |
06592 |
-6592 |
当 CASE 语句的 WHEN 子句中没有选择任何选项,并且没有 ELSE 子句时,将引发该异常。 |
COLLECTION_IS_NULL |
06531 |
-6531 |
当程序尝试将 EXISTS 以外の集合方法应用于未初始化的嵌套表或变长数组,或者程序尝试将值分配给未初始化的嵌套表或变长数组的元素时,将引发该异常。 |
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 |
尝试将数字除以零时引发。 |