• 系统内部异常

    系统隐式定义的异常错误,一般来说为 SQL 执行时的错误,例如死锁。 由 OceanBase 数据库的 PL 引擎自动抛出,但并没有异常名称的定义,程序通过 SQLCODE 和 SQLERRM 来获取细节。

  • 预定义异常

    OceanBase 数据库的 PL 引擎中定义的异常,PL 程序执行时的常见问题。这种异常情况由 OceanBase 数据库自动将其抛出,有明确的异常名称,程序中可以直接捕获。例如 SELECT… INTO… 可能触发 NO_DATA_FOUND 异常。

说明

系统内部异常和预定义异常都是系统自动抛出的。

  • 用户定义异常

    程序执行过程中,出现编程人员认为的异常情况。对这种异常情况的处理,需要用户在程序中定义,并且显式地在程序中将其引发。

PL 程序遇到 OceanBase 数据库系统错误,会抛出系统内部异常。

这种异常有两种处理方式:

  • 通过 PRAGMA EXCEPTION_INIT 进行声明,然后在 EXCEPTION HANDLE 捕获其名称。

  • 用 EXCEPTION HANDLE 中的 OTHER 捕获,通过 SQLCODE 和 SQLERRM 来获取细节。

通过命名捕获

EXCEPTION_INIT 的语法如下:

handle_name 为异常的命名,可以通过这个名字在 EXCEPTION 中捕获,sql_err_code 为相应的数据库错误号。

通过命名捕获系统内部异常的示例如下:

  1. -> DUPLICATED_DEPT_ID EXCEPTION;
  2. -> PRAGMA EXCEPTION_INIT(DUPLICATED_DEPT_ID, -5024);
  3. -> BEGIN
  4. -> UPDATE departments SET department_id=110
  5. -> where DEPARTMENT_ID=100;
  6. -> EXCEPTION
  7. -> WHEN DUPLICATED_DEPT_ID THEN
  8. -> DBMS_OUTPUT.PUT_LINE('Duplicated department id!');
  9. -> DBMS_OUTPUT.PUT_LINE(SQLCODE||'---'||SQLERRM);
  10. -> END;
  11. -> /
  12. Query OK, 0 rows affected (0.03 sec)

通过 OTHER 捕获

通过 OTHER 捕获系统内部异常的示例如下:

对这种异常情况的处理,只需在 PL 块的异常处理部分,直接引用相应的异常情况名,并对其完成相应的异常错误处理即可。

示例如下:

  1. obclient> DECLARE
  2. -> v_empid employees.employee_id%TYPE;
  3. -> v_sal employees.salary%TYPE;
  4. -> BEGIN
  5. -> v_empid := 100;
  6. -> SELECT salary INTO v_sal FROM employees
  7. -> WHERE employee_id=v_empid;
  8. -> IF v_sal<=1500 THEN
  9. -> UPDATE employees SET salary=salary+100 WHERE employee_id=v_empid;
  10. -> DBMS_OUTPUT.PUT_LINE('Employee '||v_empid||' updated');
  11. -> ELSE
  12. -> DBMS_OUTPUT.PUT_LINE('Employee '||v_empid||' ignored');
  13. -> EXCEPTION
  14. -> -- 如果员工号v_empid不存在,触发NO_DATA_FOUND异常
  15. -> DBMS_OUTPUT.PUT_LINE('Employee id '||v_empid||' not found');
  16. -> WHEN TOO_MANY_ROWS THEN
  17. -> -- 如果员工号v_empid不止一条,触发TOO_MANY_ROWS异常
  18. -> DBMS_OUTPUT.PUT_LINE('Duplicated id: '||v_empid);
  19. -> WHEN OTHERS THEN
  20. -> DBMS_OUTPUT.PUT_LINE(SQLCODE||'---'||SQLERRM);
  21. -> END;
  22. -> /
  23. Query OK, 0 rows affected (0.06 sec)
  24. Employee id 100 not found

预定义异常的信息如下表:

用户自定义异常可以显式调用 RAISE 语句来触发,通常用来处理应用逻辑的异常。基本步骤如下:

  1. 在 PL 的 DECLARE 部分定义异常名称,语法为:exception_name EXCEPTION

  2. 在 PL 程序体中显式触发异常,语法为:RAISE exception_name

  3. 在 PL程序的 EXCEPTION 部分对异常情况做出相应的处理,语法为:

示例如下:

OceanBase 数据库提供了过程自定义错误代码 RAISE_APPLICATION_ERROR 和错误提示消息,让错误处理变得更加灵活, 比如函数中抛出自定义错误, 在调用函数的过程中捕获异常并处理。

语法如下:

  1. RAISE_APPLICATION_ERROR(error_number,error_message ) ;

示例如下: