日期:2014-05-16 浏览次数:20544 次
BULK COLLECT支持EMPLOYEES%rowtype形式
FORALL插入时不支持EMPLOYEES%rowtype形式,如果有多个字段,要定义多个数组来存放.
如果插入前有条件判断,可以用VALUES OF
?
?
用fetch .... limit??系统会根据limit的行数向源库逐批获取数据
关于 limit 参数
你可以根据你的实际来调整 limit 参数的大小,来达到你最优的性能。limit 参数会影响到 pga 的使用率。而且也可以在 fetch bulk 中省略 limit 参数,写成
fetch
all_contacts_cur bulk collect into v_contacts;
有些资料中是说,如果 不写 limit 参数,将会以数据库的 arraysize 参数值作为默认值。在 sqlplus 中用 show arraysize 可以看到该值默认为 15,set arraysize 256 可以更改该值。而实际上我测试不带 limit 参数时,外层循环只执行了一轮,好像不是 limit 15,所以不写 limit 参数时,可以去除外层循环,begin-end 部分可写成:
declare type RecTyp is RECORD( t dbms_sql.varchar2_table/*bill.hxz1.t%type*/, b dbms_sql.varchar2_table/*bill.hxz1.b%type*/); l_rec RecTyp; cursor c is select * from bill.hxz1; BEGIN open c; loop fetch c bulk collect into l_rec.t,l_rec.b limit 100; forall i in 1..l_rec.t.count insert into hxz2(t,b) values(l_rec.t(i),l_rec.b(i)); exit when c%notfound; end loop; commit; close c; end;
?
?
?
现在你的测试中出现新的错误ORA-06502: ? PL/SQL: ? 数字或值错误,这个问题出现最可能的原因是当最后一次fetch ? cur ? bulk ? collect ? into ? n ? limit ? 10000;的时候,找不到任何记录,所以n.first和n.last是空的,加一句控制就可以。 ?
我之前是把exit ? when ?
cur%notfound;放在for循环之前,但是后来发现问题,如果纪录总数不能整除limit参数,那么最后一部份纪录将不会被游标扫描到.
? ?
?
declare ?
? ? ? type ? curtype ? is ? ref ? cursor; ?
? ? ?
cur ? curtype; ?
? ? ? type ? ntype ? is ? table ? of ?
test.col1%type; ?
? ? ? n ? ntype; ?
? ? ? i ? number; ?
? begin ?
? ? ? dbms_output.disable; ?
? ? ?
dbms_output.enable(1000000); ?
? ? ? open ? cur ? for ? select ?
col1 ? from ? test; ?
? ? ?
dbms_output.put_line('第1条记录插入开始:'||to_char(sysdate,'hh24:mi:ss')); ?
? ? ? loop ?
? ? ? ? ? fetch ? cur ? bulk ? collect ? into ?
n ? limit ? 10000; ?
? ? ? ? ? if ? n.count ? > ? 0 ? then ?
? -- ? 检查n中的纪录数 ?
? ? ? ? ? ? ? ? ? for ? i ? in ?
n.first ? .. ? n.last ? loop ?
? ? ? ? ? ? ? ? ? ? ?
insert ? into ? test2 ? (col1,col2) ? values ? (n(i),n(i)*n(i)); ?
?
? ? ? ? ? ? ? ? end ? loop; ?
? ? ? ? ? end ? if; ?
? ? ? ? ? commit; ?
? ? ? ? ? exit ? when ? cur%notfound; ?
? ? ? end ? loop; ?
? ? ?
dbms_output.put_line('第'||cur%rowcount||'条记录插入结
束:'||to_char(sysdate,'hh24:mi:ss')); ?
? ? ? close ? cur; ?
?
end; ?
? / ?
? ?
? 你成功执行的那段代码中exit ? when放在 ? for ? i ?
in ? ...之前,和我加控制的效果是一样的,所以不出错。
?
?
?
?
常在SQL语句中给PL/SQL变量赋值叫做绑定(Binding),一次绑定一个完整的集合称为批量绑定(Bulk ? Binding)。 ?
? ?
? 批量绑定(Bulk ? binds)可以通过减少在PL/SQL和SQL引擎之间的上下文切换(context ?
switches ? )提高了性能. ?
? ?
? 批量绑定(Bulk ? binds)包括: ?
? (i)
? Input ? collections, ? use ? the ? FORALL ?
statement,一般用来改善DML(INSERT、UPDATE和DELETE) ? 操作的性能 ?
? (ii) ? Output
? collections, ? use ? BULK ? COLLECT ? clause,一般用来提高查询(SELECT)的性能 ?
? ?
? FORALL的语法如下: ?
? ?
? ?
? FORALL ? index ?
IN ? lower_bound..upper_bound ? sql_statement; ?
create or replace procedure cp_data2 as type TYPE_EMPLOYEES is table of EMPLOYEES%rowtype; V_EMPLOYEES TYPE_EMPLOYEES; begin select * bulk collect into V_EMPLOYEES from employees @DBLINK1 ; for i in 1 .. V_EMPLOYEES.count loop insert /*+ APPEND*/ into employee_cp (EMPLOYEE_ID, FIRST_NAME, LAST_NAME, EMAIL, PHONE_NUMBER, HIRE_DATE, JOB_ID, SALARY, COMMISSION_PCT, MANAGER_ID, DEPARTMENT_ID, BIRTHDAY) values (V_EMPLOYEES(i).EMPLOYEE_ID, V_EMPLOYEES(i).FIRST_NAME, V_EMPLOYEES(i).LAST_NAME, V_EMPLOYEES(i).EMAIL, V_EMPLOYEES(i).PHONE_NUMBER, V_