PL/SQL例外的介绍

PL/SQL例外的介绍
PL/SQL预定义的例外及code如下:
Exception                             Oracle Error  SQLCODE Value  含义
ACCESS_INTO_NULL             ORA-06530        -6530          引用对象没有初始化直接为对象赋值
CASE_NOT_FOUND               ORA-06592        -6592          如果在when子句中没有case没有包含必须的分支且没有else子句时
COLLECTION_IS_NULL          ORA-06531        -6531          集合元素(嵌套表或varray)必须先初始化,没有则触发该错误
CURSOR_ALREADY_OPEN      ORA-06511        -6511         重新打开已经打开的游标
DUP_VAL_ON_INDEX             ORA-00001        -1              当在唯一索引列上键入重复值时
INVALID_CURSOR                 ORA-01001        -1001         当试图在不合法的游标上操作时
INVALID_NUMBER                 ORA-01722        -1722         内嵌sql语句不能有效地将字符转为数字,如100写成了1oo
LOGIN_DENIED                     ORA-01017        -1017         当执行PL/SQL程序时,需要登录oracle,而提供的用户密码不对时  
NO_DATA_FOUND                 ORA-01403        +100          当执行select into操作没有返回行时
NOT_LOGGED_ON                 ORA-01012        -1012         执行PLSQL应用程序时,没有登录到数据库
PROGRAM_ERROR                 ORA-06501        -6501         出现该问题,说明PL/SQL内部出现问题
ROWTYPE_MISMATCH            ORA-06504        -6504         当执行赋值操作,宿主游标变量和PL/SQL游标变量返回的类型不匹配
SELF_IS_NULL                      ORA-30625        -30625        使用对象类型时,在null实例上调用成员时(必须先初始化)
STORAGE_ERROR                 ORA-06500        -6500         PL/SQL块运行,当内存不足或内存被损坏时
SUBSCRIPT_BEYOND_COUNT ORA-06533        -6533         当使用嵌套表或varray时,其元素下标超出了元素范围
SUBSCRIPT_OUTSIDE_LIMIT  ORA-06532        -6532         当使用嵌套表或varray时,其元素下标为赋值时
SYS_INVALID_ROWID           ORA-01410        -1410         将字符串转换为rowid时,必须使用有效的字符串
TIMEOUT_ON_RESOURCE      ORA-00051        -51             等待超时
TOO_MANY_ROWS               ORA-01422        -1422          当执行select into操作返回多行时
VALUE_ERROR                     ORA-06502        -6502          当在PL/SQL块赋值操作时,变量长度不足以容纳实际数据
ZERO_DIVIDE                      ORA-01476        -1476          当使用PL/SQL块时,使用数字除0

对于非定义例外:
    对于自己定义的例外,可以自己定义 pragma exception_init 来定义出现定义的例外名称和例外的sqlcode。
  declare
    e_exception exception;
    pragma exception_init(e_exception, -2291);
    e_no_employ exception;
  begin
    update emp set deptno = &dno where empno = &eno;
    if sql%notfound then
      raise e_no_employ;
    end if;
  exception
    when e_exception then
      dbms_output.put_line('该部门不存在');
    when e_no_employ then
      dbms_output.put_line('该雇员不存在');
  end;

例外函数的使用:
    1)SQLCODE函数用于取得oracle错误号;
    2)SQLERRM函数用于取得与之相关的错误消息;
    3)在存储过程、函数、包中使用RAISE_APPLICATION_ERROR可以自定义错误号和错误信息。
  1、SQLCODE和SQLERRM
  SQLCODE用于返回oracle错误号,SQLERRM用于返回该错误号对应的错误消息。为了在PL/SQL应用程序中处理其他未预料到的oracle错误,用户可以在例外处理部分的when others子句后引用这两个函数,以取得相关的oracle错误。示例如下:
    undef v_sal
    declare
      v_ename emp.ename%type;
    begin
      select ename into v_ename from emp where sal = &v_sal;
      dbms_output.put_line('雇员名:' || v_ename);
    exception
      when no_data_found then
        dbms_output.put_line('不存在工资为:' || &v_sal || '的雇员');
      when others then
        dbms_output.put_line('错误号:' || sqlcode);
        dbms_output.put_line(sqlerrm);
    end;

 2、raise_application_error
    该过程用于在PL/SQL应用程序中自定义错误消息。注意,该过程只能在数据库端的子程序(过程、函数、包、触发器)中使用,而不能在匿名块和
客户端的子程中使用。
    raise_application_error语法如下:
    raise_application_error(error_number,message[,{true | false}]);
    其中:
    error_number表示定义错误号,该错误号必须在-20000到-20999之间的负整数;
    message用于指定错误消息,并且该长度不能超过2048字节;
    第三个参数为可选参数,若为true,则该错误会被放在先前错误堆栈中;如果设为false(默认值),则会替换先前所有错误。
  create or replace procedure raise_comm(eno number, commission number) is
    v_comm emp.comm%type;
  begin
    select comm into v_comm from emp where empno = eno;
    if v_comm is null then
      raise_application_error(-20001, '该雇员无补助');
    end if;
  exception
    when no_data_found then
      dbms_output.put_line('该雇员不存在');
  end;
 /*2011-6-2关于例外增加部分

 如何在一个循环中扑捉例外并能继续执行--解决办法,在loop里面再增加一个块,如下代码所示:

 如果是将例外直接放到最后那么遇到一条错误的记录就直接跳出不执行了。

CREATE OR REPLACE PROCEDURE update_district IS
  TYPE v_fid_varray IS TABLE OF l_interest_s.g3e_fid%TYPE;
  v_fid  v_fid_varray;
  v_name VARCHAR2(10);
  CURSOR fid_cur IS
    SELECT g3e_fid
      FROM gc_netelem
     WHERE g3e_fno = 15000
       AND district IS NULL;
BEGIN
  OPEN fid_cur;
  LOOP
    FETCH fid_cur BULK COLLECT
      INTO v_fid LIMIT 10000;  
    IF v_fid IS NOT NULL AND v_fid.count > 0 THEN
      FOR i IN v_fid.first .. v_fid.last LOOP
        BEGIN
          SELECT a.name
            into v_name
            FROM p_region_s a, l_interest_s b
           WHERE sdo_relate(a.gwm_geometry,
                            b.gwm_geometry,
                            'MASK = ANYINTERACT') = 'TRUE'
             AND b.g3e_fid = v_fid(i);       
        EXCEPTION
          WHEN no_data_found THEN
            v_name := NULL;          
            UPDATE gc_netelem t
               SET t.district    = v_name,
                   t.district_id = pkg_public.f_getdistinctid(v_name, '')
             WHERE t.g3e_fid = v_fid(i);
        END;
      END LOOP;
      COMMIT;
    END IF;
    EXIT WHEN fid_cur%NOTFOUND;
  END LOOP;
  CLOSE fid_cur;
END;

*/

 PLSQL编译警告
  1、PLSQL警告分类
 1)severe:该中警告用于检查可能出现的不可预料结果或错误结果,例如参数的别名问题。
 2)performance:该类警告用于检查可能引起的性能问题,例如在执行insert操作时为number列提供了varchar2类型的数据。
 3)informational:该类警告用于检查子程序中的死代码。
 4)all:该关键字用于检查所有警告(severe,performance,informational)。
  2、控制PL/SQL警告信息
 在编译时是否会出现上述的几种警告类型,由PLSQL_WARNINGS参数控制。该初始化参数可以在系统级或会话级设置,也可以在ALTER PROCEDURE命令中进行设置。
 ALTER SYSTEM SET PLSQL_WARNINGS='ENABLE:ALL';
 ALTER SESSION SET PLSQL_WARNINGS='ENABLE:PERFORMANCE';
 ALTER PROCEDURE hello COMPILE PLSQL_WARNINGS='ENABLE:PERFORMANCE';
 ALTER SESSION SET PLSQL_WARNINGS='DISABLE:ALL';
 ALTER SESSION SET PLSQL_WARNINGS='ENABLE:SEVERE','DISABLE:PERFORMANCE','ERROR:06002';
激活或禁止PL/SQL编译警告还可以使用PL/SQL系统包DBMS_WARNINGS。
CALL DBMS_WARNING.set_warning_setting_string('ENABLE:ALL','SESSION');
 3、使用PL/SQL编译警告
 1)检测死代码
--以下为含有死代码的一个过程(死代码即指在在程序中永不被执行的代码)
create or replace procedure dead_code as
  x number :10;
begin
  if x = 10 then
    x :20;
  else
    x :100; --else永不会执行到
  end if;
end dad_code;
为了检测该子程序是否包含死代码,必须先激活警告检查,然后重新编译子程序,最后使用show errors命令显示警告错误。
alter session set plsql_warnings='enable:informational';
alter procedure dead_code compile;
show errors;

2)检测引起性能问题的代码
  create or replace procedure update_sal(name varchar2, salary varchar2) is
  begin
    update emp set sal = salary where ename = name;
  end;
SQL> alter session set plsql_warnings='enable:performance';
Session altered
SQL> alter procedure update_sal compile;
Procedure altered
SQL> show errors;
Errors for PROCEDURE SCOTT.UPDATE_SAL:
LINE/COL ERROR
-------- ---------------------------------------------------
3/26     PLW-07202: 绑定类型可能会导致从列类型转换为其它类型


原文地址:https://www.cnblogs.com/lanzi/p/2016329.html