對於數據量較大的插入操作可采用此種方法操作,注意:
- limit減少內存占用,如果數據量較大一次性全部加載到內存中,對PGA來說壓力太大,可采用limit的方法一次加載一定數量的數據,建議值通常為1000。使用limit時注意,循環的時候如果用while cursor_name%found loop,對於最后一次fetch的數據量不足設定值1000,%found條件就會不成立。示例使用v_oid_lst.count > 0作為判斷條件。
-
在寫plsql代碼塊,定義數值變量時,建議采用pls_integer類型,或者simple_integer類型,區別:
oracle9i之前有binary_integer類型,和11g中引入的pls_integer數值范圍相同:-2147483647~+2147483647,但pls_integer有更高的性能。兩者性能均優於number類型。
Oracle中也引入了simple_integer類型,不過不能包含null值,范圍:-2147483648~2147483647,性能優於pls_integer。
- 使用ref cursor。
- 使用綁定變量。
- 自定義table類型。
- Bulk collect into加載到內存中,處理完業務邏輯后forall批量插入到數據表中。
- Forall可以使用returning bulk collect into,且可使用sql%rowcount返回其更新行數。
-
type numbers is table of number index by binary_integer/pls_integer/simple_integer; 其作用是:
加了"index by binary_integer "后,numbers類型的下標就是自增長,numbers類型在插入元素時,不需要初始化,不需要每次extend增加一個空間。
而如果沒有這句話"index by binary_integer",那就得要顯示對初始化,且每插入一個元素到numbers類型的table中時,都需要先extend。
- 關於table、record、varray的詳細使用,參考:http://blog.csdn.net/liangweiwei130/article/details/38223319
示例代碼:
SQL Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
|
declare type v_t_oid is table of ljz_all_objects.object_id%type; v_oid_lst v_t_oid; type v_t_cur_oid is ref cursor; v_cur_oid v_t_cur_oid; v_cnt simple_integer := 1000; begin open v_cur_oid for 'select object_id from ljz_all_objects where object_id>:1' using 1; fetch v_cur_oid bulk collect into v_oid_lst limit v_cnt; while v_oid_lst.count > 0 loop for i in 1 .. v_oid_lst.count loop --業務處理邏輯 v_oid_lst(i) := v_oid_lst(i) + 1; end loop; forall i in v_oid_lst.first .. v_oid_lst.last insert into ljz_test (col) values (v_oid_lst(i)); fetch v_cur_oid bulk collect into v_oid_lst limit 1000; commit; end loop; close v_cur_oid; end; |
定義record類型,多列插入:
SQL Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
|
declare type v_t_r is record( object_id ljz_all_objects.object_id%type, object_name ljz_all_objects.object_name%type); v_r v_t_r; type v_t_oid is table of v_t_r index by simple_integer; v_oid_lst v_t_oid; v_oid_lst1 v_t_oid; type v_t_cur_oid is ref cursor; v_cur_oid v_t_cur_oid; v_cnt simple_integer := 1000; begin open v_cur_oid for 'select object_id,object_name from ljz_all_objects where object_id>:1' using 1; fetch v_cur_oid bulk collect into v_oid_lst limit v_cnt; while v_oid_lst.count > 0 loop for i in 1 .. v_oid_lst.count loop --業務處理邏輯 v_oid_lst(i).object_id := v_oid_lst(i).object_id + 1; end loop; forall i in v_oid_lst.first .. v_oid_lst.last insert into ljz_test (num, col) values (v_oid_lst(i).object_id, v_oid_lst(i).object_name) returning num, col bulk collect into v_oid_lst1; dbms_output.put_line('v_oid_lst1.count=' || v_oid_lst1.count || ',隱式游標rowcount:' || sql%rowcount); fetch v_cur_oid bulk collect into v_oid_lst limit 1000; commit; end loop; close v_cur_oid; end; |
批量update、delete、insert,異常捕獲:
SQL Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
|
|
--表說明:ljz_all_objects數據來自:all_objects;test1有兩個字段:col字符型最大長度10,num數值型。 declare type v_tp_rec is record( object_name varchar2(50), object_id number); type v_tp_obj is table of v_tp_rec index by simple_integer; v_objs v_tp_obj; type v_cur_tp_obj is ref cursor; v_cur_obj v_cur_tp_obj; v_lmt_cnt simple_integer := 1000; v_rn simple_integer := 10; begin open v_cur_obj for 'select object_name,object_id from ljz_all_objects where rownum<=:1 order by decode(object_id,117,300)' using v_rn; fetch v_cur_obj bulk collect into v_objs limit v_lmt_cnt; while v_objs.count > 0 loop dbms_output.put_line('v_objs.first=' || v_objs.first); for i in v_objs.first .. v_objs.last loop v_objs(i).object_id := v_objs(i).object_id + 1; end loop; begin --批量插入,test1表col字段大小為10,這里有異常 forall i in v_objs.first .. v_objs.last insert into test1 (col, num) values (v_objs(i).object_name, v_objs(i).object_id); exception --如果不對forall執行異常捕獲,數據執行過程中如果出錯,會全部回滾, --如果捕獲異常,假如數據在執行第5條時出錯,則前4條數據執行成功,第5條及其后面所有數據都不再執行。 when others then --sql%bulk_exceptions.count記錄異常數量,如果沒有使用save exceptions,若有異常該值為1,如下輸出是1 dbms_output.put_line('sql%bulk_exceptions.count:' || sql%bulk_exceptions.count); end; --批量更新 forall i in v_objs.first .. v_objs.last update test1 set num = v_objs(i).object_id where col = v_objs(i).object_name; --對於批量更新,除了sql%rowcount幾個隱式游標屬性外,另具有sql%bulk_rowcount屬性,用來記錄第N行更新影響行數。 if sql%bulk_rowcount(2) > 0 then dbms_output.put_line('第二行更新影響行數:' || sql%bulk_rowcount(2)); end if; begin --批量刪除,使用save exceptions,和之前異常捕獲區別:使用save exceptions異常后可繼續執行直至結束。 --新屬性:sql%bulk_exceptions.count、sql%bulk_exceptions(i).error_index、sql%bulk_exceptions(i).error_code forall i in v_objs.first .. v_objs.last save exceptions delete from test1 where v_objs(i).object_id / 0 > 1; exception when others then for i in 1 .. sql%bulk_exceptions.count loop dbms_output.put_line('sql%bulk_exceptions(i).error_index:' || sql%bulk_exceptions(i) .error_index); dbms_output.put_line('sqlerrm sql%bulk_exceptions(i).error_code:' || sqlerrm(sql%bulk_exceptions(i).error_code)); end loop; end; fetch v_cur_obj bulk collect into v_objs limit v_lmt_cnt; end loop; close v_cur_obj; end; |