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

Dav*_*pez 5 sql plsql oracle11g

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

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

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

\n\n
\n

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

\n
\n\n

我不只是找到有问题的数据并将其添加到 XXW_PAYMENTS_F_EXCEPTION,我喜欢处理异常并继续循环。

\n\n

我想知道是否有我可以使用的“SKIP”实现。我尝试过标记循环,但收到“PLS-00375:非法 GOTO 语句;此 GOTO 无法分支到标签”。有什么建议么?谢谢。

\n

小智 6

您可以在 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.
Run Code Online (Sandbox Code Playgroud)