2016-09-15 71 views
1

基本上我在oracle 11g中有一個包處理一個文件並驗證並在多個表中插入信息, 爲了實現這個我創建一個存儲過程讀取文件並傳播信息,然後我打電話多個存儲過程到 驗證並在每個表中插入數據(每個表一個過程),每個SP在一個公共錯誤表中插入一條記錄,最後,我調用最後一個存儲過程來識別是否存在錯誤在通用錯誤表中生成一個包含這些錯誤的文件。並行執行oracle PL/SQL

現在...我試圖改善代碼,以儘量減少執行時間,然後我想到每個SP驗證並將信息插入到表中並不依賴於其他SP信息,所以我詢問是否有方法可以並行調用所有此SP。

今天

STORED PROCEDURE charge_file 
STORED PROCEDURE insert_table1 
STORED PROCEDURE insert_table2 
STORED PROCEDURE insert_table3 ... 
STORED PROCEDURE return_file 

我所試圖做的

STORED PROCEDURE charge_file 
STORED PROCEDURE insert_table1 - STORED PROCEDURE insert_table2 - STORED PROCEDURE insert_table3 ... 
STORED PROCEDURE return_file 

回答

2

作爲例如使用parallel_execute:

create table proc_map (proc_id number, proc_name varchar2(64), is_active varchar2(1)); 

insert into proc_map (proc_id, proc_name, is_active) values (1, 'insert_table1', 'Y'); 
insert into proc_map (proc_id, proc_name, is_active) values (2, 'insert_table2', 'Y'); 
insert into proc_map (proc_id, proc_name, is_active) values (3, 'insert_table3', 'Y'); 


create or replace procedure p_run_proc (ip_start in number, ip_end in number) is 
    v_proc_name proc_map.proc_name%type; 
begin 
    begin 
    select t.proc_name into v_proc_name 
    from proc_map t 
    where t.proc_id = ip_start; 
    exception 
    when no_data_found then null; 
    when too_many_rows then null; 
    end; 

    if v_proc_name is not null 
    then 
     execute immediate 'begin ' || v_proc_name || '; end;'; 
    end if; 
end; 

declare 
    v_task_name varchar2(4000) := dbms_parallel_execute.generate_task_name; 
    v_sql varchar2(4000); 
    v_run varchar2(4000); 
    v_thread_count number; 
    v_task_status number; 
begin 
    dbms_parallel_execute.create_task (task_name => v_task_name); 

    v_sql := 'select t.proc_id as num_col 
        ,t.proc_id as num_col 
      from proc_map t 
      where t.is_active = ''Y'' 
      order by t.proc_id'; 

    dbms_parallel_execute.create_chunks_by_SQL (task_name => v_task_name, sql_stmt => v_sql, by_rowid => false); 

    v_run := 'begin p_run_proc (ip_start => :start_id, ip_end => :end_id); end;'; 

    select count(*) into v_thread_count 
    from proc_map t 
    where t.is_active = 'Y'; 

    dbms_parallel_execute.run_task (task_name => v_task_name 
           ,sql_stmt => v_run 
           ,language_flag => dbms_sql.native 
           ,parallel_level => v_thread_count); 

    v_task_status := dbms_parallel_execute.task_status (task_name => v_task_name); 

    if v_task_status = dbms_parallel_execute.FINISHED 
    then 
     dbms_parallel_execute.drop_task (task_name => v_task_name); 
    else 
     raise_application_error (-20001, 'ORA in task ' || v_task_name); 
    end if; 

end;