oracle异常、异常捕捉以及异常处理

1、概念

异常是指PL/SQL程序在执行时出现的错误
在PL/SQL中的一个警告或错误的情形都被称为异常。提示:编译错误(主要指语法错误)不包含在内。
异常处理通常写在执行体的最下面,在所有执行语句之后以exception关键字开始异常处理

语法:

Exception
	when exception_name then
		Statement1
		…
      when exception_name thenwhen others then  --一般是最后一条子句,没有捕捉到的都被它捕捉

异常处理部分包含一个或多个when子句,子句中是被捕捉的异常名称

注意: when others then 是可以没有的。

非预定义异常只能编号没有名称
所有的异常都有编号

异常的分类:

异常包括系统异常和自定义异常
系统异常分为预定义异常和非预定义异常

2、预定义异常

是指Oracle已经预先定义好名称的异常。每个预定义异常都有名字和对应的错误码(错误编号)
捕捉预定义异常的方法很简单,直接在程序里按名称捕捉就可以了

oracle 预定义的异常:

1、两数相除,分母为0,捕捉并抛出异常

declare
	n1 number(2) := 9;
	n2 number(2) :=0;
	result number;
begin
	result := n1/n2;
	dbms_output.put_line(result);
end;

这个时候上面的代码运行的时候会报错,是有异常的。

declare
	n1 number(2) := 9;
	n2 number(2) :=0;
	result number;
begin
	result := n1/n2;
	dbms_output.put_line(result);
	exception 
	when zero_divide then
	dbms_output.put_line('除数不能为0');
end;

上面的代码运行的时候会在控制台抛出“除数不能为0”,这就是抛出异常的过程,上面是进行捕捉异常的过程。

记住两个最常用的异常:NO_DATA_FOUND 、TOO_MANY_ROWS

当在exception段中定义了多个异常时,只会执行一个,之后跳出异常段。

2、值转换异常

SET SERVEROUTPUT ON;
DECLARE
    x NUMBER;
BEGIN
    x:= 'a123';--向NUMBER类型的变量x中赋值字符串,导致异常
    dbms_output.put_line(x);
EXCEPTION
   WHEN VALUE_ERROR THEN
     DBMS_OUTPUT.PUT_LINE('数据类型错误');
END;

运行结果为:
数据类型错误
PL/SQL 过程已成功完成。

上面出现异常的原因是因为x是number数值型的函数,而在赋值的时候,x被赋予了一个字符串,所以出现了值转换时候的异常。
但是如果将纯数字的字符串赋值给x,x会自动将纯数字的字符串转换为number类型。

3、根据姓名查找员工的职位,可能会出现的异常有:没有个这员工,或者有两个或更多的人叫同样的名字。

declare
	v_name emp.ename%type := '&name';
	v_job emp.job%type;
begin
	select job into v_job from emp where ename=v_name;
	dbms_output.put_line(v_name || '的职位是:' || v_job);
	exception 
	when no_data_found then
		dbms_output.put_line('没有这个员工');
	when TOO_MANY_ROWS then
		dbms_output.put_line('有同名的员工');
	when others then
		dbms_output.put_line('其他异常');
end;

当select语句查询的结果没有数据的时候,就会抛出no_data_found异常,当结果中的数据有多条数据的时候,会抛出TOO_MANY_ROWS,如果存在异常,但不是前面两种异常就会抛出others异常。

异常是通过异常名称来捕获的。
当在exception段中定义了多个异常时,只会执行一个,之后跳出异常段

3、非预定义异常

在数据库中没有定义异常名称的异常

通常都是数据库的错误,这些错误只有错误编号,而没有错误的异常名称,所以不能直接捕捉到

用户在使用这类异常时必须先为它声明一个异常类型的名称,然后通过pragma exception_inin语句为该异常关联错误编号

使用非预定义异常包括三个步骤:

1.在程序块的声明部分定义一个异常名称
2.在声明部分使用伪过程将异常名称和错误编号关联
3.在异常处理部分捕获异常并对异常情况做出相应的处理
伪过程的语法:
pragma exception_init(exception_name,oracle_error_number)
exception_name:异常名称
oracle_error_number:错误代码

例子:

有一个异常:ORA-02292,没有名称,含义是当删除被子表引用的父表中的相关记录时发生。

表emp有外键关联表dept的主键,当部门10有员工时,不能删除部门10。如果我们做了这样的操作,就违反了约束条件。


父表:dept表
子表:emp表

delete from dept where deptno=10;
提示:违反完整性约束条件

declare
	myexception exception;
	pragma exception_init(myexception,-02292);
begin
	delete from dept where deptno=10;
	exception 
	when myexception then
		dbms_output.put_line('10部门有员工,不能删除');
	when others then
		dbms_output.put_line('其他异常');
end;

4、自定义异常

用户在实际的开发中,可能会有一些业务逻辑上的规定,如果违反了这些规定,则会发生异常

如何定义和使用自定义异常?

异常定义
在声明部分采用exception关键字声明异常:myexception exception

异常引发
在程序执行体部分,使用raise关键字进行引发:
raise myexception

举例:

在emp表中查询james的工资,如果工资小于5000,则引发自定义异常

DECLARE
  myexception EXCEPTION;
  v_sal emp.sal% TYPE;
BEGIN
  select sal into v_sal from emp where ename='JAMES';
  IF v_sal<5000 THEN
    raise myexception;
  end if;
  dbms_output.put_line('JAMES的工资是:'||v_sal);
EXCEPTION
  when myexception then
    dbms_output.put_line('工资太少了');
  when no_data_found THEN
    dbms_output.put_line('没有这个员工');
END;

使用用户自定义异常,同样需要在声明部分定义异常的名称,然后在执行体中,通过一些逻辑判断决定是否违反了用户的规则,如果违反规则,则调用raise命令人为触发自定义的异常,并在异常处理部分捕捉到这个异常进行处理。
显然:raise语句应该与if语句一起使用。

5、课堂练习:

根据员工编号对emp表修改员工的奖金,当员工原本有奖金,则再增加100元,如果原来没有奖金,则抛出异常,说明奖金为空。

declare 
  myexception exception;
  v_comm emp.comm%type;
  v_empno emp.empno%type :=&a;
begin
  select comm into v_comm from emp where empno=v_empno;
  if v_comm is null then
  raise myexception;
  end if;
  dbms_output.put_line(v_comm);
  EXCEPTION
  when myexception then
    dbms_output.put_line('MEIYOUjiangJIN');
  when no_data_found THEN
    dbms_output.put_line('没有这个员工');
END;
  • 4
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱睡觉的小馨

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值