SQLERRM正在被覆盖

时间:2014-10-22 15:39:21

标签: oracle plsql error-handling oracle10g

我正在使用SQLERRM。但是有更多的程序并行运行,因此有时SQLERRM会被其他程序覆盖。运行并行我的意思是我同时运行过程a和过程b .SQLERRM是一个全局函数,这是我的问题。如果在两个过程中抛出异常,则可能发生,过程a修改过程b中的错误消息,过程b得到错误的消息。 这些程序使用简单的结构:

BEGIN
--do something/cutted off
EXCEPTION
        WHEN OTHERS THEN
            write_log(SYSDATE, 'ERROR_1', SQLERRM);

END;

这些过程调用write_log,声明为

 CREATE OR REPLACE PROCEDURE WRITE_LOG
 (
        TS_START IN DATE DEFAULT SYSDATE,
        ERR_CODE IN VARCHAR DEFAULT NULL,
        ERR_DESC IN VARCHAR DEFAULT NULL
 ) 
 IS

 BEGIN
  INSERT INTO LOG
        ( LOG_TS_START, LOG_ERR_CODE, LOG_ERR_DESC)
    VALUES
        (TS_START, ERR_CODE, ERR_DESC);


   COMMIT;

END WRITE_LOG;

如何避免覆盖SQLERRM?正在写入日志,但错误消息是错误的。

3 个答案:

答案 0 :(得分:1)

首先,摆脱PL/SQL代码中的常见错误。

没有WHEN OTHERS THEN且没有任何理性逻辑的

RAISE只是使用,只不过是一个错误。

删除所有exception blocks,然后重试。并遵循良好的编码实践。

答案 1 :(得分:1)

过程WRITE_LOG未使用传入的参数来执行INSERT。试一试:

 CREATE OR REPLACE PROCEDURE WRITE_LOG
   (TS_START IN DATE DEFAULT SYSDATE,
    ERR_CODE IN VARCHAR DEFAULT NULL,
    ERR_DESC IN VARCHAR DEFAULT NULL)
 IS    
 BEGIN
   INSERT INTO LOG
     (LOG_TS_START, LOG_ERR_CODE, LOG_ERR_DESC)
   VALUES
     (TS_START, ERR_CODE, ERR_DESC);

   COMMIT;
END WRITE_LOG;

另外,在我看来,记录错误到数据库表是绝对错误的。因为您在日志记录过程中有一个COMMIT语句,所以您将提交所有更改,直到错误点,这很可能不是您想要做的。如果你愿意的话,你可以搞乱自主交易,但对我来说,最好的办法是登录平面文件。

分享并享受。

答案 2 :(得分:0)

写入日志表非常常见,但使用自治事务进行日志记录是标准做法。这是因为您不希望主事务中的回滚影响日志记录,或者日志记录中的提交会影响主事务。 (@BobJarvis示例不是自主的)。

显示了一个简单示例here

日志表还需要考虑其他一些事项。首先,你应该有一个log_id,它使用sys_guid(在表上定义)或触发器上的序列。此外,使用write_log可用于区分正在编写日志消息的过程(或会话)的上下文字段。

添加此设置(包括上下文)后,再次运行过程a和过程b(同时),并在上下文中传递过程名称(a或b)。您将能够在表格中看到a和b日志消息。