处理PL-SQL异常并继续循环

问题描述 投票:1回答:2

下一个PL-SQL代码处理bloob对象,直到找到异常的bloob结构:

DECLARE
  CURSOR c_mnu
  IS
    SELECT tb.payment_number,tb.blob_obj,tb.blob_size,tb.blob_id
    FROM XXW_PYMNT_ITM_TRF_STG tb
    where tb.payment_number not in (SELECT PAYMENT_NUMBER FROM XXW_PAYMENTS_F_EXCEPTION);
  test_vc VARCHAR2(32767);
  offset      NUMBER := 1;
  amount      NUMBER := 1;
  LEN         NUMBER := 1;
  idItem       VARCHAR2(100);--id item de pago
  montoAplicar VARCHAR2(100);--monto a aplicar
  billItem VARCHAR2(60);--id de billing
  blob_id_ant  NUMBER ;-- blob id anterior
  seq_num      NUMBER := 0; -- sequencia agrupando por blob id
  pago varchar(50);  
BEGIN
  FOR cu IN c_mnu
  LOOP
    LEN           :=cu.blob_size;--tamaño del blob
    test_vc       := cu.blob_obj;--variable de trabajo del blob
    pago := cu.payment_number;
    WHILE ( LEN > 0)
    LOOP
       -- Verifico si es el mismo blob id al anterior
       IF  blob_id_ant = cu.blob_id THEN
     seq_num := seq_num + 1;
       ELSE  
     seq_num := 1;
       END IF;
       --Segundo LF
       idItem:=substr(test_vc,instr(test_vc, ' ' , 1,10 )+1,(instr(test_vc, ' ' , 1,11)-(instr(test_vc, ' ' , 1,10 )+1)));
    -- Tercer LF
       montoAplicar:=substr(test_vc,instr(test_vc, ' ' , 1,15 )+1,(instr(test_vc,  chr(10) , 1,3)-(instr(test_vc, ' ' , 1,15 )+1)));
       --Cuarto LF
       billItem:=substr(test_vc,instr(test_vc, '"' , 1 )+1,((instr(test_vc,  chr(10) , 1,4 )-1)-(instr(test_vc, '"' , 1 )+1)));
       amount:=instr(test_vc,  chr(10) , 1,4 );
       offset := amount+1;
       --saco el pedazo de blob procesado
       test_vc := substr(test_vc,offset, LEN);
       --inserto los valores en la tabla de payments    
       insert into XXW_PYMNT_ITM_AMNT values (cu.payment_number,to_number(idItem),billItem,to_number(montoAplicar),cu.blob_id, seq_num); 
       --actualizo la longitud de blob
       LEN := LEN - offset;
       blob_id_ant := cu.blob_id;

    END LOOP;
  END LOOP;
  commit;
  EXCEPTION
  WHEN OTHERS THEN
  dbms_output.put_line ( 'Pago con error ' || pago);
END;

当程序通过substr函数找到比预期更多的行时,返回

6502:65000:java.sql.SQLException:ORA-06502:PL / SQL:数字或值错误:字符串缓冲区太小ORA-06512:第1行

而不只是找到麻烦的数据并将其添加到XXW_PAYMENTS_F_EXCEPTION,id喜欢处理异常并继续循环。

我想知道是否有一个我可以使用的“SKIP”实现。我试过标记循环,但我得到了“PLS-00375:非法的GOTO声明;这个GOTO无法分支到标签”。有什么建议?谢谢。

sql plsql oracle11g
2个回答
1
投票

您可以在substr行周围创建一个新块,并在那里捕获异常,以便您保持循环。这是一个带有异常处理程序的内部块的简单示例。

    >DECLARE
  2      CURSOR testc
  3      IS
  4          SELECT table_name from user_tables where rownum < 5;
  5      dummy number;
  6  BEGIN
  7      FOR testr IN testc
  8      LOOP
  9          BEGIN
 10              select 1/0 into dummy from dual;
 11          EXCEPTION
 12          WHEN OTHERS THEN
 13              dbms_output.put_line('Inner exception');
 14          END;
 15      END LOOP;
 16  EXCEPTION
 17  WHEN OTHERS THEN
 18      dbms_output.put_line('Outer exception');
 19  END;
 20  /
Inner exception
Inner exception
Inner exception
Inner exception

PL/SQL procedure successfully completed.

0
投票

除了在异常后继续的问题,如果你想跳到下一个迭代,你可以使用continue

begin
    for r in (
        select 'X' as sometext from dual union all
        select 'XY' from dual union all
        select 'XYZ' from dual union all
        select 'Z' from dual
    )
    loop
        if length(r.sometext) > 2 then
            dbms_output.put_line('(Skipping ' || r.sometext ||')');
            continue;
        end if;

        dbms_output.put_line(r.sometext);
    end loop;
end;

输出:

X
XY
(Skipping XYZ)
Z

或者没有if

begin
    for r in (
        select 'X' as sometext from dual union all
        select 'XY' from dual union all
        select 'XYZ' from dual union all
        select 'Z' from dual
    )
    loop
        continue when length(r.sometext) > 2;

        dbms_output.put_line(r.sometext);
    end loop;
end;
© www.soinside.com 2019 - 2024. All rights reserved.