oracle-databaseoracle19c

DBMS_PARALLEL_EXECUTE insert multiple views in same table parallel


i want to insert the data from 7 views (defintely multiple views, less or more, depends...) into one table with DBMS_PARALLEL_EXECUTE, table structure and view structures are the same.

i am quite new how to handle this package and always facing the same error: variable not in select list, i tried different solutions and ending up with creating a wrapping procuedure dynamically but i do not getting my code to run:

  PROCEDURE load_data_as_task (
    strLoadTable varchar2,
    arrLoadViews arrv
    )
  AS
    strLoadTask       varchar2(80);
    strLoadView       varchar2(80);
    
    stmtWrapperProc   clob;
  BEGIN
  
    for lv in arrLoadViews.first..arrLoadViews.last loop
      
      -- set task name
      strLoadTask := arrLoadViews(lv)||'_task';

      -- creating wrapper procedure
      stmtWrapperProc := q'[
        CREATE OR REPLACE PROCEDURE insert_from_view(p_id number) AS
        BEGIN
          EXECUTE IMMEDIATE 'INSERT INTO ]'||strLoadTable||q'[ SELECT * FROM ]'||arrLoadViews(lv)||q'[';
        END;
        ]';
      execute immediate stmtWrapperProc;
      
      -- create Task
      DBMS_PARALLEL_EXECUTE.CREATE_TASK(strLoadTask);
      
      -- create one chunk per load view
      DBMS_PARALLEL_EXECUTE.CREATE_CHUNKS_BY_SQL(
        task_name => strLoadTask, 
        sql_stmt => 'SELECT ' || to_char(lv) || ' AS view_id FROM dual',
        by_rowid => false
        );

      DBMS_PARALLEL_EXECUTE.RUN_TASK(
        task_name => strLoadTask,
        sql_stmt => 'BEGIN insert_from_view(:start_id); END;',
        --sql_stmt => 'DECLARE dummy NUMBER; BEGIN dummy := :start_id; EXECUTE IMMEDIATE ''INSERT INTO '||strLoadTable||' SELECT * FROM '||arrLoadViews(lv)||'''; END;',
        language_flag => DBMS_SQL.NATIVE,
        parallel_level => 1
        );
      
    end loop;
  END;

the procedure is insinde a package, load views and target table already created.

it would be great if anyone can help me to achieve this or maybe know a simpler way to load data from different views in one table parallel (at the same time)

thanks in advance!


Solution

  • for anyone that is facing the same problem, i figured out a solution
    if using DBMS_PARALLEL_EXECUTE to insert from a view it is necessary to use the bind variables :start_id and :end_id to create chunks and use it in the insert statement, even for the whole view.

    here is a solution to create dummy chunks for each view and run as tasks:

    for lv in arrLoadViews.first..arrLoadViews.last loop     
          -- create Task
          DBMS_PARALLEL_EXECUTE.CREATE_TASK(strLoadTask);
    
          -- create one dummy chunk per load view, start_id and end_id must be set
          DBMS_PARALLEL_EXECUTE.CREATE_CHUNKS_BY_SQL(
            task_name => strLoadTask, 
            sql_stmt => 'SELECT 1 AS start_id, 1 as end_id FROM DUAL',
            by_rowid => false
            );
    
          -- create insert statement, start_id and end_id must be set as bind variable from dummy chunk
          stmtInsert := '
            INSERT INTO '||strLoadTable||' 
            SELECT * FROM '||arrLoadViews(lv)||' 
            WHERE :start_id = 1 AND :end_id = 1';
    
          DBMS_PARALLEL_EXECUTE.RUN_TASK(
            task_name => strLoadTask,
            sql_stmt => stmtInsert,
            language_flag => DBMS_SQL.NATIVE,
            parallel_level => 1
            );
    
    end loop;