根据参数

时间:2015-09-17 19:02:16

标签: oracle stored-procedures plsql error-handling

他们是否可以记录由于传入参数而发生的错误? 即

PROCEDURE customer_collateral_hist(i_Vcust_cd   IN customer_collateral_history.cust_cd%TYPE,
                                   i_Vfromdate  IN customer_collateral_history.reg_dttm%TYPE,
                                   i_Vtodate    IN customer_collateral_history.reg_dttm%TYPE,
                                   i_Vauthstat  IN customer_collateral_history.auth_stat%TYPE,
                                   o_Cresultset OUT SYS_REFCURSOR)
   AS
   BEGIN
      OPEN o_Cresultset FOR
         SELECT auth_stat,
            buld_size,
            clos_dt,
            cnfm_dt,
            cnfm_tm,
            cnfm_user_id,
            cust_cd,
            date_seq,
            dbtr,
            dbtr_addr,
            dbtr_id,
            dbtr_tel_no,
            dbtr_zip_cd1,
            dbtr_zip_cd2,
            esta_orga,
            grnt_dt_from,
            grnt_dt_to,
            jdg_amt,
            jdg_dt,
            land_size,
            loc_addr,
            mort_amt,
            mort_chng_dt,
            mort_flag,
            mort_max_amt,
            mort_seq,
            mort_stat,
            old_key,
            ownr,
            ownr_addr,
            ownr_id,
            ownr_tel_no,
            ownr_zip_cd1,
            ownr_zip_cd2,
            prev_mort_amt,
            redm_dt,
            reg_dt,
            reg_dttm,
            reg_flag,
            reg_user_id,
            remark,
            supr_pow_flag
       FROM customer_collateral_history
         WHERE cust_cd LIKE '%'||NVL(i_Vcust_cd, cust_cd)||'%'
        AND TO_NUMBER(SUBSTR(reg_dttm, 1, 8)) >= NVL(i_Vfromdate, TO_NUMBER(SUBSTR(reg_dttm, 1, 8)))
    AND TO_NUMBER(SUBSTR(reg_dttm, 1, 8)) <= NVL(i_Vtodate, TO_NUMBER(SUBSTR(reg_dttm, 1, 8)))
    AND auth_stat LIKE '%'||NVL(i_Vauthstat, auth_stat)||'%';
  EXCEPTION
    WHEN OTHERS THEN
       NULL;
   END customer_collateral_hist;

END customer;
/

在上面的过程中,我将通过调用此过程来更改异常处理程序

CREATE OR REPLACE procedure 
        APMS.write_error_log ( errstr varchar2, errline varchar2) 
    IS
        pragma autonomous_transaction; 
        -- this procedure stays in its own new private transaction
    begin                         
              INSERT INTO error_log
                  (err_tmsp,
                   err_msg,
                err_line_no
                )
          values (systimestamp,
                  errstr,
                  errline
                  );
          COMMIT;  -- this commit does not interfere with the caller's transaction.
    end write_error_log;

例如,我的write_error_log过程到目前为止,将过程中遇到的错误的时间,消息和行号记录到error_log表中。但是,最后一步是编写一些代码,允许write_error_log过程捕获涉及在参数中调用数据的错误。我希望这是有道理的。

2 个答案:

答案 0 :(得分:0)

执行此操作的一种方法是在通过使用ASSERT语句到达时检查参数。 This article显示ASSERT函数。这样的陈述被列为NASA用于safety critical code的一种技术。

只需在每个函数或过程的开头添加一系列断言,以指示您期望的值范围。如果它们在该范围内,则抛出异常,您可以捕获。

答案 1 :(得分:0)

在运行时动态检查调用堆栈中的参数值没有简单的方法。您可能希望将以下一项或两项添加到异常日志

dbms_utility.format_error_backtrace dbms_utility.format_error_stack

并为其添加另一个参数以允许调用程序发送消息 - 并让每个异常块向您的过程传递输入参数及其值的列表。

所以

PROCEDURE customer_collateral_hist(i_Vcust_cd   IN customer_collateral_history.cust_cd%TYPE,
                                   i_Vfromdate  IN customer_collateral_history.reg_dttm%TYPE,
                                   i_Vtodate    IN customer_collateral_history.reg_dttm%TYPE,
                                   i_Vauthstat  IN customer_collateral_history.auth_stat%TYPE,
                                   o_Cresultset OUT SYS_REFCURSOR)
   AS
   BEGIN
      OPEN o_Cresultset FOR
         SELECT auth_stat,
            buld_size,
            clos_dt,
            cnfm_dt,
            cnfm_tm,
            cnfm_user_id,
            cust_cd,
            date_seq,
            dbtr,
            dbtr_addr,
            dbtr_id,
            dbtr_tel_no,
            dbtr_zip_cd1,
            dbtr_zip_cd2,
            esta_orga,
            grnt_dt_from,
            grnt_dt_to,
            jdg_amt,
            jdg_dt,
            land_size,
            loc_addr,
            mort_amt,
            mort_chng_dt,
            mort_flag,
            mort_max_amt,
            mort_seq,
            mort_stat,
            old_key,
            ownr,
            ownr_addr,
            ownr_id,
            ownr_tel_no,
            ownr_zip_cd1,
            ownr_zip_cd2,
            prev_mort_amt,
            redm_dt,
            reg_dt,
            reg_dttm,
            reg_flag,
            reg_user_id,
            remark,
            supr_pow_flag
       FROM customer_collateral_history
         WHERE cust_cd LIKE '%'||NVL(i_Vcust_cd, cust_cd)||'%'
        AND TO_NUMBER(SUBSTR(reg_dttm, 1, 8)) >= NVL(i_Vfromdate, TO_NUMBER(SUBSTR(reg_dttm, 1, 8)))
    AND TO_NUMBER(SUBSTR(reg_dttm, 1, 8)) <= NVL(i_Vtodate, TO_NUMBER(SUBSTR(reg_dttm, 1, 8)))
    AND auth_stat LIKE '%'||NVL(i_Vauthstat, auth_stat)||'%';
  EXCEPTION
    WHEN OTHERS THEN
       write_error_log(SQLERRM, 'Params i_vcust_cd: '||e_vcustid||' eVfromdate: '||t_vFromDate....);
       -- if you want to halt execution then re-raise the error up the stack
       RAISE;
   END customer_collateral_hist;

然后添加到您的处理程序:

CREATE OR REPLACE procedure 
        APMS.write_error_log ( errstr varchar2, p_tracetext varchar2) 
    IS
        pragma autonomous_transaction; 
        -- this procedure stays in its own new private transaction
    begin                         
              INSERT INTO error_log
                  (err_tmsp,
                   err_msg,
                   trace_Text
                )
          values (systimestamp,
                  errstr,
                  'BackTrace: '||dbms_utility.format_error_backtrace
                  ||chr(10)||' Stack: '||dbms_utility.format_error_stack
                  ||' details: '||p_tracetext 
                  );
          COMMIT;  -- this commit does not interfere with the caller's transaction.
    end write_error_log;

您需要管理的事情是确保一致的编码实践为您提供所需的细节,如果您将异常提升到调用程序,您将重复调用堆栈的每一步 - 效率不是很高。为了避免这种情况,您需要在堆栈的最低深度记录堆栈和详细信息,并在出路时在堆栈顶部写入一次。不难做到 - 但又需要勤奋的编码实践。

祝你好运!