Thursday, May 14, 2009

Oracle中的异常处理

异常与Oracle错误的关联可通过EXCEPTION_INIT编译器指令实现。语法:

  PRAGMA EXCEPTION_INIT(exception_name , oracle_error_number);

(在PL/SQL中使用编译器指令的语法都是以pragma打头,且只能在代码的声明部分使用。可参照自治事务的用法)

1>被关联的异常只能是用户自定义的异常,不能是预定义的异常名。当然用户可定义一个与预定义同名的异常(但不提倡这样做);

2>一个错误可以关联多个异常,关联同一个错误的异常不能在异常处理部分同时出现;

5、SQLCODE返回的是当前的错误号。

  SQLERRM返回的是当前的错误信息文本。

  如果错误(异常)是通过RAISE显式引发的用户自定义异常,且该异常没有通过EXCEPTION_INIT语句与错误代号进行关联,则SQLCODE返回值为1,而SQLERRM返回的信息是:ORA-06510: PL/SQL: unhandled user-defined exception。

  也可以这样理解:用户自定义的异常默认与错误代号为1的错误进行关联,而错误代号为1的错误信息文本是:ORA-06510: PL/SQL: unhandled user-defined exception。

  两个相关例子:

SQL> DECLARE

2  e_test EXCEPTION;

3 BEGIN

4   RAISE e_test;

5 EXCEPTION WHEN OTHERS THEN

6   DBMS_OUTPUT.PUT_LINE(SQLCODE);

7  DBMS_OUTPUT.PUT_LINE(DBMS_UTILITY.FORMAT_ERROR_STACK);

8 END;

9 /

1

ORA-06510: PL/SQL: unhandled user-defined exception

PL/SQL过程已成功完成。

SQL> DECLARE

2  e_test EXCEPTION;

3  PRAGMA EXCEPTION_INIT(e_test ,-20001);

4 BEGIN

5   RAISE_APPLICATION_ERROR(-20001,'This is a test.');

6 EXCEPTION

7   WHEN e_test THEN

8     DBMS_OUTPUT.PUT_LINE(SQLCODE);

9  DBMS_OUTPUT.PUT_LINE(SQLERRM);

10   WHEN OTHERS THEN

11     NULL;

12 END;

13 /

-20001

ORA-20001: This is a test.

PL/SQL过程已成功完成。

6、使用RAISE_APPLICATION_ERROR方法引发异常并创建错误代号与错误消息。语法:

  RAISE_APPLICATION_ERROR(error_number,error_message[,keep_errors]);

  其中,error_number是在-20000到-20999之间的一个值。error_message是与该错误关联的文本.keep_errors的值为TRUE或FALSE,如为TRUE,新产生的错误就会追加到已引发错误的列表中(如果已经有错误的话)。如为FALSE(FALSE也是默认值),新发生的错误就会替换当前的错误列表。

SQL> BEGIN

2   BEGIN

3     BEGIN

4    RAISE_APPLICATION_ERROR(-20001,'This is a test.',TRUE);

5     EXCEPTION WHEN OTHERS THEN

6    RAISE_APPLICATION_ERROR(-20002,'I raised by 20001.',TRUE);

7     END;

8   EXCEPTION  WHEN OTHERS THEN

9     RAISE_APPLICATION_ERROR(-20003,'I raised by 20002.',TRUE);

10   END;

11 EXCEPTION WHEN OTHERS THEN

12     DBMS_OUTPUT.PUT_LINE(SQLCODE);

13  DBMS_OUTPUT.PUT_LINE(SQLERRM);

14 END;

15 /

-20003

ORA-20003: I raised by 20002.

ORA-20002: I raised by 20001.

ORA-20001: This is a test.

PL/SQL过程已成功完成。

7、异常的传播

  1、声明部分和异常部分引发的异常都会立即传播到该封装块。

  2、使用不带任何参数的RAISE语句,再次引发当前异常。该语句只能在异常处理部分出现,通常是为了异常能从已被捕获的处理块中再次传出。

8、异常与事务

  引发异常不会结束某个事务,就像终止某个代码块不会终止一个事务一样。

  但是如果顶层的代码块以一个未处理异常而终止,该异常就会传播到调用环境,代码中产生的相应事务就会立即由服务器进行回滚。

9、异常可当作控制语句使用(如跳过某段程序的执行、终止整个程序的执行等)。

Tuesday, May 12, 2009

PL/SQL debug – 1

Error Message while executing the script:

Error code:-932Script error message:ORA-00932: inconsistent datatypes: expected - got -

possible solution:

1. check the parmaters type match the column type in select clause

2. check the result table type definition match the source table column type

3. copy part of the script to another editor window, try to run to get more determined error messages

Monday, May 11, 2009

select into

case 1. select into 语法
 
现在有表
tablea 
 cola int ,
 colb varchar(20)
)
 
要把tablea中满足条件(cola <100)的记录生成新的表tableb。
 
在ms sqlserver 可以直接用select into语法:
select * into tableb 
where cola <>
 
在oracle中语法如下:
create table tableb 
as 
  select * from tablea 
    where cola <100)

Rank()使用

找出column1对应多个column_2的查询:
---------------------------------------------
select * from (select rank() over(partition by order by    desc) rk, table_name.* 
from table_name) T 
where T.rk>=2;