`
xiaoheliushuiya
  • 浏览: 401658 次
文章分类
社区版块
存档分类
最新评论

Oracle:pl/sql 异常处理

 
阅读更多
pl/sql 提供了强大而灵活的手段来捕捉和处理程序产生的异常,从而使 oracle 的用户远离一些令人烦恼的 bug 。
pl/sql 异常处理的概念和术语
在 oracle 中所有的错误都被认为是不应该发生的异常。一个异常可能是以下 3 种情况的一种:
u 由系统产生的错误(“ out of memory ”或“ duplicate value in index ”)
u 用户行为导致的错误
u 应用程序给用户的一个警告
pl/sql 用一种异常句柄的结构来捕捉和响应错误。正是有了异常句柄的存在,我们能很方便的分离异常处理代码与可执行代码。与线性的代码相比,为了处理异常,异常句柄提供了一种类似事件驱动的模式;换句话说,就是不管一种特定的错误在何时何地发生,它都将被同一个代码处理。
当一个错误出现后,无论它是系统还是程序产生的,都将导致一个异常。之后,可执行程序被中断,控制权转移给异常处理代码。处理完异常后,程序将不会回到先前被中断的位置,相反的,控制权被交给了当前程序的外围模块(可能是程序,也可能是系统)。
procedure jimmy
is
new_value varchar(35)
begin
|--------new_value:=old_value || ‘-new’;
| if new_value like ‘like%’
| then
| …..
| end if;
| exception
|----- à when value_error
then
…..
end;
因为 old_value 是一个未被定义的变量,所以将产生一个错误,并将给异常处理模块处理。
从异常的可应用范围出发,可将异常分为两类:
系统异常:
由 oracle 定义并由 pl/sql runtime 引擎在检测到错误时产生的异常。一些系统异常有名字,比如 NO_DATA_FOUND ,然而大多数的异常仅仅只有数字编号和描述。这些异常无论在哪个 pl/sql 中程序都能被应用。
共有 21 个命名的系统异常:
命名的系统异常
产生原因
ACCESS_INTO_NULL
未定义对象
CASE_NOT_FOUND
CASE 中若未包含相应的 WHEN ,并且没有设置 ELSE 时
COLLECTION_IS_NULL
集合元素未初始化
CURSER_ALREADY_OPEN
游标已经打开
DUP_VAL_ON_INDEX
唯一索引对应的列上有重复的值
INVALID_CURSOR
在不合法的游标上进行操作
INVALID_NUMBER
内嵌的 sql 语句不能将字符转换为数字
NO_DATA_FOUND
使用 select into 未返回行,或应用索引表未初始化的元素时
TOO_MANY_ROWS
执行 select iotn 时,返回超过一行
ZERO_DIVIDE
除数为 0
SUBSCRIPT_BEYOND_COUNT
元素下标超过嵌套表或 VARRAY 的最大值
SUBSCRIPT_OUTSIDE_LIMIT
使用嵌套表或 VARRAY 时,将下标指定为负数
VALUE_ERROR
赋值时,变量长度不足以容纳实际数据
LOGIN_DENIED
Pl/sql 应用程序连接到 oracle 数据库时,提供了不正确的用户名或密码
NOT_LOGGED_ON
Pl/sql 应用程序在没有连接 oralce 数据库的情况下访问数据
PROGRAM_ERROR
Pl/sql 内部问题,可能需要重装数据字典& pl./sql 系统包
ROWTYPE_MISMATCH
宿主游标变量与 pl/sql 游标变量的返回类型不兼容
SELF_IS_NULL
使用对象类型时,在 null 对象上调用对象方法
STORAGE_ERROR
运行 pl/sql 时,超出内存空间
SYS_INVALID_ID
无效的 ROWID 字符串
TIMEOUT_ON_RESOURCE
Oracle 在等待资源时超时
由程序员定义的异常:
程序员在程序中定义的异常,它只是在特定的程序种有效。可以使用 EXCEPTION_INT 这个 pragma 将一个无名字的系统异常与一个程序员定义的名字相关联。或者用 RAISE_APPLICATION_ERROE 来自己定义一个异常的数字编号和描述。
按异常生成方式可分为:
预定义异常:
就是上面表中的 21 种有名字的系统异常。
非预定义异常:
没名字的系统异常,可以用 pragma exception_int 给它关联一个名字。
自定义异常:
需要用 RAISE 或 RAISE_APPLICATION_ERROR 生成的异常。
下面是一些要用到的属于 ;
Exception section (异常处理模块)
它是 pl/sql 语句块种包含一个或多个异常句柄的部分。 Exception section 的结构基本上与 case 相似。
Raise (产生)
通过通知 pl/sql runtime 引擎有错误来中止当前程序的运行。也可通过显式的请求,如: RAISE 或 RAISE_APPLICATION_ERROR 来 RAISE 一个异常。
Handle (句柄,某一个异常处理的代码)
在 exception section 中捕捉错误。可以在 handle 中编写程序来处理异常,比如将错误记入 log 中,显示一个错误信息,将异常传出当前程序快。
Scope (作用范围 )
一个异常从产生、被捕捉到处理整个过程所处的程序部分。
Propagation (传递)
如果一个异常没有被处理,那么它将被传递到但前块的上一级,它有可能是另一个代码快,也可能是系统。
Unhandled exception (未被处理的异常)
如果一个异常没有被处理,并一直被传递道理系统中,那么它被称为 unhandled exception 。
Un-named or anonymous excepttion (匿名异常)
(在异常类型中有介绍)
Named exception (命名异常)
包括系统异常中有名字的那部分和用户定义的名字。
在一个异常产生、被捕获并处理之前,它必须被定义。 Oracle 定义了几千个异常,绝大多数只有错误编号和相关描述,仅仅命名了若干个最常被用到的异常。这些名字被储存在 STANDARD , UTL_FILE , DBMS_SQL 这几个系统包中,详情请见 oracle:pl/sql 异常处理( 1 )。
出自之外的绝大多数异常需要程序员命名。有 2 种命名异常的方法:
1 :声明一个自定义异常
在 STANDARD 中的命名了的异常基本山是与系统的错误相关的(当然那些只有 errorcode 的异常也是这样),但在实际的应用中我们经常需要与特定的应用程序相关的异常,由程序员声明的异常就是用于处理这种情况的。
Oracle 异常处理模块的方便的地方在于,它并没有区别对待自定义的与预定义的异常。这使得我们可以像对待预定义异常一样,捕捉和处理自定义异常,只是在此之前需要声明它;同时对于一个自定义的异常,我们需要用 RAISE 来手动产生。
下面是一个声明的例子:
procedure calc_ammul_sales
(company_id_in in company.company_id%tye)
is
invalid_company_id exception;
negative_balance excrption;
duplicate_company Boolean;
begin
/*body of executable statement*/
exception
when invalid_company_id
then /*handle exception*/
when no_data_found
then /*handle exception*/
/*…..*/
end;
需要注意的是处理定义的时候,只有两个地方会出现自定义的异常:
ü raise exception ;
ü when exception then
2 :为非预定义异常关联一个名字
仅仅 21 个预定义异常对我们来说实在是太少了,还有几千个异常只有 errorcode 和描述。另外,程序员也可以用 RAISE_APPLICATION_ERROR 定义一个含 errorcode 和描述的异常。
当然,只用 errorcode 也可以很好地完成工作,只要你不担心会忘了那串数字代表的意思就行。比方说 ;
exception
when others
then
if sqlcode=-1843 then/*sqlcode 是内建的用于返回最近一次错误编号的函数 */
…..
这的确是一段让人感到晦涩的代码,还是给它关联个名字吧。
我们要用到的是 pragma exception_init(exception,integer) ,然后就可以像对待预定义异常一样对待它了,我是说没必要像上面的那种一样用 raise 。 Exception_init 是一个编译时运行的函数,它只能出现在代码的声明部分,而异常名字必须在此之前被定义。下面用一个匿名过程举个例子:
declare
invalid_company_id exception;
pragma exception_init(invalid_company_id, -1834);
要注意的时:
ü 不可以用 -1403 ( no_data_found ),用 100 ,事实上 exception_init 中的 integer 对应的是 sqlcode 返回的值。
ü 不能为 0 ,不能大于 100 ,不能小于 -1000000
一个例子:
procedure delete_company(company_id_in in number)
is
still_have_emplyee exception;
pragma exception(still_have_employee, -2293);
begin
delete from compamy
where company_id=company_id_in;
exception
when still_have_employee
then dbms_output.put_line(‘delete employees for company first’);
end;
在一下两种情况下,我们有必要使用 exception_init :
ü 一个非预定义异常是经常要被用到的。
ü 我们将用 raise_applocation_error 产生了一个自定义的 errorcode 时。
一种简便的方法是将以上两种情况中的异常定义在一个包中,这样我们就没有必要每次都重复定义了。
Create or replace package dynsql
Is
Invalid_table_name exception;
Pragma exception_init(invalid_table_name, -903);
Invalid_column_name exception;
Pragma exception_init(invalid_column_name, -904);
En_too_young const number:=-200001;
Exc_too_young exception;
Pragma exception_init(exc_too_young, -20001);
End;
有了上面这个包,就可以方便的处理异常了 ;
procedure validate_emp(birthdate in date)
is
min_tear const pls_integer:=18;
begin
if add_month(sysdate,min_year*12*-1)<birthdate_in
then
raise_application_error(dynsql.en_too_young, ‘employee must be’ || min_year ||‘old’);
end if;
end;
除了 standard 包中的 21 个预定义异常外,还有一些包也定义了一些异常。但与 standard 包中异常不同的是,在使用这些异常时,需要带上包的名字。如:
when dbms_lob.invalid_argval then ……
非常有用的一点是,可以在最外层的 pl/sql 块的异常处理模块中加入 others ,这样就可以把从内部传递出来的未被处理的剩余异常全部处理掉了。
Exception
When others
Then ….
分享到:
评论

相关推荐

    oracle 9i pl/sql程序设计笔记

    oracle 9i pl/sql程序设计笔记。

    oracle Database 11g :PL/SQL

    oracle Database 11g :PL/SQL

    Oracle PL/SQL程序设计(第5版)(套装上下册)

    《Oracle PL/SQL程序设计(第5版)(套装上下册)》基于Oracle数据库11g,从PL/SQL编程、PL/SQL程序结构、PL/SQL程序数据、PL/SQL中的SQL、PL/SQL应用构建、高级PL/SQL主题这6个方面详细系统地讨论了PL/SQL以及如何...

    Oracle PL/SQL实战(待续)

    NULL 博文链接:https://elf8848.iteye.com/blog/740881

    oracle10g_pl/sql

    oracle10g pl/sql完备教程,供初学者学习与开发者参考

    Oracle PL/SQL语言初级教程

    PL/SQL是Oracle对标准数据库语言的扩展,Oracle公司已经将PL/SQL整合到Oracle 服务器和其他工具中了,近几年中更多的开发人员和DBA开始使用PL/SQL,本教程将以循速渐进的方式讲述PL/SQL基础语法,结构和组件、以及...

    Oracle 12c PL/SQL程序设计终极指南

    本书以Oracle的最新版本12c为基础,呈现的是最新的PL/SQL技术,这一点也优于已出版的同类书.全书以一个综合性的人力资源项目为驱动,不仅能将各个理论知识点很好地融入实践,而且还能让读者体验完整的项目实操过程...

    Oracle Advanced PL/SQL Developer Professional Guide

    集合,外部过程,服务器端结果缓存,使用VPD强制行级安全性,处理大型对象和SecureFiles等功能为PL / SQL专业人员构建了一个具体平台。除了编程之外,本书还提供了有关开发工具SQL Developer的使用的工具建议,采用...

    Oracle PL/SQL实例编程(PL/SQL经典书籍)

    Oracle PL/SQL实例编程 Oracle PL/SQL实例编程 Oracle PL/SQL实例编程

    Oracle PL/SQL实例精解 数据库建立代码

    Oracle PL/SQL实例精解 student模式 数据库建立代码 包括数据库的建立、索引等。样本数据的插入。

    Oracle PL/SQL programming(5th Edition)

    Topics covered: How to use Oracle PL/SQL in all its manifestations through Oracle9i. Fundamentals of program structure (loops, cases, exceptions, etc.) and execution get attention, as do data types, ...

    Oracle8i PL/SQL高级程序设计 高清晰版

    共分为7部分(7个pdf文档...第一部分:PL/SQL介绍及开发环境 1.PL/SQL介绍 2.PL/SQL开发和运行环境 3.跟踪和调试 第二部分:非对象功能 4.创建子程序和包 5.使用子程序和包 6.数据库触发器 7.数据库作业和文件输入输出

    精通Oracle_PL/SQL

    全书涵盖了 PL/SQL提供的大量功能,包括高效数据处理、安全、触发器、DBA包以及高效的调试技术等。此外,书中含有丰富的示例,并提供了大量提示和技巧。《精通Oracle PL/SQL》结构清晰,示例丰富,实践性强,适用于 ...

    Oracle9i PL/SQL程序设计

    权威PL/SQL语言参考书

    Oracle PL/SQL programming

    Considered the best Oracle PL/SQL programming guide by the Oracle community, this definitive guide is precisely what you need to make the most of Oracle’s powerful procedural language. The sixth ...

    oracle PL/SQL pdf学习资料

    oracle PL/SQL pdf学习资料oracle PL/SQL pdf学习资料oracle PL/SQL pdf学习资料oracle PL/SQL pdf学习资料oracle PL/SQL pdf学习资料

    oracle 中 pl/sql 只是学习方法

    oracle 中 pl/sql 只是学习方法,喜欢 oracle 的朋友都下了看看吧

    Oracle PL/SQL程序设计(第5版)(下册)第二部分

    《Oracle PL/SQL程序设计(第5版)》基于Oracle数据库11g,从PL/SQL编程、PL/SQL程序结构、PL/SQL程序数据、PL/SQL中的SQL、PL/SQL应用构建、高级PL/SQL主题这6个方面详细系统地讨论了PL/SQL以及如何有效地使用它。...

    Oracle PL SQL程序设计 上 第五版(代码示例)

    《oracle pl/sql程序设计(第5版)》基于oracle数据库11g,从pl/sql编程、pl/sql程序结构、pl/sql程序数据、pl/sql中的sql、pl/sql应用构建、高级pl/sql主题6个方面详细系统地讨论了pl/sql以及如何有效地使用它。...

    oracle pl/sql实例精讲student数据库模式数据和表脚本

    oracle pl/sql实例精讲student数据库模式

Global site tag (gtag.js) - Google Analytics