异常处理
概述
/*
在PL/SQL中出现的异常,如果我们没有处理,异常会被传递给调用环境,中断我们的程序。
*/
declare
v_job emp.job%type;
begin
select job into v_job from emp where empno=8001;
dbms_output.put_line(v_job);-- 异常 没有找到数据
dbms_output.put_line('程序结束');
end;
/*
PL/SQL程序会从发生异常的代码处中断,以后的代码是无法执行的;
而Oracle异常分为俩种类型:系统异常、自定义异常。
而系统异常又分为预定义异常和非预定义异常。
*/
预定义异常
--Oracle以及为这种异常定义好了名称,我们在异常处理部分直接通过异常名称进行了捕获
ORACLE定义了它们的错误编号和异常名字,常见的预定义异常处理如下:
ACCESS_INTO_NULL:对应ORA-06530为了引用对象属性,必须首先初始化对象。直接引用未初始化的对象属性时,会发生异常
CASE_NOT_FOUND:对应ORA-06592,当CASE语句的WHEN子句没有包含必须条件分支或者ELSE子句时,会触发
COLLECTION_IS_NULL:对应ORA-06531,在给嵌套表变量或者varrary变量赋值之前,必须首先初始化集合
CURSOR_ALREADY_OPEN:ORA-06511,当已打开游标上执行OPEN操作时会触发
INVALID_CURSOR:ORA-01001,当视图从未打开游标,提取数据,或者关闭未打开游标时会触发
INVALID_NUMBER:ORA-01722,当内嵌SQL语句不能将字符转变成数字时会触发
LOGIN_DENIED:ORA-01017,连接Oracle数据库时,如果提供了不正解的用户名和口令时会触发
NO_DATA_FOUND:ORA-01403执行SELECT INTO 未返回行或者引用了未初始化的PL/SQL表元素时会触发
NOT_LOGGED_ON:ORA-01012没有连接数据库执行SQL时会触发
PROGRAM_ERROR:ORA-06501存在PL/SQL内部问题,在这种情况下需要重新安装数据字典视图和PL/SQL包
ROWTYPE_MISMATCH:ORA-016504当执行赋值操作时,如果宿主变量和游标变量不兼容的返回类型时,会触发
SELF_IS_NULL: ORA-30625,当使用对象类型时,如果在null实例上调用成员方法时,会触发
STORAGE_ERROR:ORA-06500当执行PL/SQL块时,如果超出内存空间或者内存被破坏,会触发
SUBSCRIPT_BEYOND_COUNT:ORA-06533当使用嵌套或者varray元素的范围进会触发
SUBSCRIPT_OUTSIDE_LIMIT:ORA-06532,使用嵌套表或者varray元素时,如果元素下标为负值时,会触发
SYS-INVALID_ROWID:ORA-01410当字符串转变为ROWID时如果使用了无效字符串,会触发
TIMEOUT_ON_RESOURCE:ORA-00051当等待资源时如果出现超时会触发
TOO_MANY_ROWS:ORA-01422当执行SELECT INTO时,如果返回超过一行、会触发
VALUE_ERROR:ORA-06502,执行赋值时,如果变量长度不足,会触发
ZERO_DIVIDE:ORA-01476如果用数字值除0,会触发
/*
当plsql程序中,在begin部分的语句出现了异常,就会进入到exception部分执行异常处理功能
只要我们采取了处理措施后,就不会产生报错信息
*/
declare
v_job emp.job%type;
cursor mycur is select * from emp;
v_num number(8);
begin
select job into v_job from emp where empno=8001;
dbms_output.put_line(v_job);-- 异常 没有找到数据
dbms_output.put_line(mycur%rowcount);
v_num := 10/0;
insert into dept values(10,'气氛组','青岛');
exception
when NO_DATA_FOUND then
dbms_output.put_line('执行的select语句没有查询到结果');
when TOO_MANY_ROWS then
dbms_output.put_line('执行的select语句不能查询多条结果');
when INVALID_CURSOR then
dbms_output.put_line('无效的游标');
when ZERO_DIVIDE then
dbms_output.put_line('0不能作为除数');
when DUP_VAL_ON_INDEX then --唯一索引中插入重复值
dbms_output.put_line('违反了主键约束');
when VALUE_ERROR then
dbms_output.put_line('赋值错误');
when others then -- 最牛逼的异常处理 不会有一条异常信息;
dbms_output.put_line('PL/SQL中发生了异常');
end;
注意:
SQLCODE与SQLERRM为异常处理函数。
函数SQLCODE用于取得Oracle错误号,
函数SQLERRM用于取得与错误号对应的相关错误消息
用法:
exception
when NO_DATA_FOUND then
dbms_output.put_line('执行的select语句没有查询到结果'||','||sqlcode||','||sqlerrm);
非预定义异常
非预定异常,也是因为违反了Oracle的规则,Oracle会产生报错信息(有错误编号和错误信息),
但是Oracle并没有为这类错误定义好异常名称(但有错误编号),那么我们可以自已定义一种异常名称,并将这样异常名称和错误编号进行绑定;
帕克码
我们使用的时候,先声名一个异常名,通过伪过程 PRAGMA EXCEPTION_INIT,将异常名与错误号关联起来。
declare
v exception; -- 自己定义的一种异常名称
-- 通过 PRAGMA EXCEPTION_INIT(异常名称,错误编码)
pragma exception_init(v,-04098);
begin
delete from dept where deptno = 10;
exception
when v then
dbms_output.put_line('违反了外键约束');
end;
-- 在不知道错误编码的时候怎么用
begin
delete from dept where deptno = 10;
exception
when others then
dbms_output.put_line('违反了外键约束'||sqlcode);
end;
自定义异常
程序员从业务角度出发,制定的一些规则和限制。
抛出异常:
润丝
raise 异常名称;
declare
myex exception;
begin
raise myex;
-- null;
end;
-- 完成2个数相除,要求除数不能为5
declare
v_1 number:=&请输入第一个数:
v_2 number:=&请输入第二个数;
begin
if v_2 = 5 then
dbms_output.put_line('除数不能为5');
end if;
dbms_output.put_line(v_1/v_2);
end;
这么写的话,我的程序依然会往下执行。
declare
v_1 number:=&请输入第一个数;
v_2 number:=&请输入第二个数;
myex exception;
begin
if v_2 = 5 then
dbms_output.put_line('除数不能为5');
raise myex; -- 抛个异常 让程序停止
end if;
dbms_output.put_line(v_1/v_2);
end;
declare
v_1 number:=&请输入第一个数;
v_2 number:=&请输入第二个数;
myex exception;
begin
if v_2 = 5 then
dbms_output.put_line('除数不能为5');
raise myex;
end if;
dbms_output.put_line(v_1/v_2);
exception
when myex then -- 自己定义的异常可以自己处理
dbms_output.put_line('除数不能为5');
end;
引发应用程序错误
可能不是很多人知道 RAISE_APPLICATION(哎破tei谁)_ERROR(哎我) 的用途是什么,虽然从字面上已经猜到这个函数是干什么用的。平时用来测试的异常处理
我们都是通过dbms_output.put_line来输出异常信息,但是在实际的应用中,需要把异常信息返回给调用的客户端。
declare
rate_exception exception;
b number(20);
begin
b := &b;
if b not in (2, 1, 3) then
raise rate_exception;
else
dbms_output.put_line('该水果名称为香蕉' || b);
end if;
exception
when rate_exception then
raise_application_error(-20003, '这是我自己定义的');
end;
更多推荐
异常处理——PL/SQL教程(六)
发布评论