Plsql 简明教程

PL/SQL - Exceptions

在本教程中,我们将讨论 PL/SQL 中的 Exceptions。Exception 是程序执行过程中的错误条件。PL/SQL 支持程序员使用程序中的 EXCEPTION 块捕获此类条件,并针对错误条件采取适当措施。Exceptions 有两种:

  1. System-defined exceptions

  2. 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

尝试将数字除以零时引发。