Oracle学习--->6、异常处理机制

1、Oracle中的错误分为两大类:

  • 编译时错误:程序在编写过程中出现的错误
  • 运行时错误:程序在运行过程中因为各种原因产生 的运行时错误

2、异常处理语法,基本处理结构包含3个部分:

  • 在定义区,定义异常,如果使用预定义异常,则不用再定义区定义异常
  • 在执行区,可以显示地出发异常,也可以有PL/SQL引擎触发异常
  • 只要在执行过程中出现了异常,那么执行区中后续的语句将立即停止执行,语句执行流程跳转到异常处理区

3、注意点:

  • 当RAISE语句触发异常后,程序的执行流程将跳转到EXCEPTION部分的异常处理类型异常处理块中。
  • 在EXCEPTION语句块中,使用多个WHEN THEN语句来捕捉多个异常,对于未处理的异常,可以使用WHEN OTHERS THEN来提供一个统一的异常处理

异常处理结构示例

 DECLARE
    e_duplicate_name   EXCEPTION;
    emp_id             EMPLOYEER.EMPLOYEER_ID%TYPE;
    emp_new_id         EMPLOYEER.EMPLOYEER_ID%TYPE := '700001';
 BEGIN
    SELECT employeer_id INTO emp_id FROM employeer WHERE employeer_id = '800001';
 
    IF emp_id = emp_new_id
    THEN
       RAISE e_duplicate_name;
    END IF;
 
    INSERT INTO employeer VALUES ('10', emp_new_id, 'aaaaa', 'aaaa',SYSDATE);
 EXCEPTION
    WHEN e_duplicate_name
    THEN
       DBMS_OUTPUT.put_line ('不能插入重复的工号');
    WHEN OTHERS
    THEN
       DBMS_OUTPUT.put_line (
          '异常编码:' || SQLCODE || ' , 异常信息:' || SQLERRM);
 END;
 
不能插入重复的工号
异常编码:-1722 , 异常信息:ORA-01722: 无效数字

SQLCODE:数据库操作的返回码
SQLERRM是一则函数。oracle sqlerrm函数 sqlerrm函数返回指定错误代码的错误信息。

 4、预定义异常:

  预定义异常的使用,只需将异常名称放在WHEN子句后面即可,使用时只需要使用它的异常名称即可

DECLARE
   v_temp   VARCHAR2 (10);
BEGIN
   v_temp := 'abcdefghijklmn';
EXCEPTION
   WHEN VALUE_ERROR
   THEN
      DBMS_OUTPUT.put_line ('出现VALUE_ERROR错误,错误编码为:' || SQLCODE || ' , 错误名称:' || SQLERRM);
END;
出现VALUE_ERROR错误,错误编码为:-6502 , 错误名称:ORA-06502: PL/SQL: 数字或值错误 :  字符串缓冲区太

 5、自定义异常:

  • 5.1、声明异常
  • DECLARE
       e_duplicate_name   EXCEPTION;   --自定义异常
    BEGIN
       NULL;
    END
  • 5.2、作用域范围
    •  ①、在同一个块中不能声明一个异常超过两次,但是可以在不同的块中声明相同的异常
    •  ②、在一个块中声明的异常在本块中和其子块中可见,也就是说在内存块可以引用在外层块中定义的异常,可以引用在本地中定义的异常,但不能引用在子块中定义的异常
  • DECLARE
       e_duplicate_name   EXCEPTION;   --定义外层块异常
    BEGIN
       DECLARE
          e_duplicate_name   EXCEPTION;   --覆盖了外层块中的异常
       BEGIN
          RAISE e_duplicate_name;      --触发内存块中的异常
       END;
    EXCEPTION
       WHEN e_duplicate_name         --此时并不能捕捉获取改异常
       THEN
          DBMS_OUTPUT.put_line ('出现错误,错误编码为:' || SQLCODE || ' , 错误名称:' || SQLERRM);            --显示错误编码和错误消息
       WHEN OTHERS THEN            --以其他异常被传递
          NULL;
    END;
  • 5.3、使用RASIE_APPLICATION_ERROR
    •   RASIE_APPLICATION_ERROR在子程序内部使用时,能够帮助用户从存储子程序中抛出用户自定义的错误消息
    •   语法:RASIE_APPLICATION_ERROR(error_number, error_message, [keep_errors]);
    •       error_number:范围在-20000到-20999之间的负数
    •       error_message:是最大长度为2048字节的字符串
    •       keep_error:是一个可选的布尔值,当值为True,新的错误将被添加到已经抛出的错误列表中,默认值为False,将新的错误代替当前的错误列表
    •       注意:RASIE_APPLICATION_ERROR只能在存储的子程序中调用,当被调用时,将结束当前的子程序并返回一个用户自定义的错误代码和错误消息给应用程序,这些错误代码和错误消息可以被任何Oracle错误一样被捕捉
  • CREATE OR REPLACE PROCEDURE REGISTEREMPLOYEER (
       p_deaprt_id     IN EMPLOYEER.DEPARTMENT_ID%TYPE,
       p_emp_id        IN EMPLOYEER.EMPLOYEER_ID%TYPE,
       p_emp_name      IN EMPLOYEER.EMPLOYEER_NAME%TYPE,
       p_emp_saylary   IN EMPLOYEER.EMPLOYEER_SALARY%TYPE)
    AS
       v_num   NUMBER;
    BEGIN
       IF p_emp_id IS NULL                                        --如果工号为NULL则触发错误
       THEN
          raise_application_error (-20000, '员工编号不能为空'); --触发应用程序异常
       ELSE
          SELECT COUNT (*)
            INTO v_num
            FROM employeer
           WHERE employeer_id = p_emp_id;
    
          IF v_num > 0
          THEN
             raise_application_error (-20000, '员工编号为:' || p_emp_id || '的员工工号已经存在'); --触发应用程序异常
          END IF;
       END IF;
    
       INSERT INTO employeer VALUES (p_deaprt_id, p_emp_id, p_emp_name, p_emp_saylary, SYSDATE);
    EXCEPTION
       WHEN OTHERS              --捕捉应用程序异常
       THEN
          raise_application_error (-20003,'插入数据是出现错误。异常编码为:'|| SQLCODE || '异常描述' || SQLERRM);
    END;

     

  • 5.4、抛出异常
    •   Oracle显式地使用RAISE语句抛出异常
    •       语法:RAISE exception_name
  • 5.5、处理异常
    •   当异常被触发,控制将转到语句块异常处理区
    •       语法: EXCEPTION WHEN exception_name THEN
  • DECLARE
       e_nocomm   EXCEPTION;
       v_comm     NUMBER;
       v_empno    NUMBER := &empno;
    BEGIN
       SELECT employeer_salary INTO v_comm FROM employeer WHERE employeer_id = v_empno;
       
       IF v_comm < 0
       THEN
          RAISE e_nocomm;
       END IF;
    EXCEPTION
       WHEN e_nocomm
       THEN
          DBMS_OUTPUT.PUT_LINE ('员工的工资不正确');
       WHEN NO_DATA_FOUND
       THEN
          DBMS_OUTPUT.PUT_LINE ('没有找到任何数据');
       WHEN OTHERS
       THEN
          DBMS_OUTPUT.PUT_LINE ('其他未处理的异常');
    END;

    NO_DATA_FOUND表示查询的数据为空,可以专门处理这种业务

  • 一个处理器中处理多个异常
  • DECLARE
       e_nocomm   EXCEPTION;
       v_comm     NUMBER;
       v_empno    NUMBER := &empno;
    BEGIN
       SELECT employeer_salary
         INTO v_comm
         FROM employeer
        WHERE employeer_id = v_empno;
    
       IF v_comm < 0
       THEN
          RAISE e_nocomm;
       END IF;
    EXCEPTION
       WHEN e_nocomm OR NO_DATA_FOUND
       THEN
          DBMS_OUTPUT.PUT_LINE ('员工的工资出现异常');
       WHEN OTHERS
       THEN
          DBMS_OUTPUT.PUT_LINE ('其他未处理的异常');
    END;

     

6、异常的传递

  异常传递是指当异常被抛出时,执行立即跳转到EXCEPTION语句块中的异常处理器,在异常处理器中查找是否有匹配的异常,如果在当前的PL/SQL块或子程序中没有找到对应的异常处理器,

  那么这个异常会向其PL/SQL块外层或子程序的调用方传递,知道没有可以搜索到的块为止,这里PL/SQL引擎抛出一个未处理的异常

  • 6.1、执行时异常传递
    •   执行时异常传递是指在PL/SQL块的执行部分抛出异常的传递机制,当在执行部分抛出异常后,PL/SQL使用下面的机制来确定使用哪一种处理器
  • 6.2、声明时异常传递
  • 6.3、异常处理器中的异常
  • 6.4、重新抛出异常
  • 6.5、异常处理准则

posted on 2016-11-22 09:48  LiGengMing  阅读(772)  评论(0编辑  收藏  举报

导航