SQLJ アプリケーションでのバッチ更新の実行
これは、 IBM® Data Server Driver for JDBC and SQLJ SQLJでの一括更新をサポートしています。 表の各行を 1 行ずつ更新する代わりにバッチ更新を使用すれば、SQLJ によって一群の更新を同時に実行できます。
このタスクについて
- 検索の INSERT、UPDATE、または DELETE、または MERGE の各ステートメント
- CREATE、ALTER、DROP、GRANT、REVOKE の各ステートメント
- 入力パラメーターだけを指定した CALL ステートメント
- 同じステートメントの各インスタンス
- 別々のステートメント
- 異なる数の入力パラメーターまたはホスト式を含んだステートメント
- 異なるデータ・タイプの入力パラメーターまたはホスト式を含んだステートメント
- 入力パラメーターまたはホスト式がないステートメント
バッチによる挿入を除くすべての場合について、バッチ中のステートメントの実行中にエラーが発生すると、残りのステートメントが実行され、バッチ中のすべてのステートメントが実行された後で BatchUpdateException がスローされます。
バッチによる挿入の場合、動作は次のとおりです。
- db2sqljcustomize を実行する際に、 atomicMultiRowInsert を DB2BaseDataSource.YES (1) に設定し、対象のデータサーバーが Db2 for z/OS® バッチ内のINSERT文の実行中にエラーが発生した場合、残りの文は実行されず、 BatchUpdateException がスローされます。
- db2sqljcustomize を実行する際に、 atomicMultiRowInsert を DB2BaseDataSource.YES (1) に設定しない場合、または対象のデータサーバーが Db2 for z/OS バッチ内のINSERT文の実行中にエラーが発生した場合、残りの文は実行され、バッチ内のすべての文の実行後に BatchUpdateException がスローされます。
警告に関する情報を取得するには、バッチの中に組み込むステートメントをサブミットするのに使用する ExecutionContext で ExecutionContext.getWarnings メソッドを使用します。 これで、各 SQLWarning オブジェクトのエラーに関する記述、SQLSTATE、およびエラー・コードを取得できます。
バッチに追加できないステートメントがプログラムに含まれているために、バッチが暗黙的に実行される場合は、バッチが実行されてから、その新しいステートメントが処理されます。 バッチの実行中にエラーが発生すると、バッチ実行の原因になったステートメントは実行されません。
プロシージャー
ステートメント・バッチの作成、実行、削除の基本手順は、以下のとおりです。
例
以下に示すのは、UPDATE ステートメントのバッチ実行の例です。 選択されたステートメントの右にある番号は、前述のステップに対応しています。#sql iterator GetMgr(String); // Declare positioned iterator
…
{
GetMgr deptiter; // Declare object of GetMgr class
String mgrnum = null; // Declare host variable for manager number
int raise = 400; // Declare raise amount
int currentSalary; // Declare current salary
String url, username, password; // Declare url, user ID, password
…
TestContext c1 = new TestContext (url, username, password, false); 1
ExecutionContext ec = new ExecutionContext(); 2
ec.setBatching(true); 3
#sql [c1] deptiter =
{SELECT MGRNO FROM DEPARTMENT};
// Assign the result table of the SELECT
// to iterator object deptiter
#sql {FETCH :deptiter INTO :mgrnum};
// Retrieve the first manager number
while (!deptiter.endFetch()) { // Check whether the FETCH returned a row
#sql [c1]
{SELECT SALARY INTO :currentSalary FROM EMPLOYEE
WHERE EMPNO=:mgrnum};
#sql [c1, ec] 4
{UPDATE EMPLOYEE SET SALARY=:(currentSalary+raise)
WHERE EMPNO=:mgrnum};
#sql {FETCH :deptiter INTO :mgrnum };
// Fetch the next row
}
ec.executeBatch(); 5
ec.setBatching(false); 6
#sql [c1] {COMMIT};
deptiter.close(); // Close the iterator
c1.close(); // Close the connection
}
以下に示すのは、INSERT ステートメントのバッチ実行の例です。 ATOMICTBL が次のように定義されているとします。
CREATE TABLE ATOMICTBL(
INTCOL INTEGER NOT NULL UNIQUE,
CHARCOL VARCHAR(10))また、この表には、2 および "val2" という値を持つ行が 1 つ既に含まれているものとします。 INTCOL の固有性制約のため、以下のコードを実行すると、バッチ中の 2 番目の INSERT ステートメントは失敗します。
ターゲットデータサーバーが Db2 for z/OS、 atomicMultiRowInsert を DB2BaseDataSource.YES に設定せずにこのアプリケーションをカスタマイズした場合、バッチ INSERT は非アトミックであるため、最初の値のセットがテーブルに挿入されます。 しかし、このアプリケーションが、atomicMultiRowInsert を DB2BaseDataSource.YES に設定してカスタマイズされているなら、バッチ INSERT はアトミックであり、最初の値セットは挿入されません。
選択されたステートメントの右にある番号は、前述のステップに対応しています。
…
TestContext ctx = new TestContext (url, username, password, false); 1
ctx.getExecutionContext().setBatching(true); 2,3
try {
for (int i = 1; i<= 2; ++i) {
if (i == 1) {
intVar = 3;
strVar = "val1";
{
if (i == 2) {
intVar = 1;
strVar = "val2";
}
#sql [ctx] {INSERT INTO ATOMICTBL values(:intVar, :strVar)}; 4
}
int[] counts = ctx.getExecutionContext().executeBatch(); 5
for (int i = 0; i<counts.length; ++i) {
System.out.println(" count[" + i + "]:" + counts[i]);
}
}
catch (SQLException e) {
System.out.println(" Exception Caught: " + e.getMessage());
SQLException excp = null;
if (e instanceof SQLException)
{
System.out.println(" SQLCode: " + ((SQLException)e).getErrorCode() + "
Message: " + e.getMessage() );
excp = ((SQLException)e).getNextException();
while ( excp != null ) {
System.out.println(" SQLCode: " + ((SQLException)excp).getErrorCode() +
" Message: " + excp.getMessage() );
excp = excp.getNextException();
}
}
}