IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    Oracle学习笔记——异常处理

    果冻想发表于 2015-08-12 15:18:46
    love 0

    说说异常

    在总结PL/SQL的基础知识时,说到了以下内容:

    [declare]
        -- declaration statements
        i integer;
    begin
        -- executable statements
    
    [exception]
        -- exception statements
    end;
    

    对于其中的exception没有进行详细的总结,那么exception在Oracle又是怎么样的呢?出现了exception又要如何处理呢?这篇文章就对Oracle中的exception进行详细的总结。

    Oracle预定义异常

    在Oracle中,异常分为以下两类:

    • Oracle预定义异常
    • 用户自定义异常

    在Oracle中预定义的异常如下表所示:

    异常名称 错误代码 产生原因
    ACCESS_INTO_NULL 06530 为一个未初始化对象的属性赋值
    CASE_NOT_FOUND 06592 在CASE过程中,WHEN后没有包含必要的条件分支并且没有ELSE子句
    COLLECTION_IS_NULL 06531 使用未初始化的集合元素
    CURSOR_ALREADY_OPEN 06511 游标已经打开
    DUP_VAL_ON_INDEX 00001 在具有唯一索引的列上插入一个重复值
    INVALID_CURSOR 01001 在无效的游标上进行操作
    INVALID_NUMBER 01722 在一个SQL语句中,由于字符串并不代表一个有效的数字,导致字符串向数字转换时会发生错误。(在过程化语句中,会抛出异常VALUE_ERROR。)当FETCH语句的LIMIT子句表达式后面不是一个正数时,这个异常也会被抛出。
    LOGIN_DENIED 01017 使用错误的用户名或密码登陆数据库
    NO_DATA_FOUND 01403 SELECT INTO未返回行,或者程序引用了嵌套表中一个已经删除的元素,或者引用表中一个为初始化的元素
    NOT_LOGGED_ON 01012 没有连接到数据库
    PROGRAM_ERROR 06501 PL/SQL内部错误
    ROWTYPE_MISMATCH 06504 赋值语句中使用的主游标变量和PL/SQL游标变量的类型不兼容
    SELF_IS_NULL 30625 调用一个未被实例化的对象的成员方法,内置的SELF参数总是指向这个对象,SELF会作为函数的第一个参数传递到这个成员方法,就好比C++中的this
    STORAGE_ERROR 06500 内存溢出或者内存不足
    SUBSCRIPT_BEYOND_COUNT 06533 程序引用一个嵌套表或变长数组元素,但使用的下标索引超过嵌套表或变长数组元素总个数
    SUBSCRIPT_OUTSIDE_LIMIT 06532 程序引用一个嵌套表或变长数组,但使用的下标索引不在合法的范围内
    SYS_INVALID_ROWID 01410 从字符串向ROWID转换发生错误,因为字符串并不代表一个有效的ROWID
    TIMEOUT_ON_RESOURCE 00051 当Oracle请求资源时,发生超时现象
    TOO_MANY_ROWS 01422 SELECT INTO返回的行数太多
    VALUE_ERROR 06502 发生算术、转换、截位或长度约束错误。例如,当我们的程序把一个字段的值放到一个字符变量中时,如果值的长度大于变量的长度,PL/SQL就会终止赋值操作并抛出异常VALUE_ERROR。在过程化语句中,如果字符串向数字转换失败,异常VALUE_ERROR就会被抛出(在SQL语句中,异常INVALID_NUMBER会被抛出)
    ZERO_DIVIDE 01476 程序尝试除以0

    用户自定义异常

    和其它语言一样,我们也可以定义我们满足我们自己要求的异常,自定义一样的语法格式如下:

    PRAGMA EXCEPTION_INIT(exception_name, -Oracle_error_number);
    
    • exception_name:异常的名字
    • Oracle_error_number:错误编号,以符号’-’开始,范围从-20000~-20999

    触发异常

    定义了那么多异常,那么在程序中如何抛出异常呢?在Oracle中有以下三种方式触发异常:

    • 由Oracle自动触发异常
    • 使用RAISE语句手工触发
    • 调用存储过程RAISE_APPLICATION_ERROR手工触发

    下面的代码将演示Oracle自动触发异常:

    -- Created on 2015-7-14 by JellyThink 
    declare 
        iA NUMBER(2) := 10;
    begin
        iA := iA / 0; -- Oracle自动触发异常
        dbms_output.put_line(iA);
    exception
        when ZERO_DIVIDE then
            dbms_output.put_line('Error Code:' || SQLCODE || ' ' || SQLERRM);
        when others then
            dbms_output.put_line('Others Exception');
    end;
    

    下面的代码将演示使用RAISE语句手工触发异常:

    -- Created on 2015-7-14 by JellyThink 
    declare 
        myException EXCEPTION;
    begin
        RAISE myException; -- RAISE手工触发异常
    exception
        when others then
            dbms_output.put_line('Others Exception');
    end;
    

    下面的代码将演示使用RAISE_APPLICATION_ERROR触发异常:

    -- Created on 2015-7-14 by JellyThink 
    declare 
        myException EXCEPTION;
        PRAGMA EXCEPTION(myException, -20009);
    begin
        RAISE_APPLICATION_ERROR(-20009, 'Exception'); -- 这里可以指定异常信息
    exception
        when myException then
            dbms_output.put_line('myException Exception');
    end;
    

    异常传递

    先来看看下面这段代码:

    -- Created on 2015-7-15 by JellyThink 
    declare 
        i Number;
    begin
        i := 10;
        declare
        begin
            i := i / 0; -- 嵌套块中抛出异常
        /*exception
            when ZERO_DIVIDE then
                dbms_output.put_line('Error');*/ -- 嵌套块不处理这个异常
        end;
    exception
        -- 在这里处理子块抛出的异常
        when ZERO_DIVIDE then
            dbms_output.put_line('Error Code:' || SQLCODE || ' ' || SQLERRM);
        when others then
            dbms_output.put_line('Error Code:' || SQLCODE || '  ' || SQLERRM);
    end;
    

    在一个块中,只能有一个异常处理部分,在不同的块中,可以定义多个异常处理部分。父块中可以定义异常处理,子块中也可以定义自己的异常处理。当一个子块的异常发生时,如果在子块的异常处理部分没有进行处理,该异常会传递到父块中,如果父块中没有对应的异常处理部分,那么这个异常会继续向上传递。

    总结

    异常的处理在一个程序中是必不可少的,也是你的代码走向完美的一个必要的部分。只有熟悉的掌握了异常处理,才能更好的服务于你的代码。想想我们现在系统中的存储过程,都没有异常处理,哦,谁写的,我保证不打死你。

    2015年7与15日 于呼和浩特。



沪ICP备19023445号-2号
友情链接