2017-09-11 3 views
0

아래 코드를 사용하여 APEX 5를 사용하여 csv 파일에서 db 테이블로 데이터를 업로드하지만 .csv 파일이 매우 크기 때문에 성능이 매우 느립니다. 아래 코드에서 forall 문을 사용하면 쿼리를 더 빠르게 실행할 수 있습니까? 나는 forall로 즉각적인 명령문을 대체하려고했지만 그것은 작동하지 않았다. 누군가 나를 인도 할 수 있습니까?APEX 응용 프로그램에서 csv 파일의 대량 데이터 삽입에 대한 사용법

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_filename   VARCHAR2 (2000) 
          := APEX_UTIL.get_session_state ('P4_FILE_BROWSE'); 
    v_idx    NUMBER; 
    v_first_line_done BOOLEAN := FALSE; 
    v_error_cd   NUMBER := 0; 

    TYPE my_rec IS RECORD 
    (
     company_code XXX_COMP_TABLE.company_code%TYPE, 
     cost_center XXX_COMP_TABLE.cost_center%TYPE, 
     user_name  XXX_COMP_TABLE.user_name%TYPE, 
     start_date  XXX_COMP_TABLE.effective_start_date%TYPE, 
     end_date  XXX_COMP_TABLE.effective_end_Date%TYPE 
    ); 

    TYPE v_coll_rec IS TABLE OF my_rec  INDEX BY PLS_INTEGER; 

    v_col1 v_coll_rec; 

BEGIN 
    SELECT blob_content 
    INTO v_blob_data 
    FROM apex_application_temp_files 
    WHERE name = v_filename; 

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

    --wwv_flow.debug('v_position'||v_position); 
    LOOP 
     v_idx := DBMS_LOB.INSTR (v_blob_data, '0A', v_position); 

     -- wwv_flow.debug('v_idx'||v_idx); 
     IF v_idx = 0 
     THEN 
     wwv_flow.debug ('in if'); 
     v_line := 
      UTL_RAW.cast_to_varchar2 (
       DBMS_LOB.SUBSTR (v_blob_data, 32767, v_position)); 
     ELSE 
     -- wwv_flow.debug('in else'); 
     v_line := 
      UTL_RAW.cast_to_varchar2 (
       DBMS_LOB.SUBSTR (v_blob_data, v_idx - v_position, v_position)); 
     END IF; 

     wwv_flow.debug ('v_line' || v_line); 
     EXIT WHEN v_idx = 0; 
     v_position := v_idx + 1; 
     v_line := REPLACE (v_line, ',', ':'); 
     v_data_array := wwv_flow_utilities.string_to_table (v_line); 

     IF (v_first_line_done != TRUE) 
     THEN 
     v_first_line_done := TRUE; 

     --wwv_flow.debug('v_data_array(5) '||v_data_array(5)); 
     IF  v_data_array (1) = 'COMPANY_CODE' 
      AND v_data_array (2) = 'COST_CENTER_CODE' 
      AND v_data_array (3) = 'USER_NAME' 
      AND v_data_array (4) = 'EFFECTIVE_START_DATE' --AND v_data_array(5) = 'EFFECTIVE_END_DATE' 
     THEN 
      v_error_cd := 0; 
     ELSE 
      v_error_cd := 1; 
     END IF; 
     ELSIF (v_first_line_done = TRUE AND v_error_cd = 0) 
     THEN 
     FORALL indx IN 1 .. v_col1.COUNT 
      INSERT 
       into XXX_COMP_TABLE 
      VALUES v_col1 (indx); 
     END IF; 

     v_line := NULL; 
     v_sr_no := v_sr_no + 1; 
    END LOOP; 
END; 
+0

APEX (5)는이 질문에 무관하다 - 태그 제거. –

+0

'forall' 코드를 보여주십시오. 정적 SQL에 대해서'execute immediate'을 사용할 이유는 없습니다. –

+0

큰 코드 파일을이 코드로 APEX를 통해 db 테이블에 업로드하려고합니다. 성능 문제로 forall 문으로이 쿼리를 조정할 것을 요청 받았지만이 코드에서 forall 문을 사용하는 방법을 모르겠습니다. 나는 시도했지만 아직 forall 문을 삽입하는 방법이 혼란 스럽기 때문에 forall 코드를 개발할 수 없었다. 이걸 안내 해줄 수 있니? – user3849885

답변

0
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_filename  VARCHAR2(2000) := apex_util.get_session_state('P4_FILE_BROWSE'); 
    v_idx    NUMBER; 
    v_first_line_done BOOLEAN := false; 
    v_error_cd  NUMBER :=0; 

    TYPE my_rec IS RECORD (company_code XXX_COMP_TABLE.company_code%type , cost_center XXX_COMP_TABLE.cost_center%type , 
    user_name XXX_COMP_TABLE.user_name%type , start_date XXX_COMP_TABLE.effective_start_date%type, end_date XXX_COMP_TABLE.effective_end_Date%type); 
    TYPE v_coll_rec IS TABLE OF my_rec INDEX BY PLS_INTEGER; 
BEGIN 

    SELECT blob_content 
    INTO v_blob_data 
    FROM apex_application_temp_files 
    WHERE name = v_filename; 
    v_blob_len := dbms_lob.getlength(v_blob_data); 
    v_position := 1; 
    --wwv_flow.debug('v_position'||v_position); 
    LOOP 
    v_idx := dbms_lob.instr(v_blob_data, '0A', v_position); 
    -- wwv_flow.debug('v_idx'||v_idx); 
    IF v_idx = 0 THEN 
     wwv_flow.debug('in if'); 
     v_line := utl_raw.cast_to_varchar2(dbms_lob.substr(v_blob_data, 32767, v_position)); 
    ELSE 
    -- wwv_flow.debug('in else'); 
     v_line := utl_raw.cast_to_varchar2(dbms_lob.substr(v_blob_data, v_idx - v_position, v_position)); 
    END IF; 
    wwv_flow.debug('v_line'||v_line); 
    EXIT 
    WHEN v_idx    = 0; 
    v_position   := v_idx + 1; 
    v_line    := REPLACE (v_line, ',', ':'); 
    v_data_array   := wwv_flow_utilities.string_to_table (v_line); 
    IF(v_first_line_done != true) THEN 
     v_first_line_done := true; 

     --wwv_flow.debug('v_data_array(5) '||v_data_array(5)); 
      IF v_data_array(1) = 'COMPANY_CODE' AND v_data_array(2) = 'COST_CENTER_CODE' AND v_data_array(3) = 'USER_NAME' 
           AND v_data_array(4) = 'EFFECTIVE_START_DATE' --AND v_data_array(5) = 'EFFECTIVE_END_DATE' 
           THEN 
      v_error_cd  := 0; 
      ELSE 
      v_error_cd := 1; 
      END IF;     
    ELSIF(v_first_line_done = true AND v_error_cd = 0) THEN  
    FORALL indx IN 1 .. v_coll_rec.COUNT 
INSERT INTO 
(SELECT company_code, 
cost_center, 
user_name , 
start_date, 
end_date 
FROM XXX_COMP_TABLE 
) 
VALUES v_coll_rec (indx) ;   
    END IF; 
    v_line := NULL; v_sr_no := v_sr_no + 1; 
END LOOP; 
END; 
+0

'v_col1 v_coll_rec;'을 (를) 생성 한 변수를 delcare하는 것을 잊어 버렸고 잘못된 형식을 직접 사용했습니다. 이것을 선언에 추가하고 코드의 모든 위치에서'v_coll_rec'을'v_col1'으로 대체하십시오. 삽입 할 항목이 잘못되었습니다 – XING

+0

@XING 코드를 확인해 주셔서 감사합니다. 삽입 문에 대한 오류가 나타납니다. PL/SQL : ORA-00947 : 값이 충분하지 않습니다. – user3849885

+0

위의 내용을 확인하십시오. 귀하의 게시 코드에 따라 수정했습니다 – XING

관련 문제