繁体   English   中英

如何在SQL中引发异常后继续while循环

[英]How to continue while loop after exception raised in SQL

在下面的代码中引发异常后,如何继续while循环?

DECLARE    
  v_blob_data       BLOB;    
  v_blob_len        NUMBER;    
  v_position        NUMBER;    
  v_raw_chunk       RAW(10000);    
  v_char      CHAR(1);    
  c_chunk_len   number       := 1;    
  v_line        VARCHAR2 (32767)        := NULL;    
  v_data_array      wwv_flow_global.vc_arr2;    
  v_rows number;    
  v_sr_no number := 1;  
  v_first_line_done boolean := false;  
  v_error_cd number :=0;  
  v_quote_pos1 NUMBER;  
  v_quote_pos2 NUMBER;  
  v_enclosed_str VARCHAR(200);
  v_errmsg VARCHAR2(4000);
BEGIN
  delete from TEMP_MM_UPDATE where username = :P1_USER_ID;

  -- Read data from wwv_flow_files</span>    
  select    
    blob_content    
    into v_blob_data    
    from wwv_flow_files    
    where name = :P2_FILE_UPLOAD; 

  v_blob_len := dbms_lob.getlength(v_blob_data);    
  v_position := 1; 

  -- Read and convert binary to char</span>  
  WHILE ( v_position <= v_blob_len )    
  LOOP 
    begin  
        v_raw_chunk := dbms_lob.substr(v_blob_data,c_chunk_len,v_position);    
        v_char :=  chr(hex_to_decimal(rawtohex(v_raw_chunk)));    
        v_line := v_line || v_char;    
        v_position := v_position + c_chunk_len;

      -- When a whole line is retrieved </span>   
      IF v_char = CHR(10) THEN
        LOOP  
          --Make sure there's something to replace  
          IF INSTR(v_line, '"', 1, 1) = 0 THEN  
            EXIT; -- If nothing to replace, exit loop and don't try  
          END IF;  
          --Find the position of the first and second quotes in the line of text  
          v_quote_pos1 := INSTR(v_line, '"', 1, 1);  
          v_quote_pos2 := INSTR(v_line, '"', 1, 2);  
          --Extract the inner string  
          v_enclosed_str := SUBSTR(v_line, v_quote_pos1 + 1, v_quote_pos2 - v_quote_pos1 - 1);  
          --perform the replacement  
          v_line := SUBSTR(v_line, 0, v_quote_pos1 - 1) || REPLACE(v_enclosed_str, ',', '<') || SUBSTR(v_line, v_quote_pos2 + 1);  
        END LOOP; 

        -- Convert comma to : to use wwv_flow_utilities </span>  
        v_line := REPLACE (v_line, ',', ':');  
        v_line := REPLACE (v_line, '<', ',');  
        v_line := REPLACE (trim(v_line), '-', NULL);  
        --v_line := REPLACE (trim(v_line), '"', NULL);  
        -- Convert each column separated by : into array of data </span>    
        v_data_array := wwv_flow_utilities.string_to_table (v_line);  
        --Check to see if the row of column headers has already been parsed through  
        IF(v_first_line_done != true)THEN   
          v_first_line_done := true;  
          --Check column order in spreadsheet  
          IF(v_data_array(1)    LIKE '%Username%' AND
              v_data_array(2)  LIKE '%NDN%' AND
              v_data_array(3)  LIKE '%PCFN%') THEN   
            v_error_cd := 0;  
            v_line := NULL;  
          ELSE  
            v_error_cd := 1;  
          END IF;  
        --If first line is done and the column order is correct then  
        ELSIF(v_first_line_done = true AND v_error_cd = 0) THEN   
          -- Insert data into target table </span>    
          EXECUTE IMMEDIATE 'insert into TEMP_MM_UPDATE   
          (USERNAME,
           RPT_FLAG,
           PCFN)
          values (:1,:2,:3)'   
           USING   
            v_data_array(1),   
            v_data_array(2),   
            v_data_array(3);    
           -- Clear out    
            v_line := NULL; v_sr_no := v_sr_no + 1; 
        END IF;  
      END IF;
    exception
      WHEN OTHERS then
        v_errmsg := SQLERRM;
        insert into temp_mm_update (username,error_desc)
        values (:P1_USER_ID, v_errmsg);
  END;
  END LOOP;

  DELETE FROM WWV_FLOW_FILES where name = :P2_FILE_UPLOAD;
  DELETE FROM TEMP_MM_UPDATE WHERE USERNAME IS NULL AND PCFN IS NULL;  
  IF(v_error_cd = 1) THEN  
    INSERT INTO temp_mm_update (USERNAME, ERROR_DESC)  
    VALUES (:P1_USER_ID, 'Error. Please check column order in spreadsheet.');  
  END IF;
EXCEPTION
  WHEN NO_DATA_FOUND THEN
    insert into temp_mm_update (username,error_desc)
    values (:P1_USER_ID, 'No Data Found.');
  WHEN OTHERS then
    v_errmsg := SQLERRM;
    insert into temp_mm_update (username,error_desc)
    values (:P1_USER_ID, v_errmsg);
END;

当我在上面的循环中放入异常时,该过程似乎从未完成,当我尝试删除表或类似的东西时,最终收到“ NOWAIT”错误。

如果我在循环后立即取出“ BEGIN”并在循环内也取出异常,则代码可以正常工作,但是我希望能够指定每条记录出了什么问题,而不是处理正确的记录然后在其后停止出现一条记录,该记录在一个仅接受6的列中具有9个值。

有人能帮忙吗?

谢谢,

史蒂文

编辑:
我改变了这一行:
ELSIF(v_first_line_done = true AND v_error_cd = 0)

ELSIF(v_first_line_done = true AND v_error_cd = 0 AND(v_data_array(1)不为null或v_data_array(1)不像'%-%'))
并且该过程完成了,但是当涉及引发和异常的记录时,以下所有记录都具有相同的异常。

我的CSV文件示例:
用户名NDN PCFN
DOOL0008 X 808461
DOOL0008 X 886332
DOOL0008 X 887223
DOOL0008 X 887992
DOOL0008 X 904959
DOOL0008 X 904959
DOOL0008 X 904968
DOOL0008 X 904968

因此,例如,如果列MM(其数据类型为VARCHAR2(1))在第三条记录上的值为“ XX”,并且将引发该值过大的异常,则对于记录4-8,同样的异常也会被提出。

通过玩弄我的代码,我发现了哪里出了问题。
我需要将以下行添加到我的异常代码块中:

v_line := NULL; v_sr_no := v_sr_no + 1; 

最终代码:

  DECLARE    
  v_blob_data       BLOB;    
  v_blob_len        NUMBER;    
  v_position        NUMBER;    
  v_raw_chunk       RAW(10000);    
  v_char      CHAR(1);    
  c_chunk_len   number       := 1;    
  v_line        VARCHAR2 (32767)        := NULL;    
  v_data_array      wwv_flow_global.vc_arr2;    
  v_rows number;    
  v_sr_no number := 1;  
  v_first_line_done boolean := false;  
  v_error_cd number :=0;  
  v_quote_pos1 NUMBER;  
  v_quote_pos2 NUMBER;  
  v_enclosed_str VARCHAR(200);
  v_errmsg VARCHAR2(4000);
BEGIN
  delete from TEMP_MM_UPDATE where username = :P1_USER_ID;

  -- Read data from wwv_flow_files</span>    
  select    
    blob_content    
    into v_blob_data    
    from wwv_flow_files    
    where name = :P2_FILE_UPLOAD; 

  v_blob_len := dbms_lob.getlength(v_blob_data);    
  v_position := 1; 

  -- Read and convert binary to char</span>  
  WHILE ( v_position <= v_blob_len )    
  LOOP 
    begin  
        v_raw_chunk := dbms_lob.substr(v_blob_data,c_chunk_len,v_position);    
        v_char :=  chr(hex_to_decimal(rawtohex(v_raw_chunk)));    
        v_line := v_line || v_char;    
        v_position := v_position + c_chunk_len;

      -- When a whole line is retrieved </span>   
      IF v_char = CHR(10) THEN
        LOOP  
          --Make sure there's something to replace  
          IF INSTR(v_line, '"', 1, 1) = 0 THEN  
            EXIT; -- If nothing to replace, exit loop and don't try  
          END IF;  
          --Find the position of the first and second quotes in the line of text  
          v_quote_pos1 := INSTR(v_line, '"', 1, 1);  
          v_quote_pos2 := INSTR(v_line, '"', 1, 2);  
          --Extract the inner string  
          v_enclosed_str := SUBSTR(v_line, v_quote_pos1 + 1, v_quote_pos2 - v_quote_pos1 - 1);  
          --perform the replacement  
          v_line := SUBSTR(v_line, 0, v_quote_pos1 - 1) || REPLACE(v_enclosed_str, ',', '<') || SUBSTR(v_line, v_quote_pos2 + 1);  
        END LOOP; 

        -- Convert comma to : to use wwv_flow_utilities </span>  
        v_line := REPLACE (v_line, ',', ':');  
        v_line := REPLACE (v_line, '<', ',');  
        v_line := REPLACE (trim(v_line), '-', NULL);  
        --v_line := REPLACE (trim(v_line), '"', NULL);  
        -- Convert each column separated by : into array of data </span>    
        v_data_array := wwv_flow_utilities.string_to_table (v_line);  
        --Check to see if the row of column headers has already been parsed through  
        IF(v_first_line_done != true)THEN   
          v_first_line_done := true;  
          --Check column order in spreadsheet  
          IF(v_data_array(1)    LIKE '%Username%' AND
              v_data_array(2)  LIKE '%NDN%' AND
              v_data_array(3)  LIKE '%PCFN%') THEN   
            v_error_cd := 0;  
            v_line := NULL;  
          ELSE  
            v_error_cd := 1;  
          END IF;  
        --If first line is done and the column order is correct then  
        ELSIF(v_first_line_done = true AND v_error_cd = 0) THEN   
          -- Insert data into target table </span>    
          EXECUTE IMMEDIATE 'insert into TEMP_MM_UPDATE   
          (USERNAME,
           RPT_FLAG,
           PCFN)
          values (:1,:2,:3)'   
           USING   
            v_data_array(1),   
            v_data_array(2),   
            v_data_array(3);    
           -- Clear out    
            v_line := NULL; v_sr_no := v_sr_no + 1; 
        END IF;  
      END IF;
    exception
      WHEN OTHERS then
        v_errmsg := SQLERRM;
        insert into temp_mm_update (username,error_desc)
        values (:P1_USER_ID, v_errmsg);
v_line := NULL; v_sr_no := v_sr_no + 1; 
  END;
  END LOOP;

  DELETE FROM WWV_FLOW_FILES where name = :P2_FILE_UPLOAD;
  DELETE FROM TEMP_MM_UPDATE WHERE USERNAME IS NULL AND PCFN IS NULL;  
  IF(v_error_cd = 1) THEN  
    INSERT INTO temp_mm_update (USERNAME, ERROR_DESC)  
    VALUES (:P1_USER_ID, 'Error. Please check column order in spreadsheet.');  
  END IF;
EXCEPTION
  WHEN NO_DATA_FOUND THEN
    insert into temp_mm_update (username,error_desc)
    values (:P1_USER_ID, 'No Data Found.');
  WHEN OTHERS then
    v_errmsg := SQLERRM;
    insert into temp_mm_update (username,error_desc)
    values (:P1_USER_ID, v_errmsg);
END;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM