通过SQL%BULK_EXCEPTIONS传播触发的异常

时间:2014-03-17 18:25:06

标签: sql oracle plsql

我正在处理一个包含{FORALL .. SAVE EXCEPTIONS ... UPDATE}语句的PL / SQL包。

使用表中的触发器检查数据(对业务规则)的有效性,该触发器将包含将要更新的数据。此触发器使用以下命令调用能够生成错误的过程:

RAISE_APPLICATION_ERROR( -20002, 'message');

因此可以在{FORALL .. SAVE EXCEPTIONS ... UPDATE} DML语句期间生成用户定义的错误。但是,当尝试使用SQL%BULK_EXCEPTIONS在异常处理中记录错误时,我会观察到以下输出;

SQLCODE:                                       ORA-24381
SQLERRM:                                       ORA-24381: error(s) in array DML
SQL%BULK_EXCEPTIONS(i).ERROR_CODE:             20002
SQLERRM(-(SQL%BULK_EXCEPTIONS(i).ERROR_CODE)): ORA-20002:

请注意,sql%bulk_exceptions中的error_code会丢失减号。除错误代码外,错误消息为空。

这里有两个问题:

  • 不会通过bulk_exceptions返回(用户定义的)错误消息。 (标准错误不是这种情况!fe:由于列大小限制,FORALL-UPDATE会失败,来自bulk_exceptions的错误消息可能是:“ ORA-12899:列值太大 “,并且不会是空的。”
  • 引发此异常时,将传递SQLCODE + SQLERRM“ ORA-24381:数组DML中的错误”,而不是实际触发的(用户定义的,-20000)错误代码和消息。

是否可以将来自RAISE_APPLICATION_ERROR的消息绑定到用户定义的错误代码,以便SQLERRM显示它?如何在不更改为ORA-24381错误的情况下传播此错误?

1 个答案:

答案 0 :(得分:3)

通常,sqlerrm无法返回用户定义的错误消息,因为完全可能(并且在大多数应用程序中,可能)相同的错误代码映射到多个错误消息。如果您的特定应用程序设计为每个用户定义的错误都有一个定义,并且只有一条消息对应于错误代码,那么您可以维护自己的集合,将错误代码映射到错误消息并在错误处理程序中调用它。像

这样的东西
CREATE OR REPLACE PACKAGE pkg_error_codes
AS
  TYPE error_code_tbl IS TABLE OF VARCHAR2(100) INDEX BY PLS_INTEGER;
  g_error_codes error_code_tbl;

  FUNCITON My_SQLERRM( p_error_code IN INTEGER )
    RETURN VARCHAR2;
END;

CREATE OR REPLACE PACKAGE BODY pkg_error_codes
AS 
  FUNCITON My_SQLERRM( p_error_code IN INTEGER )
    RETURN VARCHAR2
  IS
  BEGIN
    RETURN g_error_codes( p_error_code );
  END;

BEGIN
  -- Initialize your error codes
  g_error_codes( 20001, 'Some error message' );
  g_error_codes( 20002, 'Another error message' );
END;

然后,您可以在代码中致电My_SQLERRM(如果您愿意,可直接使用pkg_error_codes.g_error_codes( SQL%BULK_EXCEPTIONS(i).ERROR_CODE ))。

您可能希望创建一个表,将错误号映射到错误消息,并在初始化块中读取,而不是将映射放在代码中。并且您可能希望命名异常,并通过作为程序包主体一部分的pragma exception_init调用将它们与错误代码相关联(尽管这将消除在正常操作中在错误堆栈中出现错误消息的能力)。

根据您正在做的事情,使用SQL而不是PL / SQL使用dbms_errlog表创建错误日志表并在SQL语句中使用EXCEPTIONS INTO子句可能更有意义将任何错误写入错误日志。这将包括引发的实际错误消息。