Java自学者论坛

 找回密码
 立即注册

手机号码,快捷登录

恭喜Java自学者论坛(https://www.javazxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,会员资料板块,购买链接:点击进入购买VIP会员

JAVA高级面试进阶训练营视频教程

Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程Go语言视频零基础入门到精通Java架构师3期(课件+源码)
Java开发全终端实战租房项目视频教程SpringBoot2.X入门到高级使用教程大数据培训第六期全套视频教程深度学习(CNN RNN GAN)算法原理Java亿级流量电商系统视频教程
互联网架构师视频教程年薪50万Spark2.0从入门到精通年薪50万!人工智能学习路线教程年薪50万大数据入门到精通学习路线年薪50万机器学习入门到精通教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程MySQL入门到精通教程
查看: 439|回复: 0

Oracle异常错误处理

[复制链接]
  • TA的每日心情
    奋斗
    2024-11-24 15:47
  • 签到天数: 804 天

    [LV.10]以坛为家III

    2053

    主题

    2111

    帖子

    72万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    726782
    发表于 2021-7-4 16:20:40 | 显示全部楼层 |阅读模式

    一、ORACLE 提供异常情况(EXCEPTION)和异常处理(EXCEPTION HANDLER)来实现错误处理。

    1.异常处理的概念。

    异常情况处理(EXCEPTION)是用来处理正常执行过程中未预料的事件,程序块的异常处理预定义的错误和自定义错误,由于PL/SQL程序块一旦产生异常而没有指出如何处理时,程序就会自动终止整个程序运行.

    2.异常处理的类型。

      预定义 ( Predefined )错误:ORACLE预定义的异常情况大约有24个。对这种异常情况的处理,无需在程序中定义,由ORACLE自动将其引发。

      非预定义 ( Predefined )错误:即其他标准的ORACLE错误。对这种异常情况的处理,需要用户在程序中定义,然后由ORACLE自动将其引发。

      用户定义(User_define) 错误:程序执行过程中,出现编程人员认为的非正常情况。对这种异常情况的处理,需要用户在程序中定义,然后显式地在程序中将其引发。

    3.异常处理的语句。

    异常处理部分一般放在 PL/SQL 程序体的后半部,结构为:

    EXCEPTION
       WHEN first_exception THEN  <code to handle first exception >
       WHEN second_exception THEN  <code to handle second exception >
       WHEN OTHERS THEN  <code to handle others exception >
    END;

    4.24个预定义的异常处理。

     

    错误号

    异常错误信息名称

    说明

    ORA-0001

    Dup_val_on_index

    违反了唯一性限制

    ORA-0051

    Timeout-on-resource

    在等待资源时发生超时

    ORA-0061

    Transaction-backed-out

    由于发生死锁事务被撤消

    ORA-1001

    Invalid-CURSOR

    试图使用一个无效的游标

    ORA-1012

    Not-logged-on

    没有连接到ORACLE

    ORA-1017

    Login-denied

    无效的用户名/口令

    ORA-1403

    No_data_found

    SELECT INTO没有找到数据

    ORA-1422

    Too_many_rows

    SELECT INTO 返回多行

    ORA-1476

    Zero-divide

    试图被零除

    ORA-1722

    Invalid-NUMBER

    转换一个数字失败

    ORA-6500

    Storage-error

    内存不够引发的内部错误

    ORA-6501

    Program-error

    内部错误

    ORA-6502

    Value-error

    转换或截断错误

    ORA-6504

    Rowtype-mismatch

    宿主游标变量与 PL/SQL变量有不兼容行类型

    ORA-6511

    CURSOR-already-OPEN

    试图打开一个已处于打开状态的游标

    ORA-6530

    Access-INTO-null

    试图为null 对象的属性赋值

    ORA-6531

    Collection-is-null

    试图将Exists 以外的集合( collection)方法应用于一个null pl/sql 表上或varray上

    ORA-6532

    Subscript-outside-limit

    对嵌套或varray索引得引用超出声明范围以外

    ORA-6533

    Subscript-beyond-count

    对嵌套或varray 索引得引用大于集合中元素的个数.

        

     
       

    二、三种异常的处理的基本介绍和语法。

    假如实例表如下:

    -- Create table
    create table G_TEST_SAL
    (
      sid    NUMBER,
      sname  CHAR(5),
      salary BINARY_FLOAT,
      time   TIMESTAMP(6)
    )
    tablespace TBS_RPT
      pctfree 10
      initrans 1
      maxtrans 255
      storage
      (
        initial 64K
        minextents 1
        maxextents unlimited
      );
    
    
    -- 插入数据
    insert into G_Test_SAL values(1,'gal1',3000,to_timestamp('2000-1-1 0:0:0.0', 'syyyy-mm-dd hh24:mi:ss.ff'));
    insert into G_Test_SAL values(2,'gal2',3050,to_timestamp('2000-1-1 0:0:0.0', 'syyyy-mm-dd hh24:mi:ss.ff'));
    commit;

     

    1.预定义的异常处理。

    预定义的异常情况的处理,只需在PL/SQL块的异常处理部分,直接引用相应的异常情况名,并对其完成相应的异常错误处理即可。

    ----异常处理
    ---例1:更新指定员工工资,如工资小于1500,则加100;
    DECLARE
       v_empno G_Test_SAL.Sid%TYPE := &empno;  ----%TYpe  此句的含义是定义一个变量v_empno,变量类型为G_Test_SAL.Sid的字段类型,而且一旦G_Test_SAL.Sid类型变化,v_empno的类型也变化
                                               ----:=  是赋值的含义
                                               ----&的含义是empno变量由外部手动录入
       v_sal   G_Test_SAL.Salary%TYPE;
    BEGIN
       SELECT Salary INTO v_sal FROM G_Test_SAL WHERE Sid = v_empno;  -- select into
       IF v_sal<=1500 THEN 
            UPDATE G_Test_SAL SET Salary = Salary + 100 WHERE Sid=v_empno; 
            DBMS_OUTPUT.PUT_LINE('编码为'||v_empno||'员工工资已更新!');     --||字符串连接符
       ELSE
            DBMS_OUTPUT.PUT_LINE('编码为'||v_empno||'员工工资已经超过规定值!');
       END IF;
       
    EXCEPTION
       WHEN NO_DATA_FOUND THEN  
          DBMS_OUTPUT.PUT_LINE('数据库中没有编码为'||v_empno||'的员工');
       WHEN TOO_MANY_ROWS THEN
          DBMS_OUTPUT.PUT_LINE('程序运行错误!请使用游标');
       WHEN OTHERS THEN
          DBMS_OUTPUT.PUT_LINE(SQLCODE||'---'||SQLERRM);
    END; 

     

    执行上面的语句,并输入异常empno 如下图:

     

      

    2. 非预定义的异常处理。

    对于这类异常情况的处理,首先必须对非定义的ORACLE错误进行定义。步骤如下:

    1. 在PL/SQL 块的定义部分定义异常情况:

    <异常情况>  EXCEPTION;

     

    2. 将其定义好的异常情况,与标准的ORACLE错误联系起来,使用EXCEPTION_INIT语句:

    PRAGMA EXCEPTION_INIT(<异常情况>, <错误代码>);

     

    3. 在PL/SQL 块的异常情况处理部分对异常情况做出相应的处理。

    --非预定义异常处理
    --例2:删除指定员工的记录信息
    
    DECLARE
        v_empno G_Test_SAL.Sid%TYPE := &empno;
        empno_remaining EXCEPTION;
       PRAGMA EXCEPTION_INIT(empno_remaining, -2292);
       /* -2292 是违反一致性约束的错误代码 */
    BEGIN
       DELETE FROM G_Test_SAL WHERE Sid = v_empno;
    EXCEPTION
       WHEN empno_remaining THEN 
          DBMS_OUTPUT.PUT_LINE('违反数据完整性约束!');
       WHEN OTHERS THEN
    DBMS_OUTPUT.PUT_LINE(SQLCODE||'---'||SQLERRM); END;

     3.用户自定义的异常处理

    当与一个异常错误相关的错误出现时,就会隐含触发该异常错误。用户定义的异常错误是通过显式使用 RAISE 语句来触发。当引发一个异常错误时,控制就转向到 EXCEPTION块异常错误部分,执行错误处理代码。

    对于这类异常情况的处理,步骤如下:

    1. 在PL/SQL 块的定义部分定义异常情况:

    <异常情况>  EXCEPTION;

    2. RAISE <异常情况>;

    3. 在PL/SQL 块的异常情况处理部分对异常情况做出相应的处理。

     

    ---------------------------自定义的异常处理--------------------------------
    --例3:更新指定员工工资,增加100;
    
    
    DECLARE
       v_empno employees.employee_id%TYPE :=&empno;
       no_result  EXCEPTION;
    BEGIN
       UPDATE employees SET salary = salary+100 WHERE employee_id = v_empno;
       IF SQL%NOTFOUND THEN        -----------SQL%NOTFOUND 是一个布尔值。与最近的sql语句(update,insert,delete,select)发生交互,当最近的一条sql语句没有涉及任何行的时候,则返回true。否则返回false。
          RAISE no_result;
       END IF;
    EXCEPTION
       WHEN no_result THEN 
          DBMS_OUTPUT.PUT_LINE('你的数据更新语句失败了!');
       WHEN OTHERS THEN
          DBMS_OUTPUT.PUT_LINE(SQLCODE||'---'||SQLERRM);
    END;

     

    三、在 PL/SQL 中使用 SQLCODE, SQLERRM异常处理函数。

    SQLCODE  返回遇到的Oracle错误号。

    SQLERRM  返回遇到的Oracle错误信息.

    目前项目中遇到的各种处理信息,我们都放在了一张日志表中。

    1.第一种直接写入日志表。

    -------------------第一种-----------------------------
    ----日志表:
    R_SQLRunLog(err_time char(19),err_code number,err_msg varchar2(200),info varchar2(200))
    ----异常处理:
    WHEN OTHERS THEN
      v_ErrCode   = SQLCODE
      v_ErrTxt  = SUBSTR(SQLERRM,1,200);
      INSERT INTO R_SqlRunLog(err_time,err_code,err_msg,info)
        values(to_char(sysdate,'yyyy-mm-dd HH24:MI:SS'),v_ErrCode,v_ErrTxt,'用户加入存储过程或函数名称');

     

    2.第二种调用存储过程,当我们每次执行一个操作的时候,都会调用此过程来将错误信息添加到一个日志表中。

    --------------------------------第二种---------------------------------------------
    CREATE
    OR REPLACE PROCEDURE PETL.P_ETL_LOG_WRT (v_txdate IN VARCHAR2, v_serialno IN NUMBER, v_stepnum IN NUMBER, v_dealtype IN VARCHAR2, v_dealtab IN VARCHAR2, v_errcode IN NUMBER, v_errstate IN VARCHAR2, v_rcount IN NUMBER, v_dealprc IN VARCHAR2) AS ---------------------------------------------------------------------------------------- -- 名 称:日志记录存储过程 -- 功能说明:记录日志 -- 源表信息: -- 目 标 表:PETL.ETL_JOB_LOG -- 创建信息: -- 修改项1 : -- 修改项2 : ---------------------------------------------------------------------------------------- BEGIN INSERT INTO PETL.ETL_JOB_LOG VALUES(v_txdate,v_serialno,v_stepnum,v_dealtype,v_dealtab,TO_CHAR(SYSDATE,'YYYY-MM-DD HH24:MI:SS'),v_errcode,v_errstate,v_rcount,0,v_dealprc); COMMIT; END;

     

    若您发现我侵犯了您的版权,请及时与我联系。

    哎...今天够累的,签到来了1...
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|小黑屋|Java自学者论坛 ( 声明:本站文章及资料整理自互联网,用于Java自学者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2025-2-24 07:09 , Processed in 0.065894 second(s), 29 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表