我循环遍历表的列表并更新每个表中的列列表。是否可以并行执行循环,即一次更新多个表。
FOR Table_rec IN Table_list_cur
LOOP
--Check if the table is partitioned
IF Check_if_partitioned (Table_rec.Table_name, Table_rec.Owner)
THEN
--If Yes, loop through each parition
EXECUTE IMMEDIATE
'Select partition_name from USER_TAB_PARTITIONS where table_name = '''
|| Table_rec.Table_name
|| ''' and owner = '''
|| Table_rec.Owner
|| ''''
BULK COLLECT INTO L_part;
FOR I IN L_part.FIRST .. L_part.LAST
LOOP
--Update each parition
DBMS_OUTPUT.Put_line ('V_sql_stmt' || V_sql_stmt);
V_sql_stmt :=
'UPDATE /*+ PARALLEL(upd_tbl,4) */ '
|| Table_rec.Table_name
|| ' PARTITION ('
|| L_part (I)
|| ') upd_tbl'
|| ' SET '
|| V_sql_stmt_col_list;
DBMS_OUTPUT.Put_line ('V_sql_stmt' || V_sql_stmt);
EXECUTE IMMEDIATE V_sql_stmt;
END IF;
END LOOP;
END LOOP;
答案 0 :(得分:4)
不直接,没有。
您可以获取循环的内容,将其分解为存储过程调用,然后提交一系列作业以执行将异步运行的实际处理。使用dbms_job
包以便作业提交是事务的一部分,这看起来像
CREATE OR REPLACE PROCEDURE do_update( p_owner IN VARCHAR2,
p_table_name IN VARCHAR2 )
AS
BEGIN
<<your dynamic SQL>>
END;
然后运行循环以提交作业
FOR Table_rec IN Table_list_cur
LOOP
--Check if the table is partitioned
IF Check_if_partitioned (Table_rec.Table_name, Table_rec.Owner)
THEN
dbms_job.submit( l_jobno,
'begin do_update( ''' || table_rec.owner || ''', ''' || table_rec.table_name || '''); end;' );
END IF;
END LOOP;
commit;
运行commit
后,各个表作业将开始运行(运行的数量将由job_queue_processes
参数控制),而其余的排队等待。
现在,那说,你的方法似乎有点过时了。首先,明确指定分区名称几乎没用。您几乎肯定想要提交单个UPDATE
语句,省略分区名称,并让Oracle并行地对各个分区进行更新。每个分区运行一个更新语句而忽略了分区的目的。如果你真的想为每个分区使用4个并行线程,那么你可能不希望并行运行许多更新。并行性的一点是可以允许一个语句占用系统资源的很大一部分。如果你真的想要,比如同时运行16个分区级更新,并且每个更新运行4个从属服务器,那么让Oracle运行64个从属服务器进行单个更新(或者你真正想要的任何数量的从服务器)会更有意义。根据您希望为系统必须执行的所有其他操作留出多少资源来投入此特定任务。