一、异常
是在PL/SQL执行过程中出现的警告或错误,分为编译时错误和运行时错误
二、触发异常条件
发生一个Oracle错误
使用raise语句显示触发
三、异常类型
1)预定义异常
异常情况名 错误代码 描述
DUP_VAL_ON_INDEX ORA-00001 试图更新或插入重复记录
INVALID_CURSOR ORA-01001 非法游标操作
INVALID_NUMBER ORA-01722 字符串向数字转换失败
NO_DATA_FOUND ORA-01403 执行的SELECT没有查到数据
TOO_MANY_ROWS ORA-01427 未使用游标,SELECT语句返回了多行数据
VALUE_ERROR ORA-06502 出现数字、数据转换、字符串或限制型错误
ZERO_DIVIDE ORA-01476 被零除
2)非预定义异常
自定义异常值与系统内置异常编号绑定,如
e_emp_cons exception;
pragma exception_init(e_emp_cons,-00001);
3)自定义异常
完全自定义异常
四、示例代码
--1.预定义异常
declare
v_sal emp.sal%type;
begin
select sal into v_sal from emp
where empno=9999; -- 没有员工编号9999信息
exception
when no_data_found then
dbms_output.put_line('没有查到数据');
when others then
dbms_output.put_line('其他异常');
end;
--输出结果:没有查到数据
--2.非预定义异常
declare
e_emp_cons exception; --声明异常
pragma exception_init(e_emp_cons,-00001); --跟系统内置异常编号绑定
begin
insert into emp --选取emp全部记录,在插入emp表中(违反唯一性约束)
select * from emp;
exception
when e_emp_cons then
dbms_output.put_line('主键值有重复啦!');
when others then
dbms_output.put_line('其他异常');
end;
--3.自定义异常
/*
统计大于平均薪水的员工数量,
如果数量大于5,触发e_too_many异常,显示’大于平均工资的人数不少’;
如果数量小于等于5,触发e_too_low异常,显示’大于平均工资的人数太少’
*/
declare
e_too_many exception;
e_too_low exception;
v_count number;
begin
select count(*) into v_count from emp
where sal> ( select avg(sal) from emp );
dbms_output.put_line( v_count); -- 6
if(v_count>5) then
raise e_too_many; -- 调用异常 e_too_many
else
raise e_too_low;
end if;
exception
when e_too_many then
dbms_output.put_line('大于5'); -- 输出 【大于5】
when e_too_low then
dbms_output.put_line('小于5');
when others then
dbms_output.put_line('其他异常');
end;
--4.捕获异常的函数
begin
insert into emp
select * from emp;
exception
when others then
dbms_output.put_line(sqlerrm); --输出:ORA-00001: 违反唯一约束条件 (SCOTT.PK_EMP)
dbms_output.put_line(sqlcode); --输出: -1
end;
--Raise_Application_Error,范围定义在-20000 到 -209999中
--1)在执行部分抛出异常
BEGIN
delete from emp where deptno=40;
if SQL%NOTFOUND then
Raise_Application_Error(-20202,'没有这个部门'); --抛出
end if;
dbms_output.put_line(1); --不执行
EXCEPTION
when others then
dbms_output.put_line('指定部门没有数据');
dbms_output.put_line(sqlerrm); --错误消息
dbms_output.put_line(sqlcode); --错误编码
END;
--2)在异常区域抛出异常
declare
emp_row emp%rowtype;
BEGIN
select * into emp_row from emp where deptno = 40 and rownum<=1;
dbms_output.put_line(1); --不执行
EXCEPTION
when NO_DATA_FOUND then
Raise_Application_Error(-20111,'指定部门没有数据'); --抛出
END;