Oracle SQL 异常处理
今天学了异常处理
有预定义异常 与 用户自定义异常 还有 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.
②建存储过程。存储过程要的参数,和表里的字段一一对应。比如,表里有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 SQL 异常处理的更多相关文章
- Oracle数据库之PL/SQL异常处理
Oracle数据库之PL/SQL异常处理 异常指的是在程序运行过程中发生的异常事件,通常是由硬件问题或者程序设计问题所导致的. PL/SQL程序设计过程中,即使是写得最好的程序也可能会遇到错误或未预料 ...
- PL/SQL异常处理方法
PL/SQL异常处理方法 1:什么是异常处理: PL/SQL提供一个功能去处理异常,在PL/SQL块中叫做异常处理,使用异常处理我们能够测试代码和避免异常退出. PL/SQL异常信息包含三个部分: ...
- Oracle 存储过程异常处理
Oracle 存储过程异常处理 1.异常的优点 如果没有异常,在程序中,应当检查每个命令的成功还是失败,如 BEGIN SELECT ... -- check for ’no data f ...
- Oracle数据库---异常处理
Oracle异常处理在PL/SQL语句书写时,需要处理的异常-- 不做异常处理时DECLARE v_name emp.ename%TYPE; v_sal emp.sal%TYPE;BEGIN SELE ...
- Oracle SQL Developer 连接 MySQL
1. 在ORACLE官网下载Oracle SQL Developer第三方数据库驱动 下载页面:http://www.oracle.com/technetwork/developer-tools/sq ...
- Oracle sql连接
inner-join left-outer-join right-outer-join full- ...
- 解决Oracle SQL Developer无法连接远程服务器的问题
在使用Oracle SQL Developer连接远程服务器的时候,出现如下的错误 在服务器本地是可以正常连接的.这个让人想起来,跟SQL Server的一些设计有些类似,服务器估计默认只在本地监听, ...
- Oracle sql语句执行顺序
sql语法的分析是从右到左 一.sql语句的执行步骤: 1)词法分析,词法分析阶段是编译过程的第一个阶段.这个阶段的任务是从左到右一个字符一个字符地读入源程序,即对构成源程序的字符流进行扫描然后根据构 ...
- Oracle SQL explain/execution Plan
From http://blog.csdn.net/wujiandao/article/details/6621073 1. Four ways to get execution plan(anyti ...
随机推荐
- css属性选择器: | 与 ~
[attribute|=value] 选择器用于选取带有以指定值开头的属性值的元素. 注释:该值必须是整个单词,指属性的值是一个完整的单词,并未被中断.如“eng”."img".& ...
- 编写安全 PHP 应用程序的七个习惯
编写安全 PHP 应用程序的七个习惯 在提及安全性问题时,需要注意,除了实际的平台和操作系统安全性问题之外,您还需要确保编写安全的应用程序.在编写 PHP 应用程序时,请应用下面的七个习惯以确保应 ...
- MacBook OSX VMWare Fusion 11安装 Tools For Windows
需要加载对应客户机系统的安装文件,可以在/Applications/VMware\ Fusion.app/Contents/Library/isoimages文件夹下找到: 设置虚拟机的光驱: 在虚拟 ...
- 题解 CF165D 【Beard Graph】
思路:将黑边标记为1,白边标记为100000,树链剖分 如果查询时ans超过100000,那就有白边,输出-1,不然直接输出ans #include<bits/stdc++.h> #def ...
- <每日一课学习笔记> "mysql为什么加了索引还是慢查询"
long_query_time mysql判断慢查询的依据是,sql执行时间与系统参数 long_query_time 作比较,如果大于这个参数,就会将这条sql计入慢查询语句中.long_query ...
- vue导航守卫和axios拦截器的区别
在Vue项目中,有两种用户登录状态判断并处理的情况,分别为:导航守卫和axios拦截器. 一.什么是导航守卫? vue-router 提供的导航守卫主要用来通过跳转或取消的方式守卫导航.(在路由跳转时 ...
- SSH Secure Shell 编码设置-----支持中文
参考:https://www.cnblogs.com/hupf/p/6920323.html #vi /etc/sysconfig/i18n 将内容改为 LANG="zh_CN.GB1803 ...
- SpringMVC的@ControllerAdvice注解
@ControllerAdvice顾名思义,他是一个Controller的增强,是一个异常处理类.常用于实现下面三个方面的功能: 1.处理全局异常,结合方法型注解@ExceptionHandler,用 ...
- 利用SSH在本机和远程服务器之间传输文件或文件夹
1.从远程服务器上下载文件到本机 scp <服务器用户名>@<服务器地址>:<服务器中要下载的文件路径> <下载到本机的绝对路径> 2.从本机上传本地文 ...
- wyh的dp入门刷题笔记
0: 靠前感觉之前dp抄题解都是抄的题解,自己从没有真正理解过dp.wyh下了很大决心从头学dp,于是便有了这篇文章. 1.背包 前四讲01背包&多重背包&完全背包(混合背包) :樱花 ...