【问题标题】:NOT ABLE TO CAPTURE no_data_found error in error logs table无法捕获错误日志表中的 no_data_found 错误
【发布时间】:2017-07-10 18:55:54
【问题描述】:

当我传递一个输入参数时,我有一个存储过程。使用该输入参数,如果没有 no_data_found 那么我将引发异常,试图在该错误日志表中存储 no_data_found 错误,但我无法做到。请在下面找到我的代码,

存储过程:

create or replace procedure dumm_proc (p_opportunity_number cct_opportunity.opportunity_number%type)
as

v_oppo_id varchar2(50);
l_message varchar2(50) := sqlerrm;
l_code varchar2(50) := sqlcode;

begin

select opportunity_id into v_oppo_id 
from cct_opportunity
where opportunity_number =  p_opportunity_number;


exception
when no_data_found then
raise;
xxcct_error_logs(cct_error_seq.nextval,null,v_oppo_id,null,null,l_message,l_code,'dumm_proc',null,sysdate,user,sysdate,user);

when others then
xxcct_error_logs(cct_error_seq.nextval,null,v_oppo_id,null,null,l_message,l_code,'dumm_proc',null,sysdate,user,sysdate,user);

end;

使用另一个错误日志过程 (xxcct_error_logs) 将值存储到表中,但它总是在正常、成功完成的情况下存储。

请建议我如何通过调用 error_logs 过程来存储 no_data_found 错误。

【问题讨论】:

标签: sql oracle plsql


【解决方案1】:

原因是由于您在引发异常之前分配了 l_message,l_code 的值,因此默认情况下执行总是正常的。希望这个 sn-p 有所帮助。

CREATE OR REPLACE
PROCEDURE dumm_proc(
    p_opportunity_number cct_opportunity.opportunity_number%type)
AS
  v_oppo_id VARCHAR2(50);
  l_message VARCHAR2(50) := sqlerrm;
  l_code    VARCHAR2(50) := SQLCODE;
BEGIN
  SELECT opportunity_id
  INTO v_oppo_id
  FROM cct_opportunity
  WHERE opportunity_number = p_opportunity_number;
EXCEPTION
WHEN no_data_found THEN
  --  raise;
  l_message:=SQLERRM;
  l_code   :=SQLCODE;
  xxcct_error_logs(cct_error_seq.nextval,NULL,v_oppo_id,NULL,NULL,l_message,l_code,'dumm_proc',NULL,sysdate,USER,sysdate,USER);
WHEN OTHERS THEN
  l_message:=SQLERRM;
  l_code   :=SQLCODE;
  xxcct_error_logs(cct_error_seq.nextval,NULL,v_oppo_id,NULL,NULL,l_message,l_code,'dumm_proc',NULL,sysdate,USER,sysdate,USER);
END;

下面是sn-p,方便理解

SET serveroutput ON;
DECLARE
  l_message VARCHAR2(100):=SQLERRM;
  l_code    VARCHAR2(100):=SQLCODE;
BEGIN
  dbms_output.put_line(l_message||'-->'||l_code);
END;

--Now raising exception forcefully

    SET serveroutput ON;
    DECLARE
      l_message VARCHAR2(100):=SQLERRM;
      l_code    VARCHAR2(100):=SQLCODE;
      l_var PLS_INTEGER;
    BEGIN
      BEGIN
        l_var:='abc';
      EXCEPTION
      WHEN VALUE_ERROR THEN
        l_message:=SQLERRM;
        l_code   :=SQLCODE;
      END;
      dbms_output.put_line(l_message||'-->'||l_code);
    END;

【讨论】:

  • sn-ps 以上有帮助,但只有一个疑问,从我的代码中我需要在我的 error_logs 表中捕获 select..INTO 值....根据我的代码我需要插入 v_oppo_id 也应该被插入到 error_logs 表中。
  • 请忽略我之前的问题。你的 sn-ps 很有帮助,它成功了.. 谢谢。
【解决方案2】:

raise 结束执行并将异常传回给调用者,因此无法调用错误记录器:

exception
    when no_data_found then
        raise;
        xxcct_error_logs(cct_error_seq.nextval, ... );

作为第一步,我将其更改为:

exception
    when no_data_found then
        xxcct_error_logs(cct_error_seq.nextval, ... );
        raise;

错误记录器似乎有很多参数。可能它可以自己找出大部分细节,而您需要传递的只是对失败的过程尝试执行的操作的描述。

编辑:

我错过了您在错误之前为异常详细信息填充变量。那时没有错误。您需要在异常处理程序中捕获详细信息。你甚至不需要变量。为什么不只是:

xxcct_error_logs
( cct_error_seq.nextval
, null
, v_oppo_id
, null
, null
, sqlerrm    -- Just capture sqlerrm here
, sqlcode
, 'dumm_proc'
, null
, sysdate
, user
, sysdate
, user );

或者更简单,根本不通过。在xxcct_error_logs 过程中,它可以检查是否sqlcode = 0,如果不是,它可以接收sqlerrm。当您使用它时,您可以让它处理cct_error_seq.nextval,而不是要求每个调用者都知道要使用什么序列;用户、时间戳等也是如此。我的日志过程如下所示:

procedure msg
    ( p_message           dsl_log.message%type
    , p_started_timestamp dsl_log.log_timestamp%type default null )

【讨论】:

  • 我已按照您的建议更改了异常块,但其存储值仍为“ORA-0000:正常,成功完成”而不是“ORA-0143:no_data_found”。
  • 刚刚注意到您在出现任何错误之前捕获了sqlerrm。这就是它报告成功的原因。有机会时,我会更新我的答案并提供更多详细信息。
猜你喜欢
  • 2014-09-03
  • 2010-10-26
  • 2014-10-16
  • 1970-01-01
  • 1970-01-01
  • 2011-02-23
  • 2017-06-06
  • 2019-02-18
  • 1970-01-01
相关资源
最近更新 更多