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



我正在处理一个PL/SQL包包含{FORALL ..保存异常…更新}声明。

数据的有效性(对业务规则而言)通过表上的触发器进行检查,该表包含将要更新的数据。此触发器调用一个过程,该过程可以使用以下命令生成错误:

RAISE_APPLICATION_ERROR( -20002, 'message');

因此,在{FORALL ..}期间可能会生成用户定义的错误。保存异常…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返回。(这不是标准错误的情况!例如:如果FORALL-UPDATE由于列大小约束而失败,则来自bulk_exceptions的错误消息可能是:"ORA-12899:对于列来说值太大",并且不会为空。
  • 当引发此异常时,传递SQLCODE+SQLERRM "ORA-24381: error(s) in array DML"而不是实际触发的(用户定义的-20000)错误代码和消息。
是否有可能将来自RAISE_APPLICATION_ERROR的消息绑定到用户定义的错误代码,以便SQLERRM显示它?我如何传播此错误而不将其更改为ORA-24381错误?

一般来说,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子句将任何错误写入错误日志可能更有意义。

最新更新