- PL/SQL 教程
- PL/SQL - 主页
- PL/SQL - 概述
- PL/SQL - 环境
- PL/SQL - 基本语法
- PL/SQL - 数据类型
- PL/SQL - 变量
- PL/SQL - 常量和文字
- PL/SQL - 运算符
- PL/SQL - 条件
- PL/SQL - 循环
- PL/SQL - 字符串
- PL/SQL - 数组
- PL/SQL - 过程
- PL/SQL - 函数
- PL/SQL - 游标
- PL/SQL - 记录
- PL/SQL - 异常
- PL/SQL - 触发器
- PL/SQL - 包
- PL/SQL - 集合
- PL/SQL - 事务
- PL/SQL - 日期和时间
- PL/SQL - DBMS 输出
- PL/SQL - 面向对象
- PL/SQL 有用资源
- PL/SQL - 问题与解答
- PL/SQL - 快速指南
- PL/SQL - 有用的资源
- PL/SQL - 讨论
PL/SQL - 异常
在本章中,我们将讨论 PL/SQL 中的异常。异常是程序执行期间的错误情况。PL/SQL 支持程序员在程序中使用EXCEPTION块捕获此类情况,并对错误情况采取适当的操作。有两种类型的异常 -
- 系统定义的异常
- 用户定义的异常
异常处理语法
异常处理的一般语法如下。您可以在此处列出您可以处理的尽可能多的异常。默认异常将使用WHEN other 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 提供了许多预定义的异常,当程序违反任何数据库规则时就会执行这些异常。例如,当 SELECT INTO 语句不返回行时,会引发预定义异常 NO_DATA_FOUND。下表列出了一些重要的预定义异常 -
例外 | 甲骨文错误 | SQL代码 | 描述 |
---|---|---|---|
ACCESS_INTO_NULL | 06530 | -6530 | 当自动为 null 对象分配值时会引发该异常。 |
CASE_NOT_FOUND | 06592 | -6592 | 当未选择 CASE 语句的 WHEN 子句中的任何选项且没有 ELSE 子句时,将引发该错误。 |
COLLECTION_IS_NULL | 06531 | -6531 | 当程序尝试将 EXISTS 以外的集合方法应用于未初始化的嵌套表或 varray,或者程序尝试将值分配给未初始化的嵌套表或 varray 的元素时,会引发该错误。 |
DUP_VAL_ON_INDEX | 00001 | -1 | 当尝试将重复值存储在具有唯一索引的列中时会引发该错误。 |
INVALID_CURSOR | 01001 | -1001 | 当尝试执行不允许的游标操作(例如关闭未打开的游标)时,会引发该错误。 |
无效号码 | 01722 | -1722 | 当字符串转换为数字失败时,会引发该错误,因为该字符串不代表有效的数字。 |
登录_拒绝 | 01017 | -1017 | 当程序尝试使用无效的用户名或密码登录数据库时,会引发该错误。 |
没有找到数据 | 01403 | +100 | 当 SELECT INTO 语句不返回任何行时会引发该错误。 |
未登录 | 01012 | -1012 | 当在未连接到数据库的情况下发出数据库调用时会引发该错误。 |
程序错误 | 06501 | -6501 | 当 PL/SQL 出现内部问题时会引发该错误。 |
ROWTYPE_MISMATCH | 06504 | -6504 | 当游标获取具有不兼容数据类型的变量中的值时,会引发该错误。 |
SELF_IS_NULL | 30625 | -30625 | 当调用成员方法但对象类型的实例未初始化时会引发该异常。 |
存储错误 | 06500 | -6500 | 当 PL/SQL 内存不足或内存损坏时会引发该错误。 |
TOO_MANY_ROWS | 01422 | -1422 | 当 SELECT INTO 语句返回多行时会引发该错误。 |
VALUE_ERROR | 06502 | -6502 | 当发生算术、转换、截断或大小约束错误时会引发该错误。 |
零除法 | 01476 | 第1476章 | 当尝试将数字除以零时会引发该错误。 |