ここではArray DML(バルク・バインド)の利用法を説明します。
大量のレコードを一度に更新するのに、ループの内部で1件更新のDML(INSERT文やUPDATE文など)を呼び出すのは、クライアントとOracleサーバ間での通信が何往復も発生してしまい非効率です。
1000件のデータをテーブルに挿入する処理の方法について、以下に3つの方法を比較しますが、DOAでは、Oracle8i以降で利用可能な
Array DML(バルク・バインド)を利用することができます。
- ループの中で1件挿入のSQLを実行する方法=最も遅い方法です
- 1000件分のINSERT文を、一つのPL/SQL無名ブロックに記述して一度に実行する方法
- Array DML を用いて、一括更新を行う方法(Oracle8i以降で有効)
1.ループの中で1件づつ挿入実行
以下の方法だと、TOracleQuery.Executeが1000回実行され、その都度、Oracleサーバとの通信が発生するため、パフォーマンス上は大変に不利です。大量のデータに対しては避けるべき方法でしょう。
procedure TForm1.Button1Click(Sender: TObject); // OracleQuery1.SQL = // INSERT INTO TableA // VALUES ( :KEY, :DATA ) var i: integer; begin for i := 0 to 999 do begin with OracleQuery1 do begin SetVariable('KEY', KeyValues[i]); SetVariable('DATA', DataValues[i]); Execute; end; end; end;
2.PL/SQL無名ブロックを使う方法
上記の方法と比べて、Executeは一回ですみますが、型変換などでSQLの組み立てには苦労するはずです。特に、文字列データ中に引用符が含まれる可能性がある場合は、思わぬバグが混入する可能性があり、おすすめできません
また、サーバ上でPL/SQLエンジンからSQLエンジンへの呼び出しが1000回発生するので、ベストのパフォーマンスは得られません
procedure TForm1.Button1Click(Sender: TObject); var S: string; i: integer; begin S := 'BEGIN' + #13#10; for i := 0 to 999 do begin S := S + 'INSERT INTO TableA Values(' + IntToStr(KeyValues[i]) + ',' + AnsiQuotedString(DataValues[i]) + ');' +#13#10; end; S := S + 'END;'; with OracleQuery1 do begin SQL.Text := S; Execute; end; end;
3.Array DML(バルク・バインド)の利用
Oracle8i以降では、PL/SQL文中で、FORALLステートメントを利用し、配列(PL/SQLテーブル)からのデータを使ってデータベースを一括更新することができます。(詳しくはPL/SQLリファレンスを、FORALLやバルク・バインドをキーワードに参照してください)
DOAでは、以下のように、変数に配列データを割り当てるだけで、(FORALL句を含むPL/SQLを記述することもなく)簡単に、この機能を使うことができます。
procedure TForm1.Button1Click(Sender: TObject); // OracleQuery1.SQL = // INSERT INTO TableA // VALUES ( :KEY, :DATA ) var KeyValueArray: Variant; DataValueArray: Variant; i: integer; begin KeyValueArray := VarArrayCreate([0, 999], varVariant); DataValueArray := VarArrayCreate([0, 999], varVariant); for i := 0 to 999 do begin KeyValueArray[i] := KeyValues[i]; DataValueArray[i] := DataValues[i]; end; with OracleQuery1 do begin SetVariable('KEY', KeyValueArray); SetVariable('DATA', DataValueArray); Execute; end; end;
-
TOracleQuery
- SetVariable: Variant配列を変数に割り付けることができます。
-
Execute:
SetVariableで割り付けられた変数がVariant配列であった場合は、ArrayDMLとして、配列の各要素について同じSQLを実行します -
OnArrayError イベント:
ArrayDMLによるデータ更新途中の例外を処理します。エラー個所とエラー内容を検出でき、必要に応じて処理の中断・続行をコントロールできます。 -
ExecuteArray(Index,Count):
与えられたIndexとCountに基づいて、配列で与えられた複数件のデータ中の一部について、一括更新を行います。(全件について更新する場合はExecuteでよいので、あえてExecuteArrayを使う必要はありません)