Oracle错误处理机制
异常的类型
1、Oracle中对运行时错误的处理采用了异常处理机制。
2、一个错误对应一个异常,当错误产生时抛出相应的异常,并被异常处理器捕获,程序控制权传递给异常处理器,由异常处理器来处理运行时错误。
| 异常情况名 | 错误代码 | 描述 |
| CURSOR_ALREADY_OPEN | ORA-06511 | 尝试打开已经打开的游标 |
| INVALID_CURSOR | ORA-01001 | 不合法的游标操作(如要打开已经关闭的游标) |
| NO_DATA_FOUND | ORA-01403 | 没有发现数据 |
| TOO_MANY_ROWS | ORA-01422 | 一个SELECT INTO语句匹配多个数据行 |
| INVALID_NUMBER | ORA-01722 | 转换成数字失败 (‘X’) |
| VALUE_ERROR | ORA-06502 | 截断、算法或转换错误,通常出现在赋值错误 |
| ZERO_DIVIDE | ORA-01476 | 除数为0 |
| ROWTYPE_MISMATCH | ORA-06504 | 主机游标变量与PL/SQL游标变量类型不匹配 |
| 异常情况名 | 错误代码 | 描述 |
| DUP_VAL_ON_INDEX | ORA-00001 | 违反唯一性约束或主键约束 |
| SYS_INVALID_ROWID | ORA-01410 | 转换成ROWID失败 |
| TIMEOUT_ON_RESOURCE | ORA-00051 | 在等待资源中出现超时 |
| LOGIN_DENIED | ORA-01017 | 无效用户名/密码 |
| CASE_NOT_FOUND | ORA-06592 | 没有匹配的WHEN子句 |
| NOT_LOGGED_ON | ORA-01012 | 没有与数据库建立连接 |
| STORAGE_ERROR | ORA-06500 | PL/SQL内部错误 |
| PROGRAM_ERROR | ORA-06501 | PL/SQL内部错误 |
| 异常情况名 | 错误代码 | 描述 |
| ACCESS_INTO_NULL | ORA-06530 | 给空对象属性赋值 |
| COLLECTION_IS_NULL | ORA-06531 | 对某NULL PL/SQL表或可变数组试图应用集合方法,而不是EXISTS |
| SELF_IS_NULL | ORA-30625 | 调用空对象实例的方法 |
| SUBSCRIPT_BEYOND_COUNT | ORA-06533 | 对嵌套表或数组索引引用时超出集合中元素的数量 |
| SUBSCRIPT_OUTSIDE_LIMIT | ORA-06532 | 对嵌套表或可变数组索引的引用超出声明的范围 |
•声明一个异常名称 e_integrity EXCEPTION; •将异常与一个Oracle错误号相绑定 PRAGMA EXCEPTION-INIT(e_integrity.-2291) •示例 DECLARE e_deptno_fk EXCEPTION; PRAGMA EXCEPTION_INIT(e_deptno_fk,-2292); BEGIN …… EXCEPTION …… END;
-20999~-20000为用户定义错误的保留号。
注意: 一个异常处理器可以捕获多个异常,只需在WHEN子句中用查询名为SMITH的员工工资,如果该员工不存在,则输出“There is not such an employee!”;如果存在多个同名的员工,则输出其员工号和工资。OR连接即可;
一个异常只能被一个异常处理器捕获,并进行处理。
DECLAREv_sal emp.sal%type;
BEGINSELECT sal INTO v_sal FROM emp WHERE ename='SMITH';DBMS_OUTPUT.PUT_LINE(v_sal);
EXCEPTIONWHEN NO_DATA_FOUND THEN DBMS_OUTPUT.PUT_LINE('There is not such an emplyee!');WHEN TOO_MANY_ROWS THENFOR v_emp IN (SELECT * FROM emp WHERE ename='SMITH') LOOPDBMS_OUTPUT.PUT_LINE(v_emp.empno||' '||v_emp.sal);END LOOP;
END;
删除dept表中部门号为10的部门信息,如果不能删除则输出“There are subrecords in emp table!”。
DECLAREe_deptno_fk EXCEPTION;PRAGMA EXCEPTION_INIT(e_deptno_fk,-2292);
BEGINDELETE FROM dept WHERE deptno=10;
EXCEPTIONWHEN e_deptno_fk THENDBMS_OUTPUT.PUT_LINE(' There are subrecords in emp table!');
END;
修改7844员工的工资,保证修改后工资不超过6000。
DECLAREe_highlimit EXCEPTION;v_sal emp.sal%TYPE;
BEGINUPDATE emp SET sal=sal+100 WHERE empno=7844 RETURNING sal INTO v_sal;IF v_sal>6000 THEN RAISE e_highlimit;END IF;
EXCEPTIONWHEN e_highlimit THENDBMS_OUTPUT.PUT_LINE('The salary is too large!');ROLLBACK;
END;
DECLAREv_sal emp.sal%TYPE;e_highlimit EXCEPTION;
BEGINSELECT sal INTO v_sal FROM emp WHERE ename='JOAN';UPDATE emp SET sal=sal+100 WHERE empno=7900;IF v_sal>6000 THEN RAISE e_highlimit;END IF;
EXCEPTIONWHEN e_highlimit THENDBMS_OUTPUT.PUT_LINE('The salary is too large!');ROLLBACK;WHEN OTHERS THENDBMS_OUTPUT.PUT_LINE('There is some wrong in selecting!');
END;
可以通过两个函数来获取错误相关信息。
SQLCODE:返回当前错误代码。 •如果是用户定义错误返回值为1; •如果是ORA-1403:NO DATA FOUND错误,返回值为100 •其他Oracle内部错误返回相应的错误号。 SQLERRM:返回当前错误的消息文本。 •如果是Oracle内部错误,返回系统内部的错误描述; •如果是用户定义错误,则返回信息文本为“User-defined Exception”。
DECLAREv_sal emp.sal%TYPE;e_highlimit EXCEPTION;v_code NUMBER(6);v_text VARCHAR2(200);
BEGINSELECT sal INTO v_sal FROM emp WHERE ename='JOAN';UPDATE emp SET sal=sal+100 WHERE empno=7900;IF v_sal>6000 THEN RAISE e_highlimit;END IF;
EXCEPTIONWHEN e_highlimit THENDBMS_OUTPUT.PUT_LINE('The salary is too large!');ROLLBACK;WHEN OTHERS THENv_code:=SQLCODE;v_text:=SQLERRM; DBMS_OUTPUT.PUT_LINE(v_code||' '||v_text);
END;
DECLAREv_sal emp.sal%TYPE;
BEGINBEGIN SELECT sal INTO v_sal FROM emp WHERE ename='JOAN';EXCEPTIONWHEN NO_DATA_FOUND THEN DBMS_OUTPUT.PUT_LINE('There is not such an employee!');END;DBMS_OUTPUT.PUT_LINE('Now this is outputted by outer block!');
END;
/
There is not such an employee!
Now this is outputted by outer block!
DECLAREv_sal emp.sal%TYPE;
BEGINBEGIN SELECT sal INTO v_sal FROM emp WHERE deptno=10;EXCEPTIONWHEN NO_DATA_FOUND THEN DBMS_OUTPUT.PUT_LINE('There is not such an employee!');END;DBMS_OUTPUT.PUT_LINE('Now this is outputted by outer block!');
EXCEPTIONWHEN TOO_MANY_ROWS THENDBMS_OUTPUT.PUT_LINE('There are more than one employee!');
END;
/
There are more than one employee!
声明部分和异常处理部分的异常会立刻传播到外层语句块的异常处理部分,即使当前语句块有该异常的异常处理器。
BEGINDECLARE
v_number NUMBER(6) :='ABC';
BEGINv_number:=10;EXCEPTIONWHEN OTHERS THENDBMS_OUTPUT.PUT_LINE('This is outputted by inner block!');END;
EXCEPTION
WHEN OTHERS THENDBMS_OUTPUT.PUT_LINE('This is outputted by outer block!');
END;
/
This is outputted by outer block!
本人从事软件项目开发20多年,2005年开始从事Java工程师系列课程的教学工作,录制50多门精品视频课程,包含java基础,jspweb开发,SSH,SSM,SpringBoot,SpringCloud,人工智能,在线支付等众多商业项目,每门课程都包含有项目实战,上课PPT,及完整的源代码下载,有兴趣的朋友可以看看我的在线课堂
讲师课堂链接:https://edu.csdn.net/lecturer/893