ここでは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を使う必要はありません)
