• PL/SQL 异常的传播


    今晚看了关于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        dbms_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

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

     

  • 相关阅读:
    golang入门--一个简单的http client
    Linux 安装JDK1.8
    spring boot配置拦截器和过滤器
    spring boot swagger配置
    spring boot语言国际化
    element-ui 中为表头添加tooltips
    spring boot定时任务的使用
    Windows编译运行webrtc全过程,并实现屏幕共享
    WLYX官方团队の规则
    AVL树的平衡算法(JAVA实现)
  • 原文地址:https://www.cnblogs.com/kingsleylam/p/3025379.html
Copyright © 2020-2023  润新知