异常处理——PL/SQL教程(六)

42 篇文章 8 订阅
30 篇文章 9 订阅

异常处理

概述
/*
在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;
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值