zoukankan      html  css  js  c++  java
  • Oracle异常处理

    即使是写得最好的PL/SQL程序也会遇到错误或未预料到的事件。一个优秀的程序都应该能够正确处理各种出错情况,并尽可能从错误中恢复。任何ORACLE错误(报告为ORA-xxxxx形式的Oracle错误号)、PL/SQL运行错误或用户定义条件(不一写是错误)都可以。当然了,PL/SQL编译错误不能通过PL/SQL异常处理来处理,因为这些错误发生在PL/SQL程序执行之前。

    ORACLE 提供异常情况(EXCEPTION)和异常处理(EXCEPTION HANDLER)来实现错误处理。

    1 .异常的概念

    在设计或运行一个程序时,常出现这样或那样的错误。针对这类错误,采取相应的措施。这就是异常处理(EXCEPTION)

    异常处理就是针对系统中发生的各种错误所采取的处理措施,也叫例外.

    1、异常的定义格式:

    BEGIN
    …;
    EXCEPTION
      WHEN 异常情况 1[ OR 异常情况 2 …] THEN
         …;
      WHEN 异常情况 3[ OR 异常情况 4 …] THEN
        …;
      WHEN OTHERS THEN
    …;
    END

    说明:

    • 在块中开始一个出错处理部分必须以关键子EXCEPTION开始;
    • 将WHEN OTHERS 子句放置在所有其他出错处理子句的后面。最多只能有一个WHEN OTHERS 子句;
    • 可以在块中定义多个句柄(HANDLER),每个句柄包含一组语句;
    • 当一个错误发生时,在离开块之前,PL/SQL只处理一个句柄

    2、异常的类型

    oracle预定义的异常
    oracle预定义的异常,当这些异常情况发生时,系统可捕获异常并在程序中根据异常名称对程序进行异常处理。
    Oracle非预定义的异常
    是其他标准的Oracle错误。对这种异常情况的处理,需要用户在PL/SQL块的declare部分中定义,并在异常触发后对其处理。
    用户自定义的异常
    是由程序员根据逻辑规则定义的一些异常并对它进行处理。
    注意:ORACLE预定义异常和非预定义异常都是由ORACLE进行判断错误

    2.Oracle预定义的异常处理

    ORACLE错误

    对应的错误名

    描述

    ORA_00001

    DUP_VAL_ON_INDEX

    试图通过一个重复值更新或插入一条语句,即违反了唯一性约束

    ORA_00051

    TIMEOUT_ON_RESOURCE

    在等待资源时发生超时现象,例如DDL操作加的排他表级锁

    ORA_01001

    INVALID_CURSOR

    非法的游标操作,例如游标在没有打开时执行FETCH操作

    ORA_01522

    INVALID_NUMBER

    字符串向数字转换失败,即有个无效字符

    ORA_01012

    NO_LOGGED_ON

    在没有连接到ORACLE之前,对数据库进行调用

    ORA_01015

    LOGIN_DENIED

    在连接中提供了无效的用户名/口令

    ORA_01403

    NO_DATA_FOUND

    执行SELECT语句未查询到数据

    ORA_01410

    SYS_INVALID_ROWID

    一个隐式的CHARTOROWID转换时,包含了无效的字符或格式

    ORA_01422

    TOO_MANY_ROWS

    未使用游标,SELECT语句返回了多行数据

    ORA_06502

    VALUE_ERROR

    由于长度类型不合适,出现数字、数据转换、字符串或限制型错误

    ORA_01456

    ZERO_DIVIDE

    被零除

    ORA_06500

    STORAGE_ERROR

    如果PL/SQL运行时内存被破坏或不够就会引发内部的PL/SQL错误

    ORA_06501

    PROGRAM_ERROR

    内部的PL/SQL错误

    ORA_06504

    ROWTYPE_MISMATCH

    游标变量和PL/SQL结果集之间数据类型不匹配

    ORA_06511

    CURSOR_ALREADY_OPEN

    试图打开一个已经打开的游标

    ORA_06530

    ACCESS_INTO_NULL

    参考了没有初始化的数据库对象、LOB或其他非集合的符合类型(即这些对象的值都是NULL)

    ORA_06531

    COLLECTION_IS_NULL

    参考了没有初始化的嵌套表或VARRAY集合中的元素、或调用了没有初始化的集合方法

    ORA_06532

    SUBSCRIPT_OUTSIDE_LIMIT

    使用了一个下标比VARRAY边界值高的云素

    ORA_06533

    SUBSCRIPT_BEYOND_COUNT

    使用了一个比嵌套表或VARRAY初始化元素个数多的元素

     注:红色是比较常用到的

    对这种异常情况的处理,只需在PL/SQL块的异常处理部分,直接引用相应的异常情况名,并对其完成相应的异常错误处理即可。

    例1:对异常DUP_VAL_ON_INDEX的捕获及处理.向产品表中插入一条记录,当主键值重复时,输出该记录的主键值已经存在.

    BEGIN
         INSERT INTO products(productid,productname)
         values(&prodid,’&prodname’);
      EXCEPTION
        WHEN DUP_VAL_ON_INDEX THEN
          dbms_output.put_line('该主键值已存在');
        WHEN OTHERS THEN
          dbms_output.put_line(‘其他错误');
     END;

    例2:对异常NO_DATA_FOUND和TOO_MANY_ROWS的捕获及处理.
    查询某类别的产品信息,如不存在则显示异常’没有找到该产品’,如查到多行则显示异常‘查找到多个产品’,如只查到一行则显示产品编号、名称、单价

    DECLARE
       rec_prod  products%rowtype;
    BEGIN
       SELECT * INTO rec_prod  FROM products
       WHERE categoryid=&cateid;   
          dbms_output.put_line('产品编号'||rec_prod.productid);
          dbms_output.put_line('产品名称'||rec_prod.productname);
          dbms_output.put_line('产品单价'||rec_prod.unitprice);
     EXCEPTION
        WHEN NO_DATA_FOUND THEN
          dbms_output.put_line('没有找到该产品');
       WHEN TOO_MANY_ROWS THEN
          dbms_output.put_line('查找到多个产品');
     END;

    3 . 非预定义的Oracle异常

     要使用非预定义的Oracle异常,则用户必须首先进行定义。步骤如下:
    (1)在PL/SQL块的declare定义部分定义异常名:
    <exception_name>  EXCEPTION;
    (2)使用pragma exception_init语句,将其定义好的异常名与标准的Oracle错误编号联系起来:
    pragma  exception_init(<exception_name >, <handle_code>);
    (3)在PL/SQL块异常的处理部分对异常情况做出相应的处理。
    例3:定义一个非预定义异常,对删除产品表中产品编号为1的产品的异常进行异常处理

    DECLARE
        Fk_delete  EXCEPTION;
        PRAGMA EXCEPTION_INIT (Fk_delete ,-2292);
    BEGIN
        DELETE products WHERE productid=1;              
     EXCEPTION
    WHEN Fk_delete   THEN
           dbms_output.put_line(‘在另一个表中引用了该记录’);
    WHEN others  THEN
           dbms_output.put_line(‘其它错误’||sqlcode);
          END;

    例4:向产品表中插入一条记录,当主键重复时,输出’该主键值已存在’, 当产品名为空时,输出’违反了非空约束

     DECLARE
        Name_null EXCEPTION;
       PRAGMA exception_init(name_null, -1400);
    BEGIN
         INSERT INTO products(productid,productname)
         values(&prodid,’&prodname’);
      EXCEPTION
        WHEN DUP_VAL_ON_INDEX THEN
          dbms_output.put_line('该主键值已存在');
        WHEN Name_null THEN
          dbms_output.put_line('违反了非空约束');
    END;

    4. 用户自定义的异常

    当与一个异常错误相关的错误出现时,就会隐含触发该异常错误。用户定义的异常错误是通过显式使用 RAISE 语句来触发。当引发一个异常错误时,控制就转向到 EXCEPTION块异常错误部分,执行错误处理代码。

    用户自定义异常的处理步骤

     例5:对产品表中单价小于等于3元的产品的打折状态更新为1.如果没有找到这样的产品则触发用户自定义异常,并提示”未找到相应产品”,否则显示更新了几条信息.

    DECLARE
        prod_excep EXCEPTION;
    BEGIN
       UPDATE products SET Discontinued=1WHERE unitprice<=3;
       IF sql%notfound THEN RAISE prod_excep;
       ELSE
         dbms_output.put_line(‘更新了’||sql%rowcount||’条记录’);
       END IF;
    EXCEPTION
       WHEN prod_excep THEN
           dbms_output.put_line(‘未找到相应产品’);
    END;  

     5.三种异常的简单比较

    异常

    描 述

    处理方向

    系统预定义的异常

    在PL/SQL中经常出现的25个系统定义错误

    不必定义,允许服务器隐式地触发它们

    用户自定义的异常

    开发者认为是非正确的一个条件

    必须在说明部分定义,并且显示地触发它们

    非预定义的系统异常

    任何其他(25个以外的)服务器产生的标准错误

    必须在说明部分定义,并且允许服务器隐式地触发它们

  • 相关阅读:
    理解C#中的 async await
    kube-proxy IPVS 模式的工作原理
    Kilo 使用教程
    Wireguard 全互联模式(full mesh)配置指南
    我为什么不鼓吹 WireGuard
    iTerm2 实现 ssh 自动登录,并使用 Zmodem 实现快速传输文件
    在 Docker Desktop 中启用 K8s 服务
    ABP 适用性改造
    ABP 适用性改造
    在 ASP.NET Core 应用中使用 Cookie 进行身份认证
  • 原文地址:https://www.cnblogs.com/CX66/p/14056806.html
Copyright © 2011-2022 走看看