内容简介:今天学了异常处理预定义异常包括– NO_DATA_FOUND --没有找到数据
今天学了异常处理
raise_application_error()函数
raise_application_error() 只能把异常抛出而不能处理异常。预定义异常包括
– NO_DATA_FOUND --没有找到数据
– TOO_MANY_ROWS --找到多行数据
– INVALID_CURSOR --失效的游标
– ZERO_DIVIDE --除数为零
– DUP_VAL_ON_INDEX –唯一索引中插入了重复值
预定义异常的示例:
declare
v_id emp.empno%type; --声明变量
begin
select empno into v_id from emp where deptno =40;
exception --异常处理
when no_data_found then --no_data_found 是使用 select 某字段,然后 into 的时候,该字段没有出。
rollback;
dbms_output.put_line('没有40号部门记录');
when too_many_rows then --too_many_rows 是使用 select 某字段,然后 into 的时候,该字段有多个值。
rollback;
dbms_output.put_line('返回多条记录');
when others then --其它的异常出现
rollback;
dbms_output.put_line('出现其他错误.');
end;
用户自定义异常就是用户定义一个异常情况,遇到这种情况再对这种情况进行处理
因为用户定义的异常不一定是Oracle返回的系统错误,系统不会自动触发,需要在声明部分定义。用户定义的异常处理部分基本上和预定义异常相同。
declare
salary_level varchar2(1);
invalid_salary_level exception; --声明异常
begin
salary_level := 'D';
if salary_level not in ('A','B','C') then
raise invalid_salary_level; --触发异常
end if;
exception --异常处理
when invalid_salary_level then
dbms_output.put_line('invalid salary level');
end;
raise_application_error() 函数只是将异常抛出,不进行异常处理,并且终止程序。而用户自定义异常以及预定义异常不回终止程序,但会终止该 PL/SQL 代码块,所以一个存储过程中可以有多个 PL/SQL 代码块。
关于异常的语法及定义:
什么是异常:
PL/SQL用异常和异常处理器来实现错误处理
Oracle中出现错误的情形通常分为编译时错误(compile-time error)和运行时错误(run-time error)。
异常在PL/SQL执行过程中很可能出现
对异常如果不进行处理,异常可能会中断程序的运行
捕获异常的规则:
在异常部分WHEN 子句没有数量限制
当异常抛出后,控制无条件转到异常处理部分
EXCEPTION 关键词开始异常处理部分 WHEN OTHERS 为最后的一条子句
在异常块中,只有一个句柄会处理异常
关于异常捕获的函数:
SQLCODE 返回错误代码
SQLERRM 返回与错误代码关联的消息
保存任何非预期的异常的错误编码和错误消息
declare
v_error_code NUMBER;
v_error_message VARCHAR2(255);
BEGIN
EXCEPTION
WHEN OTHERS THEN
ROLLBACK;
v_error_code := SQLCODE;
v_error_message := SQLERRM;
INSERT INTO err_logs VALUES (v_error_code, v_error_message);
END;
异常的传播
PL/SQL中错误处理的步骤:
步骤1:如果当前块中有该异常的处理器,则执行该异常处理语句块,然后控制权传递到外层语句块 步骤2:如果没有当前异常的处理器,把该异常传播给外层块。然后在外层执行步骤1:如果此语句在最外层语句块,则该异常将被传播给调用环境
没有处理的异常将沿检测异常调用程序传播到外面,当异常被处理并解决或到达程序最外层传播停止。异常是自里向外逐级传递的。
小题:
1.根据员工号,获得员工到目前为止参加工作年限(保留到整数),员工号不存在时提示“此员工号不存在”。
create or replace function get_workyear
(v_id in emp.empno%type)
return varchar2
IS
v_workyear integer;
BEGIN
select to_char(sysdate,'yyyy')-to_char(hiredate,'yyyy') --两个数字字符串相减的值存到整数型变量中
into v_workyear
from emp
where emp.empno = v_id;
return v_workyear;
EXCEPTION
when no_data_found then
dbms_output.put_line('此员工号不存在');
return -1;
END get_workyear;
2.
①建表myemp。该表内容与emp一致;
②建存储过程。存储过程要的参数,和表里的字段一一对应。比如,表里有empno,存储过程就要有一个参数对应这字段i_empno,类型肯定和empno一样,如果你知道类型是number(4),就直接写成(i_empno in number(4),...)以此类推.
③功能实现,根据empno判断,如果myemp表里已经有这个empno,你就根据你传入的信息把empno的信息更新了,如果没有,就把你这些传入的字段,插入到表里,
eg:我只用两个字段来说明:empno、sal
入参1:123,1000,经过��断,myemp表里没有123这个empno,那么执行完存储过程,这个信息要插入到表里;
入参2:7369,2000,经判断,表里已经有这个编号,但sal为800,那么执行完存储过程,7369的sal更新为2000;
create or replace procedure store_info
(v_empno in myemp.empno%type,
v_ename in myemp.ename%type,
v_job in myemp.job%type,
v_mgr in myemp.mgr%type,
v_hiredate in myemp.hiredate%type,
v_sal in myemp.sal%type,
v_comm in myemp.comm%type,
v_deptno in myemp.deptno%type
)
IS
v_id myemp.empno%type:=0;
BEGIN
select count(*) into v_id
from myemp
where myemp.empno = v_empno;
if (v_id=0) then
insert into myemp(empno, ename, job, mgr, hiredate, sal, comm, deptno)
values (v_empno,v_ename,v_job,v_mgr,v_hiredate,v_sal,v_comm,v_deptno);
else
update myemp
set myemp.ename=nvl(v_ename,myemp.ename) , myemp.job=nvl(v_job,myemp.job),
myemp.mgr=nvl(v_mgr,myemp.mgr) , myemp.hiredate=nvl(v_hiredate,myemp.hiredate),
myemp.sal=nvl(v_sal,myemp.sal) , myemp.comm=nvl(v_comm,myemp.comm),
myemp.deptno=nvl(v_deptno,myemp.deptno)
where myemp.empno = v_empno ;
end if;
END store_info;
begin
store_info(7369,null,null,null,null,2000,null,null);
end;
结果
【注意】:
为什么要把这一题关于存储过程的题放到这里?
因为我起初用异常处理部分来写这一题......,这是不规范的。
本题中用到 count() 函数,count() 是用来计算满足条件的行数的,count(*) 计算所有的行,包括空值。
用异常处理来写本题的代码:
create table myemp(empno, ename, job, mgr, hiredate, sal, comm, deptno)
as
select empno, ename, job, mgr, hiredate, sal, comm, deptno
from emp;
create or replace procedure store_info
(v_empno in myemp.empno%type,
v_ename in myemp.ename%type,
v_job in myemp.job%type,
v_mgr in myemp.mgr%type,
v_hiredate in myemp.hiredate%type,
v_sal in myemp.sal%type,
v_comm in myemp.comm%type,
v_deptno in myemp.deptno%type
)
IS
v_id myemp.empno%type;
BEGIN
select myemp.empno into v_id
from myemp
where myemp.empno = v_empno;
update myemp
set myemp.ename=v_ename, myemp.job=v_job,myemp.mgr=v_mgr,
myemp.hiredate=v_hiredate, myemp.sal=v_sal,
myemp.comm=v_comm,myemp.deptno=v_deptno
where myemp.empno = v_id;
EXCEPTION
when no_data_found then
insert into myemp(empno, ename, job, mgr, hiredate, sal, comm, deptno)
values (v_empno,v_ename,v_job,v_mgr,v_hiredate,v_sal,v_comm,v_deptno);
END store_info;
3.
编写PL/SQL块,使用SELECT语句将管理者编号为空的员工的姓名及工作编号显示出来,如果符合条件的员工多于一人,则返回字符串“最高管理者人员过多!”字符串,如果找到没有符合条件的记录,则返回字符串“没有最高管理者,请指定”
代码:
declare
o_ename emp.ename%type;
o_empno emp.empno%type;
v_id emp.empno%type;
begin
select emp.empno into v_id
from emp
where emp.mgr is null;
select emp.ename into o_ename from emp where emp.empno = v_id;
select emp.empno into o_empno from emp where emp.empno = v_id;
dbms_output.put_line('员工姓名:'||o_ename||','|| '员工编号:'||o_empno);
exception
when no_data_found then
dbms_output.put_line('没有最高管理者,请指定');
when too_many_rows then
dbms_output.put_line('最高管理者人员过多');
end;
4.获得每个部门的平均工资,如果平均工资大于2000,视为用户定义的异常,提示“该部门的平均工资过高”。
declare
cursor cemp
is
select dept.dname,avg(sal)
from emp,dept
where emp.deptno = dept.deptno
group by emp.deptno ,dept.dname;
v_dname dept.dname%type ;
v_asal emp.sal%type ;
too_high_sal exception;
begin
open cemp;
loop --打开循环
fetch cemp into v_dname,v_asal;
exit when cemp%notfound;
begin --这里写了一个 PL/SQL 代码块,里面可以做异常处理
if v_asal > 2000 then
raise too_high_sal;
end if;
exception --异常处理,会终止此代码块。进入下一次循环
when too_high_sal then
dbms_output.put_line(v_dname||'该部门工资过高');
end;
end loop;
close cemp;--注意end loop 与 close cemp 的先后顺序。必须是先结束循环,再关闭游标。
end;
附一张图:
更多Oracle相关信息见 Oracle 专题页面 https://www.linuxidc.com/topicnews.aspx?tid=12
Linux公社的RSS地址 : https://www.linuxidc.com/rssFeed.aspx
本文永久更新链接地址: https://www.linuxidc.com/Linux/2019-02/156844.htm
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 自然语言处理之数据预处理
- Python数据处理(二):处理 Excel 数据
- 什么是自然语处理,自然语言处理主要有什么
- 集群故障处理之处理思路以及健康状态检查(三十二)
- Spark 持续流处理和微批处理的对比
- Android(Java)日期和时间处理完全解析——使用Gson和Joda-Time优雅地处理日常开发中关于时间处理的...
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Programming Ruby
Dave Thomas、Chad Fowler、Andy Hunt / Pragmatic Bookshelf / 2004-10-8 / USD 44.95
Ruby is an increasingly popular, fully object-oriented dynamic programming language, hailed by many practitioners as the finest and most useful language available today. When Ruby first burst onto the......一起来看看 《Programming Ruby》 这本书的介绍吧!
JSON 在线解析
在线 JSON 格式化工具
Base64 编码/解码
Base64 编码/解码