`
SScola
  • 浏览: 4576 次
  • 性别: Icon_minigender_1
  • 来自: 北京
最近访客 更多访客>>
社区版块
存档分类
最新评论

Oracle存储过程异常处理总结

    博客分类:
  • ETL
阅读更多

1、异常的优点 

   
  如果没有异常,在程序中,应当检查每个命令的成功还是失败,如 
  BEGIN 
  SELECT ... 
  -- check for ’no data found’ error 
  SELECT ... 
  -- check for ’no data found’ error 
  SELECT ... 
  -- check for ’no data found’ error 
  这种实现的方法缺点在于错误处理没有与正常处理分开,可读性差,使用异常,可以方便处理错误,而且异常处理程序与正常的事务逻辑分开,提高了可读性,如 
  BEGIN 
  SELECT ... 
  SELECT ... 
  SELECT ... 
  ... 
  EXCEPTION 
  WHEN NO_DATA_FOUND THEN -- catches all ’no data found’ errors 
   
  2、异常的分类 
   
  有两种类型的异常,一种为内部异常,一种为用户自定义异常,内部异常是执行期间返回到PL/SQL块的ORACLE错误或由PL/SQL代码的某操作引起的错误,如除数为零或内存溢出的情况。用户自定义异常由开发者显示定义,在PL/SQL块中传递信息以控制对于应用的错误处理。 
   
  每当PL/SQL违背了ORACLE原则或超越了系统依赖的原则就会隐式的产生内部异常。因为每个ORACLE错误都有一个号码并且在PL/SQL中异常通过名字处理,ORACLE提供了预定义的内部异常。如SELECT INTO 语句不返回行时产生的ORACLE异常NO_DATA_FOUND。对于预定义异常,现将最常用的异常列举如下: 
  exception  oracle error  sqlcode value  condition 
  no_data_found              ora-01403  +100  select into 语句没有符合条件的记录返回 
  too_many_rows  ora-01422  -1422  select into 语句符合条件的记录有多条返回 
  dup_val_on_index  ora-00001  -1  对于数据库表中的某一列,该列已经被限制为唯一索引,程序试图存储两个重复的值 
  value_error  ora-06502  -6502  在转换字符类型,截取或长度受限时,会发生该异常,如一个字符分配给一个变量,而该变量声明的长度比该字符短,就会引发该异常 
  storage_error  ora-06500  -6500  内存溢出 
  zero_divide  ora-01476  -1476  除数为零 
  case_not_found  ora-06592  -6530  对于选择case语句,没有与之相匹配的条件,同时,也没有else语句捕获其他的条件 
  cursor_already_open  ora-06511  -6511  程序试图打开一个已经打开的游标 
  timeout_on_resource  ora-00051  -51  系统在等待某一资源,时间超时 
   
  如果要处理未命名的内部异常,必须使用OTHERS异常处理器或PRAGMA EXCEPTION_INIT 。PRAGMA由编译器控制,或者是对于编译器的注释。PRAGMA在编译时处理,而不是在运行时处理。EXCEPTION_INIT告诉编译器将异常名与ORACLE错误码结合起来,这样可以通过名字引用任意的内部异常,并且可以通过名字为异常编写一适当的异常处理器。 
在子程序中使用EXCEPTION_INIT的语法如下: 
  PRAGMA EXCEPTION_INIT(exception_name, -Oracle_error_number); 
   
  在该语法中,异常名是声明的异常,下例是其用法: 
  DECLARE 
  deadlock_detected EXCEPTION; 
  PRAGMA EXCEPTION_INIT(deadlock_detected, -60); 
  BEGIN 
  ... -- Some operation that causes an ORA-00060 error 
  EXCEPTION 
  WHEN deadlock_detected THEN 
  -- handle the error 
  END; 
   
  对于用户自定义异常,只能在PL/SQL块中的声明部分声明异常,异常的名字由EXCEPTION关键字引入: 
  reserved_loaned Exception 
   
  产生异常后,控制传给了子程序的异常部分,将异常转向各自异常控制块,必须在代码中使用如下的结构处理错误: 
  Exception 
  When exception1 then 
  Sequence of statements; 
  When exception2 then 
  Sequence of statements; 
  When others then 
   
  3、异常的抛出 
   
  由三种方式抛出异常 
   
  1. 通过PL/SQL运行时引擎 
   
  2. 使用RAISE语句 
   
  3. 调用RAISE_APPLICATION_ERROR存储过程 
   
  当数据库或PL/SQL在运行时发生错误时,一个异常被PL/SQL运行时引擎自动抛出。异常也可以通过RAISE语句抛出 
  RAISE exception_name; 
   
  显式抛出异常是程序员处理声明的异常的习惯用法,但RAISE不限于声明了的异常,它可以抛出任何任何异常。例如,你希望用TIMEOUT_ON_RESOURCE错误检测新的运行时异常处理器,你只需简单的在程序中使用下面的语句: 
  RAISE TIMEOUT_ON_RESOUCE; 
   
  比如下面一个订单输入的例子,若当订单小于库存数量,则抛出异常,并且捕获该异常,处理异常 
  DECLARE 
  inventory_too_low EXCEPTION; 
   
  ---其他声明语句 
  BEGIN 
  IF order_rec.qty>inventory_rec.qty THEN 
  RAISE inventory_too_low; 
  END IF 
  EXCEPTION 
  WHEN inventory_too_low THEN 
  order_rec.staus:='backordered'; 
  END; 
   
  RAISE_APPLICATION_ERROR内建函数用于抛出一个异常并给异常赋予一个错误号以及错误信息。自定义异常的缺省错误号是+1,缺省信息是User_Defined_Exception。RAISE_APPLICATION_ERROR函数能够在pl/sql程序块的执行部分和异常部分调用,显式抛出带特殊错误号的命名异常。  Raise_application_error(error_number,message[,true,false])) 
   
  错误号的范围是-20,000到-20,999。错误信息是文本字符串,最多为2048字节。TRUE和FALSE表示是添加(TRUE)进错误堆(ERROR STACK)还是覆盖(overwrite)错误堆(FALSE)。缺省情况下是FALSE。 
如下代码所示: 
  IF product_not_found THEN 
  RAISE_APPLICATION_ERROR(-20123,'Invald product code' TRUE); 
  END IF; 
   
  4、异常的处理 
   
  PL/SQL程序块的异常部分包含了程序处理错误的代码,当异常被抛出时,一个异常陷阱就自动发生,程序控制离开执行部分转入异常部分,一旦程序进入异常部分就不能再回到同一块的执行部分。下面是异常部分的一般语法: 
  EXCEPTION 
  WHEN exception_name THEN 
  Code for handing exception_name 
  [WHEN another_exception THEN 
  Code for handing another_exception] 
  [WHEN others THEN 
  code for handing any other exception.] 
   
  用户必须在独立的WHEN子串中为每个异常设计异常处理代码,WHEN OTHERS子串必须放置在最后面作为缺省处理器处理没有显式处理的异常。当异常发生时,控制转到异常部分,ORACLE查找当前异常相应的WHEN..THEN语句,捕捉异常,THEN之后的代码被执行,如果错误陷阱代码只是退出相应的嵌套块,那么程序将继续执行内部块END后面的语句。如果没有找到相应的异常陷阱,那么将执行WHEN OTHERS。在异常部分WHEN 子串没有数量限制。 
  EXCEPTION 
  WHEN inventory_too_low THEN 
  order_rec.staus:='backordered'; 
  replenish_inventory(inventory_nbr=> 
  inventory_rec.sku,min_amount=>order_rec.qty-inventory_rec.qty); 
  WHEN discontinued_item THEN 
  --code for discontinued_item processing 
  WHEN zero_divide THEN 
  --code for zero_divide 
  WHEN OTHERS THEN 
  --code for any other exception 
  END; 
   
  当异常抛出后,控制无条件转到异常部分,这就意味着控制不能回到异常发生的位置,当异常被处理和解决后,控制返回到上一层执行部分的下一条语句。 
  BEGIN 
  DECLARE 
  bad_credit exception; 
  BEGIN 
  RAISE bad_credit; 
  --发生异常,控制转向; 
  EXCEPTION 
  WHEN bad_credit THEN 
  dbms_output.put_line('bad_credit'); 
  END; 
  --bad_credit异常处理后,控制转到这里 
  EXCEPTION 
  WHEN OTHERS THEN 
   
  --控制不会从bad_credit异常转到这里 
   
  --因为bad_credit已被处理 
   
  END; 
   
  当异常发生时,在块的内部没有该异常处理器时,控制将转到或传播到上一层块的异常处理部分。 
   
  BEGIN 
  DECLARE ---内部块开始 
   
  bad_credit exception; 
  BEGIN 
 RAISE bad_credit; 
   
  --发生异常,控制转向; 
  EXCEPTION 
  WHEN ZERO_DIVIDE THEN --不能处理bad_credite异常 
  dbms_output.put_line('divide by zero error'); 
   
  END --结束内部块 
   
  --控制不能到达这里,因为异常没有解决; 
   
  --异常部分 
   
  EXCEPTION 
  WHEN OTHERS THEN 
  --由于bad_credit没有解决,控制将转到这里 
  END; 
   
  5、异常的传播 
   
  没有处理的异常将沿检测异常调用程序传播到外面,当异常被处理并解决或到达程序最外层传播停止。在声明部分抛出的异常将控制转到上一层的异常部分。 
   
  BEGIN 
  executable statements 
  BEGIN 
  today DATE:='SYADATE'; --ERRROR 
   
  BEGIN --内部块开始 
  dbms_output.put_line('this line will not execute'); 
  EXCEPTION 
  WHEN OTHERS THEN 
   
  --异常不会在这里处理 
   
  END;--内部块结束 
  EXCEPTION 
  WHEN OTHERS THEN 
   
  处理异常 
   
  END 
-------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------
 
Oracle:pl/sql异常处理 (3)
 
处理 oracle 系统自动生成系统异常外,可以使用 raise 来手动生成错误。
l         Raise exception;
  End;
这是一个生成自定义异常的例子,当然也可以生成系统异常:
       declare
              employee_id_in number;
       Begin
Select employee_id into employee_id_in from employ_list where employee_name=&n;
If employee_id_in=0
Then
       Raise zero_devided;
End if;
       Exception
              When zero_devided
              Then
                     Dbms_output.put_line(‘wrong!’);
       End;
有一些异常是定义在非标准包中的,如 UTL_FILE , DBMS_SQL 以及程序员创建的包中异常。可以使用 raise 的第二种用法来生成异常。
       If day_overdue(isbn_in, browser_in) > 365
       Then
              Raise overdue_pkg.book_is_lost
       End if;
在最后一种 raise 的形式中,不带任何参数。这种情况只出现在希望将当前的异常传到外部程序时。
       Exception
              When no_data_found
              Then
                     Raise;
       End;
 
Pl.sql 使用 raise_application_error 过程来生成一个有具体描述的异常。当使用这个过程时,当前程序被中止,输入输出参数被置为原先的值,但任何 DML 对数据库所做的改动将被保留,可以在之后用 rollback 命令回滚。下面是该过程的原型:
       Procedure raise_application_error(
       Num binary_integer;
       Msg varchar2;
       Keeperrorstack Boolean default false
)
其中 num 是在 -20999 到 -20000 之间的任何数字(但事实上, DBMS_OUPUT 和 DBMS_DESCRIBLE 包使用了 -20005 到 -20000 的数字); msg 是小于 2K 个字符的描述语,任何大于 2K 的字符都将被自动丢弃; keeperrorstack 默认为 false ,是指清空异常栈,再将当前异常入栈,如果指定 true 的话就直接将当前异常压入栈中。
    CREATE OR REPLACE PROCEDURE raise_by_language (code_in IN PLS_INTEGER)
    IS
       l_message error_table.error_string%TYPE;
    BEGIN
       SELECT error_string
         INTO l_message
         FROM error_table, v$nls_parameters v
        WHERE error_number = code_in
          AND string_language = v.VALUE
 AND v.parameter = 'NLS_LANGUAGE';
 
       RAISE_APPLICATION_ERROR (code_in, l_message);
    END;
l         Raise package.exception;
 
l         Raise;
 
以上是 raise 的三种使用方法。第一种用于生成当前程序中定义的异常或在 standard 中的系统异常。
       Declare
              Invalid_id exception;
              Id_values varchar(2);
       Begin
              Id_value:=id_for(‘smith’);
              If substr(id_value,1,1)!=’x’
              Then
                     Raise invalid_id;
              End if;
       Exception
              When invalid_id
              Then
                     Dbms_output.put_line(‘this is an invalid id!’);
分享到:
评论

相关推荐

    oracle 转mysql项目总结

    (主要分事务处理,游标处理,存储过程方法调用,数组处理,异常处理等。) (2)oracle与mysql区别比较。 (主要包含:语法及结构区别,函数区别,数据类型区别等。) (3)ORACLE与MYSQL常用函数对比。

    oracle所有知识点笔记(全)

    基本的sql语法,触发器,存储过程,存储函数, 流程控制,游标,异常处理,记录类型,视图, 控制用户权限,高级子查询,set运算符, 基本的sql_Select语句 运算符,多表联查,排序,组函数,序列,索引,同义词, ...

    Oracle 10g应用指导

    介绍了PL/SQL中常用的函数、异常处理等,还有对随机数生成、分析函数、多表合并、多表插入等问题的解决方法。第7章 子程序和触发器,包括函数、存储过程、包以及触发器等。对子程序的调用者权限、管道表函数、传递...

    oracle实验报告

    2、 定义一个为修改职工表(emp)中某职工工资的存储过程子程序,职工名作为形参,若该职工名在职工表中查找不到,就在屏幕上提示“查无此人”然后结束子程序的执行;否则若工种为MANAGER的,则工资加$1000;工种为...

    Oracle+10g应用指导与案例精讲

    介绍了PL/SQL中常用的函数、异常处理等,还有对随机数生成、分析函数、多表合并、多表插入等问题的解决方法。第7章 子程序和触发器,包括函数、存储过程、包以及触发器等。对子程序的调用者权限、管道表函数、传递...

    2021 云和恩墨大讲堂PPT汇总(50份).zip

    Oracle存储过程性能分析案例 Oracle技术加油站:快速处理紧急性能问题的工具与经验 Oracle诊断性能问题时常用脚本工具 PostgreSQL日常工作分享 PostgreSQL实践分享 wls、was中间件故障基本分析介绍

    深入解析Oracle.DBA入门进阶与诊断案例

    附录 数值在Oracle的内部存储 344 第8章 回滚与撤销 347 8.1 什么是回滚和撤销 347 8.2 回滚段存储的内容 348 8.3 并发控制和一致性读 349 8.4 回滚段的前世今生 350 8.5 Oracle 10g的UNDO_RETENTION...

    PL/SQL 详解

    ORACLE 学习文档,总结,囊括常用过程,函数,游标,异常处理。。。,非常实用

    SQL21日自学通

    存储过程包和触发机制403 总结406 问与答407 校练场407 练习407 第19 天TRANSACT-SQL 简介408 目标408 TRANSACT-SQL 概貌408 对ANSI SQL 的扩展408 谁需要使用TRANSACT-SQL409 TRANSACT-SQL 的基本组件409 数据...

    java 面试题 总结

    finally是异常处理语句结构的一部分,表示总是执行。 finalize是Object类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法,可以覆盖此方法提供垃圾收集时的其他资源回收,例如关闭文件等。 13、sleep()...

    asp.net知识库

    发布Oracle存储过程包c#代码生成工具(CodeRobot) New Folder XCodeFactory3.0完全攻略--序 XCodeFactory3.0完全攻略--基本思想 XCodeFactory3.0完全攻略--简单示例 XCodeFactory3.0完全攻略--IDBAccesser ...

    大数据PPT材料.docx

    在中国市场,工信部发布的物联网"十二五"规划上,把信息处理技术作为4项关键技术创新工程之一提出来,其中包括了海量数据存储、数据挖掘、图像视频智能分析,这都是大数据的重要组成部分。而另外 3 项关键技术创新...

    Java JDK 7学习笔记(国内第一本Java 7,前期版本累计销量5万册)

    chapter8 异常处理 231 8.1 语法与继承架构 232 8.1.1 使用try、catch 232 8.1.2 异常继承架构 235 8.1.3 要抓还是要抛 238 8.1.4 认识堆栈追踪 241 8.1.5 关于assert 245 8.2 异常与资源管理 247 ...

    亮剑.NET深入体验与实战精要2

    1.6.5 错误异常处理方法 70 本章常见技术面试题 76 常见面试技巧之面试前的准备 76 本章小结 77 第2章 细节决定成败 79 2.1 Equals()和运算符==的区别 80 2.2 const和readonly的区别 82 2.3 private、protected、...

    亮剑.NET深入体验与实战精要3

    1.6.5 错误异常处理方法 70 本章常见技术面试题 76 常见面试技巧之面试前的准备 76 本章小结 77 第2章 细节决定成败 79 2.1 Equals()和运算符==的区别 80 2.2 const和readonly的区别 82 2.3 private、protected、...

    Spring中文帮助文档

    处理复杂类型的存储过程调用 12. 使用ORM工具进行数据访问 12.1. 简介 12.2. Hibernate 12.2.1. 资源管理 12.2.2. 在Spring容器中创建 SessionFactory 12.2.3. The HibernateTemplate 12.2.4. 不使用回调的...

    Spring API

    处理复杂类型的存储过程调用 12. 使用ORM工具进行数据访问 12.1. 简介 12.2. Hibernate 12.2.1. 资源管理 12.2.2. 在Spring容器中创建 SessionFactory 12.2.3. The HibernateTemplate 12.2.4. 不使用回调的...

    工程硕士学位论文 基于Android+HTML5的移动Web项目高效开发探究

    目前市场业务中在产品以及其他项目的认证和检测方面存在诸多不便,用户需要实地考察并频繁与检测单位沟通,填写繁琐的纸质检测报告、当面送递样品,对于检测环节中存在的问题难以及时交互并处理。市场上相应的检测...

    Java面试宝典2010版

    45、JAVA语言如何进行异常处理,关键字:throws,throw,try,catch,finally分别代表什么意义?在try块中可以抛出异常吗? 29 46、java中有几种方法可以实现一个线程?用什么关键字修饰同步方法? stop()和suspend()方法...

Global site tag (gtag.js) - Google Analytics