2016-09-15 73 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;