PL/SQL -- 异常处理 Exception

               

--================================

-- PL/SQL --> 异常处理(Exception)

--================================

 

 

 

    Exception是一种PL/SQL标识符,当运行的PL/SQL块出现错误或警告,则会触发异常处理。为了提高程序的健壮性,可以在PL/SQL块中引

入异常处理部分,进行捕捉异常,并根据异常出现的情况进行相应的处理。

 

一、异常的类型 

    ORACLE异常分为两种类型:系统异常、自定义异常。

    其中系统异常又分为:预定义异常和非预定义异常。

 

    1.预定义异常

        ORACLE定义了他们的错误编号和异常名字,常见的预定义异常处理Oracle常见的错误

   

        NO_DATA_FOUND          SELECT ... INTO ... 时,没有找到数据

        DUL_VAL_ON_INDEX       试图在一个有惟一性约束的列上存储重复值

        CURSOR_ALREADY_OPEN    试图打开一个已经打开的游标

        TOO_MANY_ROWS          SELECT ... INTO ... 时,查询的结果是多值

        ZERO_DIVIDE            零被整除

 

    2.非预定义异常

        ORACLE为它定义了错误编号,但没有定义异常名字。我们使用的时候,先声名一个异常名,

        通过伪过程PRAGMA EXCEPTION_INIT,将异常名与错误号关联起来。

 

    3.自定义异常

        程序员从我们业务角度出发,制定的一些规则和限制。

 

二、异常处理

    PL/SQL中,异常处理按个步骤进行:

        定义异常

        抛出异常

        捕获及处理异常

 

    a.定义异常

        exception_name EXCEPTION;

 

    b.抛出异常

        RAISE exception_name

 

    c.捕获及处理异常

        EXCEPTION

            WHEN e_name1 [OR e_name2 ... ] THEN

                statements;

            WHEN e_name3 [OR e_name4 ... ] THEN

                statements;

                ......

            WHEN OTHERS THEN

                statements;

        END;

        /

 

 

三、异常处理示例   

    1.预定义异常的例子

        --演示一个整除的异常

            DECLARE

                v_n1 NUMBER:=50;

                v_n2 NUMBER:=0;

                v_n3 NUMBER;

            BEGIN

                v_n3:=v_n1/v_n2;

                DBMS_OUTPUT.PUT_LINE('v_n3='||v_n3);

            EXCEPTION

                WHEN ZERO_DIVIDE  THEN

                    DBMS_OUTPUT.PUT_LINE('v_n2 don't is 0');       

            END;

            /

       

        --演示VALUE_ERROR(错误号ORA-06502)

            scott@ORCL> declare

              2  v_ename varchar2(3);

              3  begin

              4      select ename into v_ename from emp where empno=&eno;

              5      dbms_output.put_line(v_ename);

              6  exception

              7      when value_error then

              8      dbms_output.put_line('variable datatype length is small');

              9  end;

             10  /

            Enter value for eno: 7788

            old   4:     select ename into v_ename from emp where empno=&eno;

            new   4:     select ename into v_ename from emp where empno=7788;

            variable datatype length is small

 

            PL/SQL procedure successfully completed.       

       

        --演示TOO_MANY_ROWS(对应Oracle错误号ORA-01422)

            scott@ORCL> declare

              2  v_ename emp.ename%type;

              3  begin

              4      select ename into v_ename from emp where deptno=&dno;

              5  exception

              6      when too_many_rows then

              7      dbms_output.put_line('Too many rows are returned');

              8  end;

              9  /

            Enter value for dno: 10

            old   4:     select ename into v_ename from emp where deptno=&dno;

            new   4:     select ename into v_ename from emp where deptno=10;

            Too many rows are returned

 

            PL/SQL procedure successfully completed.           

       

    2.非预定义异常

        非预定义异常使用的基本过程

            a.定义一个异常名

            b.将异常名与异常编号相关联

            c.在异常处理部分捕捉并处理异常

       

        DECLARE

            e_deptid EXCEPTION;

            PRAGMA EXCEPTION_INIT(e_deptid,-2292);

        BEGIN

            DELETE FROM DEPT WHERE DEPTNO=10;

        EXCEPTION

            WHEN e_deptid THEN

                DBMS_OUTPUT.PUT_LINE('at sub table have record!');

        END;

        /

 

        DECLARE

            e_emp EXCEPTION;

            PRAGMA EXCEPTION_INIT(e_emp,-2291);

        BEGIN

            INSERT INTO EMP(empno,deptno) VALUES (7935,60);

        EXCEPTION

            WHEN e_emp THEN

                DBMS_OUTPUT.PUT_LINE('60 at table dept not exist');

        END;

        /  

 

    3.自定义异常

        自定义异常与Oracle错误没有任何关系,有开发人员为特定情况所定义的例外

        下面的例子中当输入empno为时,尽管该雇员编号不存在,但PL/SQL代码并未给出适当的提示

            scott@ORCL> declare

              2  e_integrity exception;

              3  pragma exception_init(e_integrity,-2291);

              4  begin

              5      update emp set deptno=&dno where empno=&eno;

              6  exception

              7      when e_integrity then

              8      dbms_output.put_line('The dept is not exists');

              9  end;

             10  /

            Enter value for dno: 20

            Enter value for eno: 1111

            old   5:     update emp set deptno=&dno where empno=&eno;

            new   5:     update emp set deptno=20 where empno=1111;

 

            PL/SQL procedure successfully completed.

 

        针对上述情况,可以使用自定义异常处理。

        对于自定义的异常处理需要显示的触发,其步骤如下

            a.定义异常(declare部分进行定义)

            b.显示触发异常(在执行BEGIN部分触发异常,使用RAISE语句)

            c.引用异常(EXCEPTION部分捕捉并处理异常)

       

        --对上面的例子,使用自定义异常来处理,代码如下:

            scott@ORCL> declare

              2  e_integrity exception;

              3  pragma exception_init(e_integrity,-2291);

              4  e_no_employee exception;

              5  begin

              6      update emp set deptno=&dno where empno=&eno;

              7      if sql%notfound then

              8          raise e_no_employee;

              9      end if;

             10  exception

             11      when e_integrity then

             12          dbms_output.put_line('The dept is not exists');

             13      when e_no_employee then

             14          dbms_output.put_line('The employee is not exists');

             15  end;

             16  /

            Enter value for dno: 20

            Enter value for eno: 1234

            old   6:     update emp set deptno=&dno where empno=&eno;

            new   6:     update emp set deptno=20 where empno=1234;

            The employee is not exists

 

            PL/SQL procedure successfully completed.       

       

        --下面的例子中,如果插入的工资少于,就抛出异常

            DECLARE

                v_sal emp.sal%TYPE;

                v_id emp.empno%TYPE;

                e_sal EXCEPTION;      --定义异常

            BEGIN

                v_id:=&inputid;

                v_sal:=&inputsal;

                INSERT INTO emp (empno,sal) VALUES (v_id,v_sal);

                IF v_sal<700 THEN

                    RAISE e_sal;      --捕捉异常

                END IF;

            EXCEPTION                 --处理异常

                WHEN e_sal THEN

                    ROLLBACK;

                    DBMS_OUTPUT.PUT_LINE('Sal must be more than 700'); 

            END;

            /

           

四、使用异常函数处理异常           

    1.SQLCODESQLERRM函数

        函数SQLCODE用于取得Oracle错误号

        函数SQLERRM用于取得与错误号对应的相关错误消息

            scott@ORCL> get /u01/bk/scripts/sqlcode_errm.sql

              1  undef v_sal

              2  declare

              3      v_ename emp.ename%type;

              4      begin

              5          select ename into v_ename from emp

              6          where sal=&&v_sal;

              7          dbms_output.put_line('Employee Name:'||v_ename);

              8  exception

              9      when no_data_found then

             10          dbms_output.put_line('The employee is not exists for salary '||&v_sal);

             11      when others

猜你喜欢

转载自blog.csdn.net/uffvhj/article/details/87437679
今日推荐