Oracle异常错误处理

短命女 2021-06-26 16:06 583阅读 0赞

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

1.异常处理的概念。

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

2.异常处理的类型。

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

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

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

3.异常处理的语句。

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

  1. EXCEPTION
  2. WHEN first_exception THEN <code to handle first exception >
  3. WHEN second_exception THEN <code to handle second exception >
  4. WHEN OTHERS THEN <code to handle others exception >
  5. 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 索引得引用大于集合中元素的个数.

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

假如实例表如下:

  1. -- Create table
  2. create table G_TEST_SAL
  3. (
  4. sid NUMBER,
  5. sname CHAR(5),
  6. salary BINARY_FLOAT,
  7. time TIMESTAMP(6)
  8. )
  9. tablespace TBS_RPT
  10. pctfree 10
  11. initrans 1
  12. maxtrans 255
  13. storage
  14. (
  15. initial 64K
  16. minextents 1
  17. maxextents unlimited
  18. );
  19. -- 插入数据
  20. 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'));
  21. 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'));
  22. commit;

1. 预定义的异常处理。

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

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

执行上面的语句,并输入异常empno 如下图:
在这里插入图片描述
在这里插入图片描述

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

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

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

    <异常情况> EXCEPTION;

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

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

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

    —非预定义异常处理
    —例2:删除指定员工的记录信息

    DECLARE

    1. v_empno G_Test_SAL.Sid%TYPE := &empno;
    2. 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

    1. DBMS_OUTPUT.PUT_LINE('违反数据完整性约束!');

    WHEN OTHERS THEN

    1. DBMS_OUTPUT.PUT_LINE(SQLCODE||'---'||SQLERRM);

    END;

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

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

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

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

  1. <异常情况> EXCEPTION;

2. RAISE <异常情况>;

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

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

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

SQLCODE 返回遇到的Oracle错误号。

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

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

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

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

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

  1. --------------------------------第二种---------------------------------------------
  2. CREATE OR REPLACE PROCEDURE PETL.P_ETL_LOG_WRT
  3. (v_txdate IN VARCHAR2,
  4. v_serialno IN NUMBER,
  5. v_stepnum IN NUMBER,
  6. v_dealtype IN VARCHAR2,
  7. v_dealtab IN VARCHAR2,
  8. v_errcode IN NUMBER,
  9. v_errstate IN VARCHAR2,
  10. v_rcount IN NUMBER,
  11. v_dealprc IN VARCHAR2) AS
  12. ----------------------------------------------------------------------------------------
  13. -- 称:日志记录存储过程
  14. -- 功能说明:记录日志
  15. -- 源表信息:
  16. -- 表:PETL.ETL_JOB_LOG
  17. -- 创建信息:
  18. -- 修改项1
  19. -- 修改项2
  20. ----------------------------------------------------------------------------------------
  21. BEGIN
  22. 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);
  23. COMMIT;
  24. END;

发表评论

表情:
评论列表 (有 0 条评论,583人围观)

还没有评论,来说两句吧...

相关阅读