如何在pl sql中跟踪异常终止

Posted

技术标签:

【中文标题】如何在pl sql中跟踪异常终止【英文标题】:How to trace abnormal termination in pl sql 【发布时间】:2014-02-14 09:44:52 【问题描述】:

我有一个处理大约 7000 条记录的 pl sql 文件。根据输入,它会选择插入,更新到不同的表。异常处理程序写在每个查询中。但是我的程序异常终止而没有显示任何错误消息。这种终止每次都发生在不同的代码位置。第一次可能处理1200条记录,下一次处理1400条记录。它与缓存问题有关吗?请提供输入以解决此问题。我正在使用 sql developer 1.5.4。有没有办法调试这样的场景?

添加pl sql文件:

下面是我的 pl sql 文件,它从文件中提到的“marx_resph_bk.txt”读取输入。

================================================ ====================================

SET SERVEROUTPUT ON;

exec dbms_output.enable(NULL);

declare

  v_line         varchar2(500);
  v_cnt          integer;
  v_cntp          integer:=0;
  v_cnth          integer:=0;
  v_file_date    date := to_date('20140201','yyyymmdd');
  v_avail_date   date := to_date('20131210','yyyymmdd');
  v_sent_date    date;
  v_eff_date     date;
  v_status       char;
  ACCEPTED       char := 'A';
  REJECTED       char := 'R';

  v_tracking_id  kc.kc_marx_transaction.kmt_marx_tsa_sk%type;
  v_hicn  kc.kc_marx_transaction.kmt_hicn_id%type;
  v_c_id         kc.kc_marx_transaction.c_id%type;
  v_trcs         kc.kc_marx_transaction.kmt_tsa_rpy_cd%type;
  v_disp_cd      kc.kc_marx_transaction.kmt_disp_cd%type;
  v_pl_id        kc.kc_hcfa_mbr_transaction.pl_id%type;
  v_cms_ttc      kc.kc_hcfa_mbr_transaction.kcmt_type_code%type;
  v_ic_ttc       kc.kc_hcfa_mbr_transaction.kcmt_type_code%type;
  v_td_id        kc.kc_validations.td_id%type;
  v_qd_id        kc.kc_validations.qd_id%type;


  f_verbatim utl_file.file_type;
  f_errors   utl_file.file_type;

  cursor c_Trcs is
    select kcmt_reply_code trc
    from kc.kc_hcfa_mbr_transaction
    where c_id = v_c_id
    and pl_id = v_pl_id
    and kcmt_file_date = v_file_date
    and kcmt_cms_aval_dt = v_avail_date
    and kcmt_type_code = v_cms_ttc;

begin
utl_file.fclose(f_verbatim);
  utl_file.fclose(f_errors);
  f_verbatim := utl_file.fopen ('/net/iRX_downloads2/work/infocare_utl', 'marx_resph_bk.txt', 'r');
  f_errors   := utl_file.fopen('/net/iRX_downloads2/work/infocare_utl', 'marx_result.txt', 'w');
<<next_hic>>
  loop
    begin

      utl_file.get_line(f_verbatim, v_line);
      v_cntp := v_cntp+1;
      dbms_output.put_line(' Line CNT: '||v_cntp);
      exception
        when no_data_found then
        dbms_output.put_line(' No Line');
          exit;
    end;

    v_hicn := substr(v_line,1,10);
    v_status := substr(v_line,474,1);
    v_tracking_id := to_number(substr(v_line,486,15));

    begin
      dbms_output.put_line(' Selecting marx_transaction');
      select c_id, substr(kmt_ctc_id,2,4), kmt_tsa_cd, kmt_eff_dt,
        kmt_snt_to_marx_sys_dt, nvl(kmt_disp_cd,'X')
      into v_c_id, v_pl_id, v_ic_ttc, v_eff_date, v_sent_date, v_disp_cd
      from kc.kc_marx_transaction
      where kmt_marx_tsa_sk = v_tracking_id;

      if v_disp_cd <> 'X' then
        dbms_output.put_line(' Skipping');
        goto next_hic;
      end if;

      exception
        when others then
        dbms_output.put_line(' Selecting tracking Id');
          utl_file.putf(f_errors, 'Select Tracking ID :'||v_tracking_id
            ||':'||sqlerrm);
          rollback;
          return;
    end;

    if v_pl_id = '3909' then
      v_pl_id := '3963';
    end if;

    v_cms_ttc := v_ic_ttc;
    v_td_id := null;
    v_qd_id := null;
    case
      when v_ic_ttc = '51' then
v_td_id := '50'; v_qd_id := '85';
      when v_ic_ttc = '61' then
        v_td_id := '10'; v_qd_id := '20';
      when v_ic_ttc = '71' then
        v_td_id := '90'; v_qd_id := '140'; v_cms_ttc := '61';
      when v_ic_ttc = '73' then
        v_td_id := '73'; v_qd_id := '445';
      when v_ic_ttc = '75' then
        v_td_id := '72'; v_qd_id := '430';
      when v_ic_ttc in ('72','76','78','80','81') then
        null;
      else
        utl_file.putf(f_errors, 'Invalid TTC:'||v_ic_ttc||':Tracking ID :'
          ||v_tracking_id);
          dbms_output.put_line(' Invalid TTC:');
        goto next_hic;
    end case;

    if v_status = REJECTED then
      begin
        delete kc.kc_validations
        where c_id = v_c_id
        and pl_id = v_pl_id
        and td_id = v_td_id
        and ec_code like 'C%';

        exception
          when others then
            null;
      end;
    end if;

    v_cnt := 0;
    v_trcs := null;

    for l_1 in c_Trcs loop

      v_trcs := v_trcs||l_1.trc;
      v_cnt  := v_cnt + 1;
   dbms_output.put_line(' Inside Cursor loop');
      -- Only need to store validation errors for those TTCs that can be
      -- worked through the browse queue screens in the front end
      if v_status = REJECTED and v_td_id is not null then
        begin
          insert into kc.kc_validations
(c_id, pl_id, td_id, qd_id, ec_code, v_column_db_name, v_update_date)
          values
          (v_c_id, v_pl_id, v_td_id, v_qd_id, 'C'||l_1.trc, ' ', sysdate);

          exception
            when others then
            dbms_output.put_line(' Validation Insert:');
              utl_file.putf(f_errors, 'Validation Insert: c_id :'||v_c_id
                ||': pl_id :'||v_pl_Id||': td_id :'||v_td_id||': '||sqlerrm);
              rollback;
              return;
        end;

        if (l_1.trc = '127' or l_1.trc = '169') and v_ic_ttc = '61' then
          begin
             update kc.kc_customer_coverages_new
             set ccv_prj_eff_date = v_eff_date,
                 ccv_accrete_eff_date = v_sent_date,
                 ccv_ssa_medd_wth_prem_eff_dt = v_eff_date,
                 ccv_lis_eff_dt = v_eff_date,
                 ccv_update_date = sysdate,
                 ccv_update_userid = user,
                 cet_type = '4A'
             where c_id = v_c_id
             and   pl_id = v_pl_id;

             exception
               when others then
               dbms_output.put_line(' Error found CCV');
                 utl_file.putf(f_errors, 'CCV Update:c_id:'||v_c_id||':pl_id:'
                   ||v_pl_id||':eff_dt:'||to_char(v_eff_date,'yyyymmdd')||':'
                   ||'sent_dt:'||to_char(v_sent_date,'yyyymmdd')||':'||sqlerrm);
                 rollback;
                 return;
          end;
        end if;
      end if;

      -- KC.KC_MARX_TRANSACTION.KMT_TSA_RPY_CD is only large enough to
      -- accommodate a string of five TRCs (rarely, if ever, is this needed)
      if v_cnt = 5 then
        exit;
      end if;

    end loop;

begin
v_cnth := v_cnth+1;
dbms_output.put_line(' CNT: '||v_cnth);
dbms_output.put_line('v_status: '||v_status||' v_trcs: '||v_trcs||' v_tracking_id: '||v_tracking_id );
dbms_output.put_line(' v_C_ID: '||v_c_id||' v_hicn: '||v_hicn);
      update kc.kc_marx_transaction
      set kmt_disp_cd = v_status,
          kmt_tsa_rpy_cd = v_trcs,
          kmt_rsp_pcs_by_marx_sys_dt = sysdate,
          last_upd_use_id = user,
          last_upd_ts = sysdate,
          last_upd_pgm_nm = 'ACCRETION II - ACCR_ACC_REJ_STATUS.SQL'
      where kmt_marx_tsa_sk = v_tracking_id;

      exception
        when others then
        dbms_output.put_line(' Error Update Tracking');
          utl_file.putf(f_errors, 'Update Tracking ID :'||v_tracking_id
            ||':'||sqlerrm);
          rollback;
          return;
    end;

  end loop;
 dbms_output.put_line('TOTAL CNT: '||v_cnth);
  utl_file.fclose(f_verbatim);
  utl_file.fclose(f_errors);

commit;
end;
/

================================================ ================================

而且它永远无法显示我的最终 dbms_output.put_line 用于 Total CNT。

【问题讨论】:

无法回答。您至少应该提供您的脚本和示例输入。投票决定暂停。 请告诉我们存储过程以及如何调用它。 EXCEPTION一个机会怎么样?如果这不起作用,请返回并再次提出问题。 【参考方案1】:

你的异常处理程序

when others then
dbms_output.put_line(' Selecting tracking Id');
  utl_file.putf(f_errors, 'Select Tracking ID :'||v_tracking_id
    ||':'||sqlerrm);
  rollback;
  return;

包含对文件的错误跟踪写入 - 具有相同信息的 dbms_output.put_line() 怎么样?您可以将其作为假脱机文件输出。似乎您也使用循环 - 结束循环;和 goto 控制方法 - 你可以使用 while() 循环来代替吗?它可能更透明。

我猜你的 RETURN 语句也有问题 - 因为你没有在嵌套块中返回之前关闭文件处理程序你没有关于错误的信息,文件是空的并且你没有到达结尾主块:

SQL> declare
  2  
  3    f_errors   utl_file.file_type;
  4  
  5  begin
  6    utl_file.fclose(f_errors);
  7    f_errors   := utl_file.fopen('FDC_BTI_DIR', 'test_01.txt', 'w');
  8      begin
  9  
 10        raise no_data_found;
 11  
 12        exception
 13          when others then
 14          dbms_output.put_line(' Selecting tracking Id');
 15            utl_file.putf(f_errors, 'Select Tracking ID :'||sqlerrm);
 16            rollback;
 17            return;
 18      end;
 19    utl_file.fclose(f_errors);
 20  end;
 21  /
Selecting tracking Id                                                           

SQL> declare
  2  
  3    f_errors   utl_file.file_type;
  4    buff varchar2(4000);
  5  
  6  begin
  7    utl_file.fclose(f_errors);
  8    f_errors   := utl_file.fopen('FDC_BTI_DIR', 'test_01.txt', 'r');
  9    utl_file.get_line(f_errors, buff, 4000);
 10    dbms_output.put_line(buff);
 11    utl_file.fclose(f_errors);
 12  end;
 13  /
declare
*
error in line 1:
ORA-01403: data not found 
ORA-06512: at  "SYS.UTL_FILE", line 106 
ORA-06512: at  "SYS.UTL_FILE", line 746 
ORA-06512: at  line 9 


SQL> declare
  2  
  3    f_errors   utl_file.file_type;
  4  
  5  begin
  6    utl_file.fclose(f_errors);
  7    f_errors   := utl_file.fopen('FDC_BTI_DIR', 'test_01.txt', 'w');
  8      begin
  9  
 10        raise too_many_rows;
 11  
 12        exception
 13          when others then
 14          dbms_output.put_line(' Selecting tracking Id');
 15            utl_file.putf(f_errors, 'Select Tracking ID :'||sqlerrm);
 16            utl_file.fclose(f_errors);
 17            rollback;
 18            return;
 19      end;
 20    utl_file.fclose(f_errors);
 21  end;
 22  /
Selecting tracking Id                                                           

SQL> declare
  2  
  3    f_errors   utl_file.file_type;
  4    buff varchar2(4000);
  5  
  6  begin
  7    utl_file.fclose(f_errors);
  8    f_errors   := utl_file.fopen('FDC_BTI_DIR', 'test_01.txt', 'r');
  9    utl_file.get_line(f_errors, buff, 4000);
 10    dbms_output.put_line(buff);
 11    utl_file.fclose(f_errors);
 12  end;
 13  /
Select Tracking ID :ORA-01422: exact fetch returns more than requested number of rows                                                                    

SQL> declare
  2  
  3    f_errors   utl_file.file_type;
  4  
  5  begin
  6    utl_file.fclose(f_errors);
  7    f_errors   := utl_file.fopen('FDC_BTI_DIR', 'test_01.txt', 'w');
  8      begin
  9  
 10        raise invalid_number;
 11  
 12        exception
 13          when others then
 14          dbms_output.put_line(' Selecting tracking Id');
 15            utl_file.putf(f_errors, 'Select Tracking ID :'||sqlerrm);
 16            rollback;
 17      end;
 18    utl_file.fclose(f_errors);
 19  end;
 20  /
Selecting tracking Id                                                           

SQL> declare
  2  
  3    f_errors   utl_file.file_type;
  4    buff varchar2(4000);
  5  
  6  begin
  7    utl_file.fclose(f_errors);
  8    f_errors   := utl_file.fopen('FDC_BTI_DIR', 'test_01.txt', 'r');
  9    utl_file.get_line(f_errors, buff, 4000);
 10    dbms_output.put_line(buff);
 11    utl_file.fclose(f_errors);
 12  end;
 13  /
Select Tracking ID :ORA-01722: invalid_number

【讨论】:

以上是关于如何在pl sql中跟踪异常终止的主要内容,如果未能解决你的问题,请参考以下文章

PL/SQL:如何在异常中获取 ORA 代码?

Oracle PL/SQL - 如何在异常子句的单独表中捕获坏数据?

如何修改我的 PL/SQL 过程以进行异常处理?

在 pl sql 中的所有异常情况下无论如何都要做些啥吗?

PL/SQL 引发处理异常

pl/sql:如果可能出现异常,如何放置所有行的值?