我正在处理一个包含{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会丢失减号。除错误代码外,错误消息为空。
这里有两个问题:
是否可以将来自RAISE_APPLICATION_ERROR的消息绑定到用户定义的错误代码,以便SQLERRM显示它?如何在不更改为ORA-24381错误的情况下传播此错误?
答案 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
子句可能更有意义将任何错误写入错误日志。这将包括引发的实际错误消息。