您的位置:首页 > 数据库

PL/SQL 异常的传播

2015-12-21 19:13 155 查看
今晚看了关于PL/SQL异常传播的内容,做个笔记。
1.PL/SQL执行语句块发生运行时错误

PL/SQL 语句块的可执行部分发生某个运行时错误,执行权会转到该语句块的异常处理部分。当与该异常相关的语句执行完毕之后,执行权会转到主机环境或者外围语句块。如果不存在该错误的异常处理程序,该异常就会被传播到外围语句块,然后再次执行刚才所描述的步骤。如果没有发现异常处理程序,则程序执行会终止,执行权会转到主机环境。请看下例:

1 begin
2   declare
3     a number := 4;
4     b number := 0;
5   begin
6     a := a/b;
7     dbms_output.put_line('a is ' || a);
8   exception
9     when zero_divide then dbms_output.put_line('inner zero divide');
10   end;
11   dbms_output.put_line('can u see me?');
12 end;


执行之后在第6行抛出一个异常,执行权转到exception,在里面被捕获,并执行相应语句,此后执行权转到外围语句块。因此第7行不会执行,转而执行第11行。

所以输出结果是:

1 inner zero divide
2 can u see me?


但如果在内部的异常处理块无法与之匹配捕获,那么异常将传播到外围语句块的异常处理部分进行处理,来看下面的例子:

1 begin
2   declare
3     a number := 4;
4     b number := 0;
5   begin
6     a := a/b;
7     dbms_output.put_line('a is ' || a);
8   exception
9     when value_error then dbms_output.put_line('inner value error');
10   end;
11   dbms_output.put_line('can u see me?');
12 exception
13   when zero_divide then dbms_output.put_line('outter zero divide');
14 end;


在第6行抛出异常后,执行权转换到异常处理块,同样第7行不会执行。在内部异常处理块,该异常不是value_error,那么异常将传播到外围语句块的异常处理部分,因此第11行不会执行,在第13行捕获异常,输出语句。

1 outter zero divide


如果异常在内部就捕获了,即使内部异常处理的类型与外部异常处理的类型一样,也不会传播到外部,因为已经在内部处理了。因此将上面第9行的value_error改为与外面一样的zero_divide,第13行照样执行。

 

2.PL/SQL语句块声明部分发生运行时错误

PL/SQL语句块声明部分发生运行时错误,如果没有外围语句块,执行权将转换到主机环境(即报错),而不会转到该块的异常处理部分。那么要捕获该异常,只需要在外部加上语句块即可。

1 begin
2   declare
3        a char(2) := 'hello';
4   begin
5        dbms_output.put_line('a is ' || a);
6   exception
7        when invalid_number or value_error then dbms_output.put_line('inner error');
8   end;
9   dbms_output.put_line('hello world');
10 exception
11   when invalid_number or value_error then dbms_output.put_line('outter error');
12 end;


如上面代码,在声明部分抛出异常,接下来异常被传播到第10行的外部异常处理部分,因此第5和第9行都不会执行,第11行被执行,输出如下。

1 outter error


 

3.再次抛出异常

在有些情况下,也许希望当发生特定类型的错误时,能够停止当前程序。也就是说,在内部抛出异常后,如果在内部处理完那么外部语句将继续执行,如果想一出现异常就停止程序,那么可以将异常传递到外部语句块,让外部语句块的异常处理部分进行处理,这个过程叫再次抛出异常。关键在于内部捕获到异常后,使用raise关键字将其传播出去。

1 begin
2   declare
3        a char(2);
4   begin
5        a := 'hello';
6        d
9c8b
bms_output.put_line('a is ' || a);
7   exception
8        when invalid_number or value_error then raise;
9   end;
10   dbms_output.put_line('hello world');
11 exception
12   when invalid_number or value_error then dbms_output.put_line('outter error');
13 end;


如上面代码,第8行捕获到异常后,将其再次抛出,被外部程序所捕获,因此外部的第10行不会被执行,结果如下:

1 outter error


 

明晚继续努力,学习异常的高级概念。

 

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: