為了滿足大數據量的批量插入這個需求,最近研究了一下Oracle數據庫的批量插入這塊兒,本篇先介紹一下這兩天來所了解到的以及一次不成功的C++進行存儲過程批量插入方案。
一.Oracle處理批量插入存儲過程
1.Oracle處理批量插入涉及到的相關概念有:Type、bulk collect、Oracle數組等。現在對它們依次簡單的介紹一下。
1)Type
Type主要用於用戶建立Oracle自定義類型。
Type常用的自定義類型介紹:
A.子類型
類似與全局定義的常量,只要改一處地方,與此常量相關的地方都修改了。一般子類型常用於貨幣類型的定義,如number(10,5),我們可以定義子類型:subtype hb_num is number(10,5),這樣貨幣的精度需要修改時,不用搜遍全部地方,只需進行一處修改即可。
B.Object類型
定義了一個員工類
create or replace type type_employee as object( id varchar2(36), name varchar2(50), age integer(3), experience varchar2(4000) );可以使用該類型創建表,如下:
create table employee of type_employee --則創建出了員工表使用該Object類型,還可以創建其他類型,如下
--創建數組類型 create or replace type type_employee_arr as table of type_employee更多詳細的內容請看:Oracle Type介紹
2)oracle數組
A.固定數組
type v_arr is varray(10) of varchar2(50);
B.可變數組
type v_arr is table of varchar2(50);
C.多維數組
--下面的定義如同1)中的創建數組的情況,不過兩者作用的范圍不同 --以object對象建立的數組可用作任何地方 --以表定義的type不能定義全局的type,只可在函數、存儲過程定義變量處定義 type v_table is table of poco_test%rowtype index by binary_integer;3)bulk collect
bulk collect用於一次取出一個數據集合,比游標取數據效率高,但是其需要大量的內存,可以使用select into、fetch into、returning into語句到bulk collect中
declare type v_table is table of poco_test%rowtype index by binary_integer; v_values v_table; begin select * bulk collect into v_values from poco_test; end;2.了解了相關的基本內容後,下面為本次研究Oracle批量插入的示例代碼
create or replace type poco_test_object_type as object( id varchar2(36), name varchar2(200),code varchar(200));
create or replace type poco_test_object_arr_type as table of poco_test_object_type;
create or replace procedure poco_test_arr_pro(v_arr in poco_test_object_arr_type) is test_obj poco_test_object_type;
begin for idx in v_arr.first()..v_arr.last loop test_obj := v_arr(idx); insert into poco_test values(test_obj.id,test_obj.name,test_obj.code); end loop; end poco_test_arr_pro;
declare abc poco_test_object_arr_type; o poco_test_object_type; begin o:=poco_test_object_type(1,2,3); abc:=poco_test_object_arr_type(o,o,o); poco_test_arr_pro(abc); end;
二、JDBC調用參數為數組類型的存儲過程示例代碼
public class PocoTestModel { private String id; private String name; private String code; ........ }
Connection con = null; CallableStatement cstmt = null; try { con = OracleConnection.getConn(); List通過繼承oracle.sql.ORAData接口,實現toDatum函數,可以簡化執行的代碼編寫orderList = new ArrayList (); for(int i=0;i<100000;i++){ orderList.add(new PocoTestModel(UUID.randomUUID().toString(),"name"+i,"code"+i)); } StructDescriptor recDesc = StructDescriptor.createDescriptor("poco_test_object_type", con); ArrayList pstruct = new ArrayList (); for (PocoTestModel ord:orderList) { Object[] record = new Object[3]; record[0] = ord.getId(); record[1] = ord.getName(); record[1] = ord.getCode(); STRUCT item = new STRUCT(recDesc, con, record); pstruct.add(item); } ArrayDescriptor tabDesc = ArrayDescriptor.createDescriptor("poco_test_object_arr_type", con); ARRAY vArray = new ARRAY(tabDesc, con, pstruct.toArray()); cstmt = con.prepareCall("{call poco_test_arr_pro(?)}"); cstmt.setArray(1, vArray); cstmt.execute(); con.commit(); }catch ....
public class PocoTestModel implements ORAData { private String id; private String name; private String code; public static final String _ORACLE_TYPE_NAME = "poco_test_object_type"; protected MutableStruct _struct; static int[] _sqlType = { OracleTypes.VARCHAR, OracleTypes.VARCHAR }; static ORADataFactory[] _factory = new ORADataFactory[_sqlType.length]; public PocoTestModel() { _struct = new MutableStruct(new Object[_sqlType.length], _sqlType, _factory); } public Datum toDatum(Connection conn) throws SQLException { _struct.setAttribute(0, this.id); _struct.setAttribute(1, this.name); _struct.setAttribute(1, this.code); return _struct.toDatum(conn, _ORACLE_TYPE_NAME); } public PocoTestModel(String id,String name, String code) { this(); this.id = id; this.name = name; this.code = code; } .... } Connection con = null; CallableStatement cstmt = null; try { con = OracleConnection.getConn(); System.out.println(new Date()); ListorderList = new ArrayList (); for(int i=0;i<100000;i++){ orderList.add(new PocoTestModel(UUID.randomUUID().toString(),"name"+i,"code"+i)); } ArrayDescriptor tabDesc = ArrayDescriptor.createDescriptor("poco_test_object_arr_type", con); ARRAY vArray = new ARRAY(tabDesc, con, orderList.toArray()); cstmt = con.prepareCall("{call poco_test_arr_pro(?)}"); cstmt.setArray(1, vArray); cstmt.execute(); con.commit(); }catch ...