环境:11g
create table emp_copy
as
select empno, ename, job, hiredate from emp where 1 = 2;
1.整体
--简写
declare
cursor c_emps is
select empno, ename, job, hiredate from emp;
type emp_aat is table of c_emps%rowtype
index by pls_integer;
aa_emps emp_aat;
begin
open c_emps;
fetch c_emps bulk collect into aa_emps;
close c_emps;
forall i in 1 .. aa_emps.count
insert /*+ append_values*/ into emp_copy
values aa_emps(i);
dbms_output.put_line(
to_char(sql%rowcount) || ' rows inserted.'
);
end;
等价于:(指定字段)
declare
cursor c_emps is
select empno, ename, job, hiredate from emp;
type emp_aat is table of c_emps%rowtype ;
aa_emps emp_aat;
begin
open c_emps;
fetch c_emps bulk collect into aa_emps;
close c_emps;
forall i in 1 .. aa_emps.count
insert /*+ append_values*/ into emp_copy
(empno, ename, job, hiredate)
values
(aa_emps(i).empno,
aa_emps(i).ename,
aa_emps(i).job,
aa_emps(i).hiredate);
end;
支持append_values
2.指定字段,indices of可以跳过不存在的值
create table emp_copy
as
select empno, ename, job, hiredate from emp where 1 = 2;
select * from emp_copy;
declare
cursor c_emps is
select empno, ename, job, hiredate from emp;
type emp_aat is table of c_emps%rowtype
index by pls_integer;
aa_emps emp_aat;
begin
/* bulk fetch sample data... */
open c_emps;
fetch c_emps bulk collect into aa_emps;
close c_emps;
forall i in indices of aa_emps
insert into emp_copy
(empno, ename, job, hiredate)
values
(aa_emps(i).empno,
aa_emps(i).ename,
aa_emps(i).job,
aa_emps(i).hiredate);
dbms_output.put_line(
to_char(sql%rowcount) || ' rows inserted.'
);
end;
一样,支持/*+ append_values*/实测
3.指定字段,使用动态sql
declare
cursor c_emps is
select empno, ename, job, hiredate from emp;
--这里使不使用index by pls_integer效果一样;
type emp_aat is table of c_emps%rowtype index by pls_integer;
aa_emps emp_aat;
--动态sql 一样支持append_values
v_sql varchar2(20000):='insert /*+ append_values*/ into emp_copy (empno, ename, job, hiredate) values(:1,:2,:3,:4)';
begin
open c_emps;
fetch c_emps bulk collect into aa_emps;
close c_emps;
forall i in 1 .. aa_emps.count
execute immediate v_sql using aa_emps(i).empno,
aa_emps(i).ename,
aa_emps(i).job,
aa_emps(i).hiredate;
end;
支持append_values;
4.forall 也支持 insert into..select方式,可以指定字段插入
但是不支持append方式
实测这里append和append_values效果一样;
insert /*+append_values*/ into emp_copy
select empno, ename, job, hiredate from emp where rowid='AAAUVnAAEAAAiOHAAB';
方式1:一次提交
declare
cursor c_emps is
select rowid rid from emp;
v_tab dbms_sql.Urowid_Table;
begin
open c_emps;
fetch c_emps bulk collect
into v_tab;
close c_emps;
forall i in 1 .. v_tab.count
insert
into emp_copy
select empno, ename, job, hiredate from emp where rowid = v_tab(i);
dbms_output.put_line(sql%rowcount || ' rows inserted.');
commit; --放在sql%rowcount后面,否则得不到行数
end;
方式2:分批提交,相对完整的写法
declare
cursor c_emps is
select rowid rid from emp;
v_tab dbms_sql.Urowid_Table;
v_limit pls_integer := 5;
v_count pls_integer:=0;
begin
open c_emps;
loop
v_count:=v_count+1;
fetch c_emps bulk collect
into v_tab limit v_limit;
forall i in 1 .. v_tab.count
insert
into emp_copy
select empno, ename, job, hiredate from emp where rowid = v_tab(i);
dbms_output.put_line('第'||v_count||'次循环:'||(sql%rowcount) || ' rows inserted.');
commit;
exit when c_emps%notfound;
end loop;
close c_emps;
exception when
others then
dbms_output.put_line(sqlerrm||dbms_utility.format_error_backtrace);
end;
输出:
第1次循环:5 rows inserted.
第2次循环:5 rows inserted.
第3次循环:2 rows inserted.
更新和删除同理可以使用上面的方式
小结:
对于插入操作效率,优先考虑cats,其次merge into+append_values
如果内存不足,则使用批量提交+append_values;
对于批量提交:
如果集合里面的值不连续,那么用indices of;
如果连续就要正常的Insert into values就可以了,
第4种方式不支持append,且查2遍,效率并不好,不推荐;
如果待查询的sql是动态的,就使用动态sql;
对于更新操作效率:
rowid分片效率最高,只是操作稍麻烦点
然后手动查rowid结合批量更新或者merge into
然后自动任务DBMS_PARALLEL_EXECUTE
如有说的不对的地方,还请指正,谢谢
Q:279907389