Oracle系列之四——异常处理

Oracle系列之四——异常处理

为什么使用异常处理?每个程序员都知道的答案。Pl/sql也不例外,为了提高程序的健壮性,开发人员必须对相应的异常进行处理。

不过在oracle中,一般不叫异常,而是叫例外。

Oracle提供了预定义例外、非预定义例外、自定义例外三种类型。其中,预定义例外用于处理常见的Oracle错误;非预定义例外则用于处理预定义例外所不能处理的ORACLE错误;自定义例外则用于处理与ORACLE错误无关的其他情况。

 

开发人员应该在可能发生例外的地方捕捉例外,如果没有捕捉到,例外则会传递到调用环境。

在PL/SQL块中捕捉并处理例外需要使用例外处理部分来完成,例外处理部分是以关键字EXCEPTION开始的,语法如下:

Exception

When exception1 [ or exception2 ]then

Statement1;

Statement2;

When exception3 [ or exception4 ] then

Statement1;

Statement2;

When others then

Statement1;

如上,例外处理程序以EXCEPTION开始,在例外处理部分用WHEN子句来捕捉各种例外,如果还有其它预计不到的例外,可以使用when others子名来进行捕捉和处理。

 

  1. 处理预定义例外。

    预定义例外是PL/SQL所提供的系统例外。当PL/SQL应用程序违反了ORACLE规则或系统限制时,则会隐含地触发一个内部例外。每个预定义例外都对应一种ORACLE系统错误。Oracle一共提供了二十多种预定义例外,我们可以在官方文档中找到这些预定义异常。

 

 

示例如下:

--例外示例

declare

v_name emp.ename%type;

begin

select ename into v_name from emp where empno = &no;

dbms_output.put_line('name:'|| v_name);

--异常处理块开始

exception

--捕捉特定异常

when no_data_found then

--针对特定异常进行处理

dbms_output.put_line('没有此雇员号,请检查输入是否正确。');

end;

 

  1. 处理非预定义例外

    使用预定义例外只能处理22个ORACLE错误,而在开发pl/sql程序时,可能还会遇到其他Oracle错误,如在PL/SQL地中执行DML操作时,如果违反了约束规则,则会直接将错误传递到调用环境。

    我们应该在程序中合理处理这些ORACLE错误。此时就需要非预定义例外,步骤如下:

 

 

首先在定义部分定义例外名,然后在ORACLE错误和例外名之间建立关联,最终在例外处理部分引用例外。当在关联例外名和ORACLE错误时,需要使用伪过程EXCEPTION_INIT.

 

示例如下:

 

--处理非预定义例外

declare

--定义例外名

e_demo exception;

--关联例外名和错误代码

pragma exception_init(e_demo,-2291);

begin

--dbms_output.put_line('========');

update emp set deptno=&dno where empno = &no;

--insert into dept values(13,'data',systimestamp);

--例外处理块

exception

when e_demo then

dbms_output.put_line('该员工不存在');

end;

我们在上面的例子中输入147499,因为deptemp表之间具有主外键关系,所以在当在emp中修改员工的部门号时,该部门号必须在dept表中存在。如果不存在,则会抛出-2291错误。我们在这里将错误号-2291与例外e_demo进行关联,这样,当出现错误号为-2291的异常时,就会触发ora-0291对应的例外e_demo.

三.自定义异常

自定义例外是指PL/SQL开发人员定义的例外。预定义例外与非预定义例外都与ORACLE有关,并且当出现ORACLE错误时,会隐含地触发相应例外;而自定义例外与ORACLE错误没有任何关系,它是由开发人员为特定情况所定义的例外。

 

--处理非预定义例外

declare

--定义例外名

e_demo exception;

--关联例外名和错误代码

pragma exception_init(e_demo,-2291);

begin

--dbms_output.put_line('========');

update emp set deptno=&dno where empno = &no;

--insert into dept values(13,'data',systimestamp);

--例外处理块

exception

when e_demo then

dbms_output.put_line('该员工不存在');

end;

 

这段代码和上面的代码是完全相同的,但是当我们输入201111时,尽管员工号不存在1111,但是却不会出现任何错误。而这时,我们应该向用户显示更有意义的信息。这时就需要自定义异常。步骤如下:

 

 

      

 

首先在定义部分定义例外名,然后在出现例外进用RAISE子句显式的触发例外,最后在例外处理部分处理例外。

示例如下:

--处理非预定义例外

declare

--定义例外名

e_demo exception;

--关联例外名和错误代码

--pragma exception_init(e_demo, -2291);

begin

--dbms_output.put_line('========');

update emp set deptno = &dno where empno = &no;

if sql%notfound then

raise e_demo;

end if;

--insert into dept values(13,'data',systimestamp);

--例外处理块

exception

when e_demo then

dbms_output.put_line('该员工不存在');

end;

我们在原来的代码上稍加修改即可。此时再输入20和1111,就会打印出'该员工不存在'。

四.例外函数

熟悉JAVA的开发人员都知道,我们通过e.getMessage()可以获得异常的相关信息。对象e上定义了很多有价值的方法。同样的,我们在pl/sql中,我们也可以通过相关函数,获得例外的一些信息。比如SQLCODE可以获得错误号,SQLERRM可以获得错误号对应的错误信息,raise_application_error可以允许用户自定义错误号和错误信息。

--sqlcodesqlerrm函数示例

declare

v_name emp.ename%type;

begin

select ename into v_name from emp;

exception

when no_data_found then

dbms_output.put_line('不存在雇员');

when others then

--when others中特别有用

dbms_output.put_line('error code :'|| sqlcode);

dbms_output.put_line('error message :'|| sqlerrm);

end;

 

raise_application_error的语法如下:

raise_application_error(error_code,error_message[ , { true | false } ] );

其中,error_code用于定义错误号,该错误号只能是从-20000到-20999之间的负整数;

Error_message用于指定错误信息,并且该消息的长度不能超过2048字节;第三个参数可选,如果为true,则表示该错误会被放在先前的错误堆栈中;否则,则会替换先前所有错误。

注意,该过程只能在数据库端的子程序(过程、函数、包、触发器)中使用

而不能在匿名块和客户端的子程序中使用。

 

posted @ 2014-04-08 12:46  小指  阅读(805)  评论(0编辑  收藏  举报