您的位置:首页 > 数据库 > Oracle

Oracle Error Handling(Oracle 异常处理)

2015-08-10 17:29 246 查看
今天被企业导师要求在之前编写的存储过程中加入异常处理的语句, 以增强代码的健壮性. 研究了下 Oracle11g 官方文档, 再做一个简单的实践就解决了. 还是写个博客理理思路, 毕竟好记性不如烂笔头. 由于篇幅和时间关系, 这里只结合部分实例对Oracle的异常处理做一个大概的介绍, 想要完全完整学习Oracle异常处理请自行参阅 Oracle11g官方文档. 如果只是想快速上手异常处理, 不想看概念, 请直接查看本文实例.

一.Oracle支持三种类型的异常: 内部定义异常, 预定义异常 和 用户自定义异常

1.Internally
Defined Exceptions: 内部定义异常

内部定义异常 是 Oracle 数据库异常信息集 中已经定义好了的异常信息, 由系统自行抛出( 隐式抛出 ). 这种类型的异常只拥有异常代码(error code 如ORA-27102 ),
没有异常名称, 除非我们给它一个名称 或 PL/SQL给它一个名称. 因此也被称为非预定义内部定义异常(这么叫的原因请看预定义异常概念).

2.Predefined
Exceptions: 预定义异常


预定义异常其实就是拥有自己的异常名(error name)的内部定义异常, 所以其实是预定义内部定义异常. 比如 ORA-06500就拥有自己的名字 STORAGE_ERROR

3.User-Defined
Exceptions: 自定义异常


自定义异常自然就是根据我们需要而定义的异常, 需要我们自己在代码中抛出(使用 raise 关键字, 显示抛出). 比如 我们规定 a < b是不合法的, 那么我们就可以使用一个if 语句来判断, 当 a < b的时候,就抛出我们自定义的异常, 并做处理.

二.错误信息的获取

在Oralce中, 我们可以使用SQLCODE SQLERRM来获取错误代码
和 错误信息, 但是需要注意: 这两者都是过程化函数, 不能在SQL中直接使用,
只能将它们的返回值先赋给局部变量(如 mypara := sqlcode ), 再使用这些局部变量.

三.处理异常可以分为根据异常名来做针对性的处理 和只使用others 对异常做一个笼统的处理两种情况.

1) 使用异常名称做针对性处理 (可用于处理拥有异常名称的异常: 自定义异常, 预定义异常, 被给予了名称的内部定义异常)

注: 对于没有异常名的内部定义异常, 如果我们大概知道可能会抛出的异常, 并且知道异常的代码, 我们可以给予异常名称, 使用异常名称来做针对性的异常处理.

实例1:
定义名称为 my_exception 的自定义异常, 使用raise关键字抛出, 捕获后针对异常名做一个处理.

-- author: csdn libertine1993
create or replace procedure pro_selfdefinde_exp
as
my_exception exception;                          --定义自定义异常名称
para1 number := 1;
para2 number := 2;
begin
if para1 < para2 then                            --这里我们规定para1 < para2是不合法的, 使用raise抛出异常 my_exception
raise my_exception;
end if;
exception
when my_exception then
insert into my_error_info(f_id, f_error_msg)
values(sys_guid(), '使用my_exception异常名, 捕获到了异常!');
end pro_selfdefinde_exp;


我们知道异常的名字是my_exception, 可以在捕获的时候做一些针对性的处理, 这里的针对性处理就是插入一条有针对性的描述的记录.于是我们可以看到下面这条记录



实例2:使用预定义异常的名字处理异常, 由于预定义异常属于内部定义异常, 因此异常的抛出是系统隐式的自动抛出, 不需要使用raise关键字

Oracle中预定义下面一个预定义异常: (左往右分别是 异常名和异常代码)



-- author: csdn libertine1993
create or replace procedure pro_preddefine_exp
as
para1 number := 1;
para2 number := 0;
para3 number;

error_code number;
error_msg varchar(64);
begin
para3 := para1 / para2; --系统将会隐式的抛出 除数为0的异常
exception
when zero_divide then
insert into my_error_info(f_id, f_error_msg)
values(sys_guid(), '这是使用预定义的异常名 zero_divide 捕获到的异常');
END PRO_PREDDEFINE_EXP;


结果:



2) 不给于异常名称, 只以others 关键字来对所有异常做一个笼统的处理.

实例: 尝试插入一条没有主键的记录, 捕获异常后, 只使用others做一个笼统的处理, 这里的处理是将异常信息插入我们自己建的my_error_info表.

-- author: libertine1933 from csdn
-- 尝试将一条缺少主键的记录插入 mytest表, 获取抛出的异常并将异常信息插入 my_error_info表

create or replace procedure pro_testexception
AS
errorcode number;            --异常代码
errormesg varchar2(64);      --异常信息
begin
--为了便于观察, 每次都会清空错误信息表内之前的记录
delete from my_error_info;

insert into mytest(f_price) values('123'); --mytest表
exception
when others then             --使用others而不是异常名, 因此我们只能对异常做一个笼统的操作
errorcode := sqlcode;    --使用sqlcode 和 sqlerrm 必须先赋值给两个局部变量
errormesg := substr(sqlerrm, 1, 64);
insert into my_error_info(
f_id,               --自己建的错误信息表中每条记录的ID, 由sys_guid()生成
f_create_date,      --记录创建日期, 由sysdate生成
f_error_code,       --错误代码
f_error_msg         --错误信息
)
values(
sys_guid(),
sysdate,
errorcode,
errormesg
);
END PRO_TESTEXCEPTION;


由于 mytest表 的主键 F_CMID 不能为空, 所以插入失败, 系统自行抛出一个异常(这种常见的异常属于内部定义异常, 由系统自动抛出), 由于使用的是others, 我们并不能得知异常的具体归属, 所以只能做一个笼统的处理, 这里的笼统处理就是将异常信息记录在表中, 这样我们就能够看到下面这条记录 :



最后, 本文只是对Oracle异常处理做了一个大概的介绍, 关于Oracle中异常的传播, 重定义预定义异常等知识点, 有兴趣继续了解的请参阅Oracle 11g官方文档, 在此不做阐述.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: