Skip to content

异常处理语句

异常处理语句共包括三个部分:

  • 异常定义
  • 抛出异常
  • 异常处理

异常定义ExceptionDef

语法格式

sql
ExceptionDef::=
    exception_name EXCEPTION

参数说明

  • ExceptionDef:用户自定义异常语句,使用关键字EXCEPTION在DECLARE中定义。
  • exception_name:用户自定义异常名称。

抛出异常ThrowStmt

语法格式

sql
ThrowStmt::=
    {RAISE | THROW} [EXCEPTION] exception_name;

参数说明

  • ThrowStmt:抛出异常语句,抛出异常语句在块语句体或过程体中使用,可使用关键字RAISETHROW
  • b_expr:附带错误信息。

异常处理OptExceptionStmt

语法格式

sql
OptExceptionStmt::=
    EXCEPTION Exception_Item [Exception_Item...]

Exception_Item::=
    WHEN exception_name THEN pl_stmt_list 
|   WHEN ICONST THEN pl_stmt_list

可以有多个WHEN子句,每个子句处理一种特定的异常。使用WHEN OTHERS THEN可以捕获所有未被捕获的异常。

参数说明

  • ICONST:预定义的系统异常,如ERR_MORE_DATA_FOUNDERR_NO_DATA_FOUND等。
  • pl_stmt_list:异常发生时执行的PL/SQL语句列表。

示例

  • 示例1
    定义一个常数变量与两个异常定义的块语句,当常数变量x大于0时抛出异常exce_1,否则抛出exce_2;对应exce_1的异常处理输出消息“raise exception 1”,对应exce_2异常处理输出消息“raise exception 2”,其他异常则输出“others exception”。

    sql
    DECLARE
      x INT;
      exce_1 EXCEPTION;
      exce_2 EXCEPTION;
    BEGIN
      x:=1;
      IF x>0 THEN
        RAISE exce_1;
      ELSE
        RAISE exce_2;
      END IF;
      EXCEPTION
        WHEN exce_1 THEN
        DBMS_OUTPUT.PUT_LINE('raise exception 1');
        WHEN exce_2 THEN
        DBMS_OUTPUT.PUT_LINE('raise exception 2');
        WHEN OTHERS THEN
        DBMS_OUTPUT.PUT_LINE('others exception');
    END;
    /
    -- 输出:
    raise exception 1
  • 示例2
    定义错误信息直接抛出错误不进入异常处理流程。

    sql
    DECLARE
      exec EXCEPTION;
    BEGIN
      IF 1!=2 THEN
        RAISE exec '数据错误';
      END IF;
    END;
    /
    
    -- 输出:
    Error: [E50001 L5 C1] 数据错误
  • 示例3
    存储过程直接使用系统预定义的异常。捕获异常后,执行相应的处理。

    说明:

    自V12.7版本起,支持预定义异常:

    • DUP_VAL_ON_INDEX:违反唯一值约束,对应之前版本ERR_DUP_VAL_ON_INDEX
    • NO_DATA_FOUND:未找到任何数据,对应之前版本ERR_NO_DATA_FOUND
    • TOO_MANY_ROWS:查询结果过多,对应之前版本ERR_MORE_DATA_FOUND
    • ZERO_DIVIDE:除数为0,对应之前版本ERR_DIV_ZERO
    sql
    
    SQL> CREATE TABLE EMP(emp_id INT,name VARCHAR(32), age SMALLINT);   
    
    SQL> CREATE OR REPLACE PROCEDURE test_proc(id INT) AS
          temp_name VARCHAR(32);
        BEGIN
          -- 查询并返回数据 
          SELECT name INTO temp_name FROM EMP WHERE emp_id = id;
          DBMS_OUTPUT.PUT_LINE(temp_name);
        EXCEPTION
          -- 异常处理 
          WHEN NO_DATA_FOUND THEN -- 没有找到数据 
            DBMS_OUTPUT.PUT_LINE('没有找到该员工');
          WHEN TOO_MANY_ROWS THEN -- 找到多条数据
            DBMS_OUTPUT.PUT_LINE('找到多个员工:' || temp_name);
          WHEN OTHERS THEN        -- 其他异常 
            DBMS_OUTPUT.PUT_LINE('发生其它错误');
        END;
        /   
    
    SQL> EXEC test_proc(1);
    没有找到该员工