如何将dbms_output.put_line的结果插入到表中以进行错误捕获?

时间:2018-11-28 03:24:30

标签: oracle plsql

Exception
WHEN OTHERS THEN
--dbms_output.put_line('pl_update_sidm_user r: ERROR CODE:' || sqlcode || '~' || 
--sqlerrm || ' EMPL_NBR:' || r.EMPL_NBR);

insert into ERROR_MSG (ERROR_MSG_ID,ERROR_MSG) values (ERROR_MSG_ID_SEQ.NEXTVAL, 'pl_update_sidm_user_duty_role r2');
END;

我想将错误结果放在表中。 但是,我该怎么办?

我可以将dbms_output的结果作为字符串放入表中吗?

如果没有,我可以不用sqlcode,sqlerrm来获得dbms_output吗?

谢谢!!

2 个答案:

答案 0 :(得分:2)

documentation

  

SQL语句无法调用SQLCODE或SQLERRM。使用他们的价值观   在SQL语句中,首先将它们分配给局部变量

也是

  

除了使用FORALL语句及其SAVE EXCEPTIONS子句之外,Oracle建议使用DBMS_UTILITY.FORMAT_ERROR_STACK

因此,对于SQLCODESQLERRM,应将它们分配给变量并使用它们。

DECLARE
v_errcode NUMBER;
v_errmsg VARCHAR2(1000);
BEGIN
--some other statements that may raise exception.
EXCEPTION
WHEN OTHERS THEN
v_errcode := SQLCODE;
v_errmsg  := SQLERRM;
insert into ERROR_TABLE (ERROR_MSG_ID,ERROR_MSG) --change your table name
values (ERROR_MSG_ID_SEQ.NEXTVAL,
      v_errcode||':'||v_errmsg); 

END;
/

按照Oracle的建议,最好使用这样的插入。

insert into ERROR_TABLE (ERROR_MSG_ID,ERROR_MSG) values (ERROR_MSG_ID_SEQ.NEXTVAL,
      DBMS_UTILITY.FORMAT_ERROR_STACK);

Demo

答案 1 :(得分:1)

从技术上讲,其他人的建议是正确的:在“其他人例外”块中执行的“插入”操作实际上将在日志表中插入新行。

问题是这样的插入语句将成为主过程同一事务的一部分,并且由于您在执行它时出错,因此您很可能回滚该事务,这也会回滚日志表中的插入

我想您面临的问题不是您没有成功记录错误消息:而是您随后将其回滚,以及您在同一事务中所做的所有其他写操作。

Oracle通过使用“自主事务”过程为您提供了一种在单独事务中执行代码的方法。

您需要创建这样的过程:

create or replace  procedure Write_Error_log(
              arg_error_code number, 
              arg_error_msg varchar2, 
              arg_error_backtrace varchar2) is
 PRAGMA AUTONOMOUS_TRANSACTION;
 begin
    INSERT INTO error_msg (
          error_msg_id, 
          error_code, 
          error_msg, 
          error_stack)
     VALUES (
          error_msg_id_seq.NEXTVAL, 
          arg_error_code,
          arg_error_msg,  
          arg_error_backtrace);
     commit; -- you have to commit or rollback always, before exiting a 
             -- pragma autonomous_transaction procedure
 end; 

此过程要做的是使用完全独立的事务在日志表中写入新记录:即使在调用过程中执行回滚操作,数据也将保留在日志表中。您还可以使用这样的过程来创建通用日志(不仅是错误)。

您现在要做的就是在需要记录某些内容时调用上面的过程,因此您的代码变为:

DECLARE
   v_errcode NUMBER;
   v_errmsg VARCHAR2(1000);
BEGIN
   --some other statements that may raise exception.
EXCEPTION WHEN OTHERS THEN
     Write_Error_log(SQLCODE, SQLERRM, dbms_utility.format_error_backtrace);
END;
/

P.S:我的代码中可能有一些错别字:由于目前无法访问oracle服务器,我现在无法对其进行测试。