1、异常处理概念
异常情况处理(EXCEPTION)是用来处理正常执行过程中未预料的事件,程序块的异常处理预定义的错误和自定义错误,由于PL/SQL程序块一旦产生异常而没有指出如何处理时,程序就会自动终止整个程序运行。
2、异常的分类:
1) 预定义( Predefined )错误
ORACLE预定义的异常情况大约有24个。对这种异常情况的处理,无需在程序中定义,由ORACLE自动将其引发。
相当于异常发生 Oracle 不希望你处理异常 只是希望让你修改代码。
错误号 | 异常错误信息名称 | 说明 |
| ||
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|
预定义异常:
declare
v_sal student.sal%type;
begin
select sal into v_sal from student where classid='100';
exception
when too_many_rows then
dbms_output.put_line('输出的行数太多了');
when others then
dbms_output.put_line('出现了其他类型的异常');
end;
或者
declare
v_sal t_emp.sal%type;
begin
select sal into v_sal from t_emp where employee_id='20';
exception
when no_data_found then
dbms_output.put_line('未找到数据');
end;
2)非预定义( Predefined )错误
即其他标准的ORACLE错误。对这种异常情况的处理,需要用户在程序中定义,然后由ORACLE自动将其引发。
Oracle会自动的引发 但是现在希望你自己来处理异常
对于这类异常情况的处理,首先必须对非定义的ORACLE错误进行定义。步骤如下:
A、在PL/SQL 块的定义部分定义异常情况:
异常情况的名字 EXCEPTION;
B、 将其定义好的异常情况,与标准的ORACLE错误联系起来,使用PRAGMAEXCEPTION_INIT语句:
PRAGMA EXCEPTION_INIT(异常情况的名字,错误代码);在PL/SQL 块的异常情况处理部分对异常情况做出相应的处理。
|实例2|
非预定义异常
Declare
--声明一个异常
e_deleteid_exception exception;
--把自定义的异常和oracle的错误关联起来
pragma exception_init(e_deleteid_exception,-2292);
begin
delete from t_emp where employee_id='100';
exception
when e_deleteid_exception then
dbms_output.put_line('出现错误');
end;
3)用户定义(User_define) 错误
程序执行过程中,出现编程人员认为的非正常情况。对这种异常情况的处理,需要用户在程序中定义,然后显式地在程序中将其引发。相当于非预定义的扩展情况 这时候自己定义你认为的异常 自己解决。
当与一个异常错误相关的错误出现时,就会隐含触发该异常错误。用户定义的异常错误是通过显式使用RAISE语句来触发。当引发一个异常错误时,控制就转向到EXCEPTION块异常错误部分,执行错误处理代码。
对于这类异常情况的处理,步骤如下:
A、在PL/SQL 块的定义部分定义异常情况:
异常情况名字 EXCEPTION;
B、 RAISE <异常情况>;
C、 在PL/SQL 块的异常情况处理部分对异常情况做出相应的处理。
|实例3|
用户自定义异常
declare
e_too_high_sal exception;
v_sal employees.salary%type;
begin
select salary into v_sal from employees where employee_id=100;
if v_sal>2000 then
raise e_too_high_sal;
end if;
exception
when e_too_high_sal then dbms_output.put_line('工资太高了');
end;
|实例4|
用户自定义异常
declare
v_sal t_emp.sal%type;
v_name t_emp.name%type;
--声明一个异常
delete_mgr_excep exception;
--把自定义的异常和oracle的错误关联起来
pragma exception_init(delete_mgr_excep,-2292);
--声明一个异常
too_high_sal exception;
begin
select sal into v_sal from t_emp where employee_id=1;
if v_sal>100000 then
raise too_high_sal;
end if;
delete from t_emp where employee_id=111;
dbms_output.put_line(v_sal);
select name into v_name from t_emp where sal='8487.20';
exception
when too_many_rows then dbms_output.put_line('输出的行数太多了');
when delete_mgr_excep then dbms_output.put_line('Manager不能直接删除');
--处理异常
when too_high_sal then dbms_output.put_line('工资过高了');
end;
|实例5|
更新指定员工工资,增加100;若该员工不存在则抛出用户自定义异常: no_result
declare
--自定义异常
no_result exception;
begin
update t_emp set sal=sal+100 where employee_id='110';
--使用隐式游标,抛出自定义异常
if sql%notfound then
raise no_result;
end if;
exception
--处理程序抛出的异常
when no_result then
dbms_output.put_line('更新失败');
end;
/
详解:
sql是系统自动创建隐式游标
隐式游标自动声明、打开和关闭,其名为 SQL
通过检查隐式游标的属性可以获得最近执行的DML 语句的信息
隐式游标的属性有:
SQL%FOUND – SQL 语句影响了一行或多行时为 TRUE
SQL%NOTFOUND – SQL 语句没有影响任何行时为TRUE
SQL%ROWCOUNT – SQL 语句影响的行数
SQL%ISOPEN - 游标是否打开,始终为FALSE
细水长流,打磨濡染,渐趋极致,才是一个人最好的状态。