SQL の forEach に関する考慮事項
EGL の forEach 文は
各行で EGL ステートメントを実行しながら、SQL 結果セットを読み取ります。
EGL の open 文または get 文を使用して、あらかじめ結果セットを作成しておく必要があります。
結果セットを使用できない場合、この文を処理することはできず、ハード入出力エラーが発生します。
ループは、次のイベントの 1 つが発生するまで継続します。
- すべての行が取り出される。
- exit 文が実行される。
- ハード・エラーまたはソフト・エラーが発生する。
ほとんどの場合、EGL ランタイムは最後のループの反復後に暗黙の SQL CLOSE 文を実行します。 この暗黙のステートメントは SQL システム変数を変更するため、forEach ステートメントの本文に SQL 関連のシステム変数の値を保存する必要があります。
EGL ランタイムは、forEach 文が noRecordFound 以外のエラーのために終了した場合には、 SQL CLOSE 文を実行しません。
構文

- label
- ラベル。後にコロンが続き、continue 文または exit 文で参照できます。詳しくは、 条件およびループ文を参照してください。
- sqlRecord
- 結果セットを作成した open 文または get 文で参照した SQL レコード変数。 SQL レコードまたは結果セット ID を指定する必要があります。
- resultSetID
- 現在の読み取り対象である結果セットを作成した open 文または get 文に指定した任意の識別子。
- target
- EGL が生成する SQL の INTO 文節では、ここに指定した情報を使用します。
これらは、結果セットの各行について forEach 文が生成する SQL の FETCH 文の値を受け取る EGL ホスト変数です。
レコード名を指定すると、EGL はそのレコード内のすべてのフィールドを使用します。
ホスト変数の名前の前にコロンを挿入しないでください (ホスト変数を参照)。
このコンテキストで INTO 文節を作成すると、関連する open 文からすべての INTO 文節がオーバーライドされます。
- statement
- 結果セットの各行について実行される、EGL 言語の文。
例
以下に、カスタマー・ファイル内のデータベース・レコードを変更するプロセスの例を示します。
vgVar.handleHardIOErrors = 1;
try
open myResults for myCustomer
with #sql{
SELECT customer_number, customer_name
FROM Customer
WHERE customer_number >= :myCustomer.customerNumber
FOR UPDATE OF customer_name
}
into myCustomer.customerNumber, myCustomer.customerName;
onException(sqlEx SQLException)
myErrorHandler(6); // プログラムを終了する
end
try
forEach (from myResults)
// 最初に姓を作成する
reverseName(myCustomer.customerName);
try
execute
#sql{
UPDATE Customer
SET customer_name = :myCustomer.customerName
WHERE CURRENT OF myResults
};
onException(sqlEx SQLException)
myErrorHandler(10); // プログラムを終了する
end
end
onException(sqlEx SQLException)
myErrorHandler(8); // プログラムを終了する
end
sysLib.commit();
エラー条件
100 の SQLCODE は、一致するデータが見つからなかったことを示します。
このエラーでは、forEach ブロックが通常どおりに終了されます。
EGL が、こうした状況で forEach に関連する onException ブロックを実行することはありません。
次の例のようなテストで onException ブロックを開始する必要はありません。
onException(sqlEx SQLException)
if (sqlcode != 100) // 不要なテスト