• Oracle PL/SQL 程序设计读书笔记 第6章 异常处理


    Oracle PL/SQL 程序设计读书笔记 - 第6章 异常处理

    Oracle PL/SQL 程序设计读书笔记 - 第6章 异常处理

    6.1 异常处理概念和术语

    • 系统异常:这是由Oracle定义 的,在PL/SQL运行时引擎 发现某个错误 后招抛出来的异常。某些系统异常有名称 ,比如NODATAFOUND,更多的异常公有一个数字 和描述。
    • 程序员定义的异常:这是由程序员定义的异常,并且专门针对当前的应用程序设计。你可以使用EXCEPTIONINIT指令给Oracle错误指定名称,或者使用RAISEAPPLICATION_ERROR给这个错误指定一个数字和描述。
    • 无名或者匿名异常:有些异常只有一个错误代码和描述,没有可用于RAISE语句或者异常处理WHEN语句中的名称。
    • 有名的异常:一个Oracle的内置包或者由开发人员命名。也可以通过EXCEPTION_INIT编译指令为异常分配一个名字,或者只定义一个名字(名字可以 用在RAISE和异常处理部分)

    6.2 定义异常

    PL/SQL的两个缺省包之一,STANDARD包和DBMS_STANDARD包。

    6.2.1 声明有名异常

    你必须 在PL/SQL代码块的声明部分自己声明这些异常。声明异常的方法是在程序中列出异常的名称,后面再跟上关键词EXCEPTION,像这样

    PROCEDURE XXX
    IS
        invalid_company_id EXCEPTION
    ;
    BEGIN
       
    .... body of excutable statements ...
    EXCEPTION
       WHEN NO_DATA_FOUND
    -- system exception
       THEN
         
    ...
       WHEN invalid_company_id
       THEN
         
    ...
    END;

    异常的名字在格式上非常类型布尔类型变量名,但是有两种引用方式。 * 在程序的执行单元 中的RAISE语句引用(抛出异常)

    RAISE xxx_exception;
    • 在异常处理单元的WHEN语句(处理招聘的异常时)

      WHEN xxx_exception THEN

    6.2.2 异常名称和错误代码相互关联

    错误数字是在-20000和-20999之间的数字。没有名字的异常是完全合法的。 SQLCODE是一个内置函数,使用是返回最后抛出错误,。

    • 使用EXCEPTIONINIT EXCEPTIONINIT指令会让编译器把那个用EXCEPTION定义的标识符和一个指定的错误数字关联到一起。一旦创建了这个关联关系,你就可以通过名字来抛出异常,也可以 用名字写一个明确的WHEN处理句柄来捕获这个错误。 EXCEPTION_INIT编译指令必须出现在代码块的声明单元,并且该异常已经在同一个块中或外层块,或者包的规范部分被命名了。这是一个匿名块的语法:

      DECLARE exceptionname EXCEPTION; PRAGMA EXCEPTIONINIT(exception_name, integer);

    这里的exception_name就是异常的名称,integer是一个整数值。也就是要关联到这个被命名异常的Oracle错误号。错误数字可以使用符合下列约束的任意整数: 不可以使用-1403。若因为某些原因要把自己命名的异常关联到这个错误,你需要给EXCEPTION_INIT指令传递100 不可以使用除了0和100之外的任何正数 * 不可以使用小于-1000000的负数。

    建议以下两种场合使用EXCEPTION_INIT指令 为一些程序中经常要用到的,匿名的系统异常命名。 为使用RAISE-APPLICATION_ERROR抛出的应用专有错误命名。

    6.2.4 异常的作用范围

    • 被命名的系统异常:这些异常不是在某个专门的代码块中声明或定义的,是全局都可用的。可以在任何代码中抛出和处理被命名的系统异常。
    • 被命名的程序定义的异常:这种异常只能在声明它的块的执行单元异常处理单元被抛出和处理。对于在包规范部分定义的异常,那么对于那些对这个包具有的EXECUTE权限的用户的程序,这个异常都是可见的
    • 匿名系统异常:这些任何PL/SQL块的异常处理单元的WHEN OTHERS部分处理。如果这些已成被指定了名字,这个名称的作用范围是和被命名的自定义异常是一样的。
    • 匿名的自定义异常:这些异常只是在调用 RAISEAPPLICATIONERROR时才定义,并返回到调用程序。

    6.3 抛出异常

    程序中可以有3种抛出异常的办法 数据库检测到错误时可以抛出异常 使用RAISE语句抛出异常 * 使用内置的RAISEAPPLICATIONERROR过程抛出异常

    6.3.1 RAISE语句

    • 一、可以用于抛出一个在当前块自定义的异常,也可以抛出在STANDARD包中定义的系统异常。

      RAISE exceptiojn_name;

    • 二、需要一个包名做限定符

      RAISE packagename.exceptionname;

    • 三、不需要异常名称,但只可以用在异常处理单元的WHEN语句中。

      EXCEPTION WHEN xxx THEN RAISE;

    6.3.2 使用RAISE_APPLICATION_ERROR

    使用RAISEAPPLICATIONERROR而不是RAISE的好处在于,你可以给异常加上一段错误消息。

    PROCEDURE RAISE_APPLICATION_ERROR (
      num binary_integer
    ,
      msg varchar2
    ,   --长度不能超过2K
      keeperrorstack
    booleandefault FALSE);

    6.4 处理异常

    异常处理代码在程序中的位置是在所有可执行语句之后,在块的END语句之前。

    DECLARE
       
    ... declarations ...
    BEGIN
       
    ... executable statements ...
    [ EXCEPTION
       
    ... exception handlers ...]
    END;

    WHEN exception_name
    [OR exception_name ...]
    THEN
       executable statements

    WHEN OTHERS语句是可选 的,如果没有这个语句,任何未处理的异常立即传播到外层块。WHEN OTHERS 语句必须是异常处理部分的最后一个句柄。如果在WHEN OTHERS后面还有WHEN语句,会收到编译错误。

    6.4.1 内置的错误函数

    • SQLCODE返回代码块中最后一次抛出的错误代码,如果没有任何错误,返回0。ORACLE数据库用一个栈结构SQLCODE值。
    • SQLERRM函数可以返回某个错误代码对应的错误消息。返回的字符串的最大长度是512个字节。

    6.4.3 未处理异常

    如果程序中抛出了一个异常,但这个异常并没有在当前的PL/SQL或者外层的块的异常处理单元被处理,这个异常就是未处理异常。PL/SQL会把这个未处理的异常作为错误一直返回到运行PL/SQL的应用环境。

    6.4.4 传播未处理异常

    抛出一个异常后,PL/SQL在当前块寻找针对该异常的处理句柄。如果没有发现匹配的句柄,PL/SQL会把异常传播到包含当前块的外层块中。PL/SQL通过在外层块再次抛出的方式尝试处理这个异常。这个动作会在后续的外层块中继续,直到没有能够抛出这个异常的块为止。当所有 的块都用尽了,PL/SQL就向执行最外层PL/SQL块的应用环境返回一个未处理异常。

    如果你使用了局部定义异常,你就应该提供一个针对该错误名的异常句柄。

    6.4.5 异常后继续

    你可以通过给任何语句加上一个BEGINning,之后加上一个EXCEPTION单元和END语句构建一个“虚拟块”出来。用这种方法,你可以通过在代码中构建匿名块的方式来控制异常引起的失败范围。

    6.4.6 WHEN OTHERS的处理代码

    在异常处理单元里包含WHEN OTHERS语句,可以捕获所有其他的未处理异常。因为你没有明确指出对某些特殊异常的处理,你可能需要利用内置异常函数比如SQLCODE和DBMSUTILITY.FORMATERROR_STACK获得发生的错误的信息。

  • 相关阅读:
    实验8 统计和输出一次考试中的最高分、最低分、平均分,以及在90~100、 80~89、 70~79、 60~69和60分以下各分数段的人数。程序代码如下(可复制):
    实验7(3)输入x后,根据下式计算并输出y值
    实验7
    实验7(4)编写程序,输入一批学生的成绩,遇0或负数则输入结束,要求统计并输出优秀(大于85)、通过(60~84)和不及格(小于60)的学生人数。
    输入n个字符
    实验6-1 输入n个整数,将它们存入数组a中。输出最大值和它所对应的下标
    作业3-5 输入五级制成绩(A-E),输出相应的百分制成绩(0-100)区间,要求使用 switch语句。例如,输入 A,输出 90-100。五级制成绩对应的百分制成绩区间为:A(90-100)、B(80-89)、C(70-79)、D(60-69)和 E(0-59)。
    作业3-6 查询水果的单价。有 4 种水果,苹果(apples)、梨(pears)、桔子(oranges)和葡萄(grapes),单价分别是 3.00 元/公斤,2.50 元/公斤,4.10 元/公斤和 10.20 元/公斤。在屏幕上显示以下菜单(编号和选项),用户可以连续查询水果的单价,当查询次数
    作业3-4 循环输入多个年份 year,判断该年是否为闰年。判断闰年的条件是:能被 4 整除但不能被100 整除,或者能被 400 整除。输入-1退出程序执行
    作业3-3 输入 15 个字符,统计其中英文字母、空格或回车、数字字符和其他字符的个数
  • 原文地址:https://www.cnblogs.com/tjpanda88/p/2285462.html
Copyright © 2020-2023  润新知