星辰日月00

欲多则心散,心散则志衰,志衰则思不达也!

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

--pl/sql程序执行过程中出现的错误,称之为异常。根据其严重程序,需要做不同的处理。
一、异常的基本概念
没有错误处理的pl/sql应用程序不是一个完善的应用程序,这样的程序代码在执行过程中,
 经常会出现程序不能正常执行,执行中的程序突然终止执行,甚至造成系统崩溃。为了能够设计
 出对可能出现的各种错误进行相应处理的程序,pl/sql语言提供了异常处理机制。
1.异常处理机制
pl/sql程序的错误分为两类:一类是pl/sql的语法错误,它由pl/sql编译器发现并给出错误信息。
 另一类是运行时错误,编译器发现的错误,由于不能修改程序就无法执行,因此编译错误由
 程序员来修改。
oracle中对运行时错误的处理采用了异常处理机制。一个错误对应一个异常,当错误产生时就抛出
 相应的异常,并被异常处理器(异常处理代码)捕获,程序控制权传递给异常处理器,由异常处理器
 来处理运行时的错误。
2.异常分类
pl/sql语言的异常分为两大类,一类是oracle系统异常,另一类是自定义异常。
 oracle系统异常又分为两种,一种是预定义异常,另一种是非预定义异常。
(1)预定义异常
预定义异常是Oracle系统异常中的一种,用于处理常见的Oracle错误。
Oracle预定义异常的特点是,Oracle系统定义了它们的错误编号与异常名字。
当运行pl/sql代码产生预定义错误时,与错误对应的预定义异常被自动抛出,通过预定义
异常名字捕获该异常,并对错误进行处理。
(2)非预定义异常
非预定义异常也是Oracle系统异常中的一种,用于处理预定义以外的Oracle系统错误。
它的特点是,Oracle系统定义了它们的错误编号,但没有定义异常名字。这些oracle系统错误没有
预定义异常(异常名字)与其关联,需要在pl/sql块的声明部分定义一个异常名字,然后通过伪过程
pragma exception_init将该异常名字与一个oracle错误编号相关联。这样,当运行pl/sql代码产生非预定义
错误时,与错误代码对应的非预定义异常被自动抛出,通过定义的异常名字捕获该异常,并对错误进行处理。
(3)自定义异常
自定义异常用于处理用户定义错误,即处理与Oracle系统错误无关的其他错误,自定义异常是指有些操作
并不会产生Oracle系统错误,但是程序员从业务规则角度考虑,认为是一个错误。例如,执行update操作
没有更新任何记录行时,不会引发Oracle系统错误,也不会产生异常。但是,有时需要开发人员为此操作
产生一个异常,以便进行处理,这就是用户定义异常。
3.异常处理过程
如果捕获到异常,可以在pl/sql块内处理异常,也可以不在pl/sql块内处理异常。如果不在pl/sql块内处理异常,
那么,Oracle会把异常传递到调用它的pl/sql块或pl/sql程序运行环境。
在pl/sql程序中,异常处理的三个步骤:
 定义异常。在声明部分为错误定义异常。
 抛出异常。pl/sql语句执行过程中产生错误时,招聘与错误对应的异常。
 捕获及处理异常。
(1)定义异常
定义异常的方法是在pl/sql程序的声明部分定义一个exception类型的变量。
语法格式:
 exception_name exception;
如果是非预定义异常同学需要使用伪过程,在编译阶段将异常名与一个Oracle错误代码相关联,
语法格式:
 pragma exception_init(exception_name, error_number);
 --exception_name为异常名,error_number为Oracle系统内部错误号,用一个负位数表示,
 -20999至-20000为用户定义错误的保留号。
(2)抛出异常。
由于系统不能自动识别用户定义错误,因此当产生自定义错误时,需要程序员使用特定的pl/sql
代码抛出相应的自定义异常。
语法格式:
 raise exception_name;
(3)捕获及处理异常
异常捕获语句对各类异常加以识别,对不同异常分别进行各自的处理。
语法格式:

1 exception
2 when e_name1[or e_name2...] then
3  sequence of statements1;
4 when e_name3[or e_name4...] then
5  sequence of statements2;
6  ...
7 [when others
8  sequence of_statementsn;]
9 end;


 

二、系统异常处理
1.预定义异常

 1 declare
 2  v_dividend number := 50;
 3  v_divisor number := 0;
 4  v_quotient number;
 5 begin
 6  v_quotient := v_dividend/v_divisor;
 7 exception
 8  when zero_divide then
 9   dbms_output.put_line('除数为零!');
10 end;
11 set serveroutput on
12 declare
13  v_specialty students.specialty%type;
14  v_name students.name%type;
15 begin
16  v_specialty := '&specialty';
17  select name into v_sname
18   from students where specialty = v_specialty;
19   dbms_output.put_line('学生姓名:'|| v_sname);
20 exception
21  when too_many_rows then
22   dbms_output.put_line('返回的学生记录多于一行!');
23  when no_data_found then
24   dbms_output.put_line('输入的专业不存在!');
25 end;

 

2.非预定义异常
非预定义异常需要用户定义异常名,而且还需要使用伪过程,在编译阶段将异常名与
一个Oracle错误代码相关联。

 1 set serveroutput on
 2 declare
 3  e_deptid exception;
 4  pragma exception_init(e_deptid, -2292);
 5 begin
 6  delete from departments
 7   where department_id = 101;
 8 exception
 9  when e_deptid then
10   dbms_output.put_line('在老师表中存在子记录!');
11 end;

 


3.自定义异常处理
自定义异常处理不仅需要用户定义异常名字,而且需要程序员安排何时抛出异常。

 1 set serveroutput on
 2 declare
 3  e_wage exception;
 4  v_wage teachers.wage%type;
 5 begin
 6  v_wage := &wage;
 7  insert into teachers
 8   values(10111, '王彤', '教授', '01-9月-1990', 1000, v_wage, 101);
 9  if v_wage < 0 then
10   raise e_wage;
11  end if;
12 exception
13  when e_wage then
14   dbms_output.put_line('教师工资不能为负值!');
15 end;
16 set serveroutput on
17 declare
18  e_wage exception;
19  v_wage teachers.wage%type;
20  v_deptid teachers.department_id%type;
21  v_bonus teachers.bonus%type;
22 begin
23  v_wage := &wage;
24  v_deptid := &department_id;
25  insert into teachers
26   values(10111, '王彤', '教授', '01-9月-1990', 1000, v_wage, 101);
27  select bonus into v_bonus
28   from teachers
29   where department_id = v_deptid;
30  if v_wage < 0 then
31   raise e_wage;
32  end if;
33 exception
34  when e_wage then
35   dbms_output.put_line('教师工资不能为负值!');
36   rollback;
37  when others then
38   dbms_output.put_line('查询老师资金时出错!');
39 end;

 

 

 

4.使用异常函数
在pl/sql代码运行出现错误时,通过使用异常函数可以获得错误代码以及相关的错误描述。
其中函数sqlcode用于获得Oracle错误代码,而sqlerrm则用于获得与之相应的错误描述。

 1 set serveroutput on
 2 declare
 3  e_wage exception;
 4  v_wage teachers.wage%type;
 5  v_deptid teachers.department_id%type;
 6  v_bonus teachers.bonus%type;
 7 begin
 8  v_wage := &wage;
 9  v_deptid := &department_id;
10  insert into teachers
11   values(10111, '王彤', '教授', '01-9月-1990', 1000, v_wage, 101);
12  select bonus into v_bonus
13   from teachers
14   where department_id = v_deptid;
15  if v_wage < 0 then
16   raise e_wage;
17  end if; 
18 exception
19  when e_wage then
20   dbms_output.put_line('教师工资不能为负值!');
21   rollback;
22  when others then
23   dbms_output.put_line('错误代码:'||sqlcode);
24   dbms_output.put_line('错误描述:'||sqlerrm);
25 end;

 

posted on 2012-03-24 15:56  星辰日月00  阅读(323)  评论(0编辑  收藏  举报