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.SQLCODE与SQLERRM函数

        函数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 then

             12          dbms_output.put_line('Error No:'||SQLCODE);

             13          dbms_output.put_line(SQLERRM);

             14* end;

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

            Enter value for v_sal: 1600

            old   5:         where sal=&&v_sal;

            new   5:         where sal=1600;

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

            new   9:         dbms_output.put_line('The employee is not exists for salary '||1600);

            Error No:-1422

            ORA-01422: exact fetch returns more than requested number of rows

 

            PL/SQL procedure successfully completed.   

 

    2.RAISE_APPLICATION_ERROR

        是将应用程序专有的错误从服务器端转达到客户端应用程序(其他机器上的SQLPLUS或者其他前台开发语言)。

        该函数用于在PL/SQL中定义错误消息,且只能在数据库端的子程序中使用(存储过程、函数、包、触发器),不能在匿名块和客户端的

        子程序中使用

 

        使用方法

            RAISE_APPLICATION_ERROR(error_number,message[,{true | false}]);

           

            该函数内的错误代码和内容,都是用用户自定义

            error_number:用于定义错误号,且错误号从-20000 到-20999 之间,以避免与ORACLE 的任何错误代码发生冲突。

            message:用于指定错误消息,且消息长度不能超过k,超出部分将被截取

            可选参数true,false:默认值为false,会替换先前的所有错误。当设置为true,则该错误会被放在先前错误堆栈中。

           

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

              1  create or replace procedure raise_comm

              2  (v_no emp.empno%type,v_comm out emp.comm%type)

              3  as

              4  begin

              5       select comm into v_comm from emp where empno=v_no;

              6       if v_comm is null then

              7           raise_application_error(-20001,'It is no comm for this employee');

              8       end if;

              9  exception

             10       when no_data_found then

             11       dbms_output.put_line('The employee is not exist');

             12* end;

            scott@ORCL> start /u01/bk/scripts/sp_raise_comm.sql

 

            Procedure created.

 

            scott@ORCL> variable g_sal number;

            scott@ORCL> call raise_comm(7788,:g_sal);

            call raise_comm(7788,:g_sal)

                 *

            ERROR at line 1:

            ORA-20001: It is no comm for this employee

            ORA-06512: at "SCOTT.RAISE_COMM", line 7

                       

            scott@ORCL> call raise_comm(7499,:g_sal);

 

            Call completed.

 

            scott@ORCL> print g_sal

 

                 G_SAL

            ----------

                   300     

 

五、PL/SQL编译警告

    1.PL/SQL警告的分裂

        SEVERE: 用于检查可能出现的不可预料结果或错误结果,例如参数的别名问题.

        PERFORMANCE: 用于检查可能引起性能问题,如在INSERT操作是为NUMBER列提供了VARCHAR2类型数据.

        INFORMATIONAL: 用于检查程序中的死代码.

        ALL: 用于检查所有警告.

   

    2.控制PL/SQL警告消息

        通过设置初始化参数PLSQL_WARNINGS来启用在编译PL/SQL子程序时发出警告消息,缺省为DISABLE:ALL

        警告消息设置的级别

            系统级别

            会话级别

            ALTER PROCEDURE

            既可以激活或禁止所有警告类型,也可以激活或禁止特定消息号

            scott@ORCL> show parameter plsql%ings;

 

            NAME                                 TYPE        VALUE

            ------------------------------------ ----------- ------------------------------

            plsql_warnings                       string      DISABLE:ALL       

           

            scott@ORCL> ALTER SYSTEM SET PLSQL_WARNINGS='ENABLE:ALL' |'DISABLE:ALL'

            scott@ORCL> ALTER SESSION SET PLSQL_WARNINGS='ENABLE:PERFORMANCE' |'DISABLE:ALL'

            scott@ORCL> ALTER PROCEDURE usp COMPILE PLSQL_WARNINGS='ENABLE:PERFORMANCE';

            scott@ORCL> ALTER SESSION SET PLSQL_WARNINGS='ENABLE:SEVERE','DISABLE:PERFORMANCE','ERROR:06002';

   

    3.演示PL/SQL编译告警

        a.检测死代码

            在下面的代码中,ELSE子句永远不会执行,应该避免出现类似的死代码.

            从Oracle 10g开始,在编写PL/SQL子程序之前开发人员可以激活警告检查.

           

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

                  1  CREATE OR REPLACE PROCEDURE dead_code AS

                  2     x number := 10;

                  3  BEGIN

                  4     IF x>0 THEN

                  5             x:=1;

                  6     ELSE             

                  7             x:=2;    --死代码

                  8     END IF;

                  9* END dead_code;

               

                scott@ORCL> start /u01/bk/scripts/dead_code.sql

               

                scott@ORCL> alter session set plsql_warnings='enable:informational';

               

                scott@ORCL> show parameter plsql%ings

 

                NAME                                 TYPE        VALUE

                ------------------------------------ ----------- ------------------------------

                plsql_warnings                       string      ENABLE:INFORMATIONAL, DISABLE:

                                                                 PERFORMANCE, DISABLE:SEVERE

                                                                 

                scott@ORCL> alter procedure dead_code compile;

 

                SP2-0805: Procedure altered with compilation warnings          

 

                scott@ORCL> show errors;

                Errors for PROCEDURE DEAD_CODE:

 

                LINE/COL ERROR

                -------- -----------------------------------------------------------------

                4/6      PLW-06002: Unreachable code

                7/3      PLW-06002: Unreachable code

       

        b.检测引起性能问题的代码

            scott@ORCL> create or replace procedure update_sal

              2  (no number,salary varchar2)

              3  as

              4  begin

              5      update emp set sal=salary where empno=no;

              6  end;

              7  /

 

            Procedure created.

 

            scott@ORCL> alter session set plsql_warnings='enable:performance';

 

            scott@ORCL> alter procedure update_sal compile;

 

            SP2-0805: Procedure altered with compilation warnings

 

            scott@ORCL> show errors

            Errors for PROCEDURE UPDATE_SAL:

 

            LINE/COL ERROR

            -------- -----------------------------------------------------------------

            5/24     PLW-07202: bind type would result in conversion away from column      

           

六、更多参考

 

有关SQL请参考

        SQL 基础--> 子查询

        SQL 基础-->多表查询

SQL基础-->分组与分组函数

SQL 基础-->常用函数

SQL 基础--> ROLLUP与CUBE运算符实现数据汇总

SQL基础-->层次化查询(START BY ... CONNECT BY PRIOR)

 

    有关PL/SQL请参考

        PL/SQL --> 语言基础

PL/SQL --> 流程控制

PL/SQL --> 存储过程

PL/SQL --> 函数

PL/SQL --> 游标

PL/SQL -->隐式游标(SQL%FOUND)

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

PL/SQL --> PL/SQL记录

PL/SQL --> 包的创建与管理

PL/SQL --> 包重载、初始化

PL/SQL --> DBMS_DDL包的使用

PL/SQL --> DML 触发器

PL/SQL --> INSTEAD OF 触发器

 

 

时间: 2024-09-24 03:28:48

PL/SQL --&gt; 异常处理(Exception)的相关文章

PL/SQL的异常处理机制的初步探讨

PL/SQL中如何在抛出异常后继续 这个问题曾一度让我郁闷,很有用的技巧! SQL> declare 2 type testitb is table of number index by binary_integer; a testitb; b number; 3 4 5 begin a(10):=11; 6 7 a(1):=12; a(4):=4; 8 9 for i in a.first .. a.last loop 10 11 b:=i; 12 dbms_output.put_line('

PL/SQL异常处理初步

PL/SQL处理异常不同于其他程序语言的错误管理方法,PL/SQL的异常处理机制与ADA很相似,有一个处理错误的全包含方法.当发生错误时,程序无条件转到异常处理部分,这就要求代码要非常干净并把错误处理部分和程序的其它部分分开.oracle允许声明其他异常条件类型以扩展错误/异常处理.这种扩展使PL/SQL的异常处理非常灵活. 当一个运行时错误发生时,称为一个异常被抛出.PL/SQL程序编译时的错误不是能被处理得异常,只有在运行时的异常能被处理.在PL/SQL程序设计中异常的抛出和处理是非常重要的

PL/SQL学习笔记(一)

断断续续学过,这次系统地来读读. (一) PL/SQL是oracle在标准SQL语言上的过程性扩展,它不仅允许嵌入SQL语句,而且允许定义变量和常量,允许过程语言结构(条件语句和循环语句),允许使用异常处理oracle错误等.通过使用PL/SQL,可以在一个PL/SQL块中包含多条SQL语句和PL/SQL语句.PL/SQL具有以下优点: 1.提高应用系统的运行性能. 通过使用PL/SQL块包含多条SQL语句,从而减少了SQL语句的发送次数,降低了网络开销,提高了应用程序性能 2.提供模块化的程序

PL/SQL异常处理

     在设计PL/SQL程序时,经常会发生这样或那样的错误,异常处理就是针对错误进行处理的程序段,Oracle 9i中的异常处理分为系统预定义异常处理和自定义异常处理两部分. 系统预定义异常处理     系统预定义异常处理是针对PL/SQL程序编译.执行过程中发生的问题进行处理的程序. 下列代码为正确代码,在[SQLPlus Worksheet]中能够顺利执行.    ―――――――――――――――――――――――――――――――――――――    set serveroutput on  

PL/SQL中的几种异常处理方法

异常处理 这是Pona的文章,我斗胆将其贴上来,Pona不要介意哦!^_^   PL/SQL里,有三种方法可以在处理大批量数据时不会因为一条或几条数据错误而导致异常中止程序.   1.用Fetch into a cursor%TYPE把要处理的数据放到记录集里.当一条数据不符条件时,用标签<<NEXT_RECORD>>和GOTO NEXT_RECORD跳转语句使程序忽略这一条,转到下一条继续处理. ------------------------------------------

PL/SQL6——异常处理(Exception)

 Exception是一种PL/SQL标识符,当运行的PL/SQL块出现错误或警告,则会触发异常处理.为了提高程序的健壮性,可以在PL/SQL块中引 入异常处理部分,进行捕捉异常,并根据异常出现的情况进行相应的处理.   一.异常的类型      ORACLE异常分为两种类型:系统异常.自定义异常.     其中系统异常又分为:预定义异常和非预定义异常.       1.预定义异常         ORACLE定义了他们的错误编号和异常名字,常见的预定义异常处理Oracle常见的错误      

PL/SQL异常处理(原创)

Exception概述 Exception是一种PL/SQL标识符,当运行的PL/SQL块出现错误或警告,则会触发异常处理.为了提高程序的健壮性,可以在PL/SQL块中引入异常处理部分,进行捕捉异常,并根据异常出现的情况进行相应的处理.ORACLE异常分为两种类型:系统异常.自定义异常.其中系统异常又分为:预定义异常和非预定义异常.预定义异常ORACLE定义了他们的错误编号和异常名字,常见的预定义异常处理如下 错误号 异常错误信息名称 说明 ORA-0001 Dup_val_on_index 违

PL/SQL异常处理介绍

1.定义 异常:PL/SQL在执行的过程中所产生的标识符,PL/SQL中的一个警告或错误都被称为异常. 错误通常分为两类: 编译时错误--一般是语法错误,由PL/SQL引擎发现并报告给用户,程序本身不能处理,因为还没运 行. 运行时错误--程序在运行时引发的错误,例如没返回结果与返回多个结果(只能返回一行结果的情 况下) 异常处理---通常是指处理运行时错误. 引发异常的一个重要原因是处理数据时发生错误.统计表明,SELECT语句.DML语句以及游标操作语 句更容易引发异常. 编写PL/SQL块

oracle-Oracle PL/SQL 外键关联的异常处理

问题描述 Oracle PL/SQL 外键关联的异常处理 删除父表记录后, 若不写异常处理器,则会报错,并自动回滚所有被删除的数据. 若写了异常处理器,则在异常处理中回滚,只能恢复父表记录, 而子表中对应的记录被删除仍无法恢复. 预期结果应该是在回滚之后被删除的所有记录都恢复. 解决方案 外键关联肯定不能直接删除父表啊 可以这么做, 方法一:先删除外键关联,再去删除父表 方法二:先删除子表,再去删除父表 解决方案二: Oracle:pl/sql 异常处理 解决方案三: 同意1楼说的,删子,再删父