SQL の open に関する考慮事項

SQL のコンテキストでは、EGL の open 文は、リレーショナル・データベースから結果セットを作成し、ユーザーがリスト内を移動するときに使用することのできるカーソルを作成します。

EGL では、このカーソルに直接アクセスできませんが、代わりに、get 文に定位置オプションが用意されています (SQL の get に関する考慮事項を参照)。 open 文の実行後、カーソルは結果セットの最初の行 (レコード) を指しています。

構文

open 文の構文図
resultSetID
open ステートメントが作成する結果セットを識別するために選択する文字ストリング。 この ID は、定位置の get ステートメント、または replace ステートメント、delete ステートメント、close ステートメントで使用できます。
rowsetsize
RowsetSize は、1 回の複数行のフェッチ、または 1 回の複数行の挿入で検索される行数を制御する注釈です。
scroll
結果セット内を移動するための定位置の get 文を使用可能にするオプション。 定位置 get 文について詳しくは、 SQL の get に関する考慮事項を参照してください。このオプションは、Java™ で出力を生成している場合にのみ使用可能です。
hold
コミットの実行時に、プログラムが結果セット内の位置を維持するようになるオプションです。 次のすべての条件に当てはまる場合、hold オプションが適しています。
  • ストアード・プロシージャーを呼び出すためではなく、カーソルをオープンするために EGL の open ステートメントを使用する場合。
  • 結果セット中の位置を失うことなく、定期的に変更内容をコミットする場合。
  • 使用しているデータベース管理システムが、SQL カーソル宣言で WITH HOLD オプションの使用をサポートしている場合。

コミットを実行しても hold オプションを指定したカーソルは閉じられませんが、ロールバックまたはデータベース接続を実行すると、すべてのカーソルが閉じられます。 コミット時にカーソル位置を保持する必要がない場合は、hold を指定しないでください。

詳しくは、このトピック内の『互換性』を参照してください。

forUpdate
データベースから取り出したデータを後続の EGL 文で置換または削除できるようにするオプション。 ストアード・プロシージャーを呼び出す場合には、このオプションを使用しないでください。
usingKeys ... field
ここで、SQL レコードのフィールド名を指定して、そのレコード定義で指定したキー・フィールドをオーバーライドできます。 usingKeys 文節で指定したフィールド (複数可) により、暗黙の SQL 文の WHERE 文節のキー値コンポーネントが作成されます。 暗黙の SQL 文は、 明示的な SQL 文を指定しない場合に実行時に使用されます。usingKeys 文節を組み込む場合、SQL レコード変数も指定する必要があります。

usingKeys 文節を指定しない場合、 暗黙の文のキー値コンポーネントは open 文で参照される SQL レコード・パーツが基となります。

forUpdate キーワードを指定すると、 キー項目に関連付けられた列は、SQL FOR UPDATE OF 文節でリストされる列から除外されます。 forUpdate キーワードを指定しない場合、キー項目に関連付けられた列だけが SQL ORDER BY 文節の列のリストに含まれます。

組み込み SQL 文を指定すると、他の場合に EGL が生成する暗黙のコードは、いずれも無視されます。

with #sql{ sqlStatement }
組み込み SQL SELECT 文を指定します。これは、SQL レコード変数も指定する場合には、オプションになります。 組み込みコードは、他の場合に EGL が生成するすべての暗黙のコードに対して優先されます。 #sql ディレクティブと左中括弧の間にスペースを入れないでください。
次のような場合について考えてみます。ユーザーのコードには、SQL レコードを使用する get ステートメントまたは open ステートメントがあり、明示的な SQL を含み、INTO 文節がありません。例えば、このような get ステートメントを含む EGL コードを以下に示します。
customer CustomerRecordPart{};
get customer with #sql{
   select MySCHEMA.CUSTOMER.Column01
   from MYSCHEMA.CUSTOMER
   where MYSCHEMA.Column02 = "AZ"}; 
このコード内で参照されたレコード・パーツは、以下のとおりです。
Record CustomerRecordPart type SQLRecord {tableNames = [["MYSCHEMA.CUSTOMER"]]}
   customerNumber INT    {column = "MYSCHEMA.CUSTOMER.Column01"};
   ...
end

今ここで説明した get ステートメントまたは open ステートメントでは、SQL の SELECT 文節の列名に使用される修飾は、レコード・パーツ内の対応するフィールドで使用される修飾と一致する必要があります。

into target
SQL の INTO 文節に相当するもので、結果セットから値を受け取る EGL ホスト変数 (ホスト変数を参照) を識別します。 レコード名を指定することもできます。その場合、EGL はそのレコード内のすべてのフィールドを使用します。 #sql ディレクティブの外側にあるこのような文節ではホスト変数名の前にコロンを挿入しないでください。
preparedStatementID
EGL prepare 文により作成されたコードを識別し、これにより動的処理が可能です。 詳しくは、SQL の prepare に関する考慮事項を参照してください。
using field
SQL の USING 文節に相当するもので、実行時に準備済み文から使用可能な EGL ホスト変数を識別します。 using field (#sql ディレクティブの外側にある) 文節では、ホスト変数名の前にコロンを挿入しないでください。
SQLRecordVariable
SQL レコード変数の名前。 SQL レコード変数を指定しない場合、組み込み SQL コード (#sql ディレクティブ付き) を提供しなければなりません。 SQL レコード変数を提供して、組み込み SQL コードを指定しない場合、 EGL はレコード・プロパティーの情報を使用して暗黙の SQL SELECT 文を作成します。 open 操作の後にこの変数を照会して、エラー条件を検出できます。 詳しくは、このトピックの『エラー処理』を参照してください。
SQLDynamicArray
この変数は、SQL レコード変数によって構成される動的配列に名前を付けます。 EGL は、open ステートメントのターゲットとして SQLRecord の動的配列をサポートします。動的配列の使用は、このステートメントで行セット処理が使用されている場合のみ有効です。

デフォルトの処理

デフォルトでは、SQL レコード変数を指定した場合の open ステートメントの効果は以下のとおりです。
  • open 文は、一連の行を使用可能にします。 SQL レコード・パーツでマッピングを使用して、EGL は選択した行の各列をレコード変数フィールドに関連付けます。読み取り専用のレコード・フィールドに関連付けられた列を除いて、すべての列は EGL replace 文による後続の更新に使用できます。
  • SQL レコードに対して 1 つのキー・フィールドのみを宣言する場合、open 文は以下の条件を満たすすべての行を選択します。
    • 行が SQL レコード・パーツのレコード固有の defaultSelectCondition プロパティーを実行する。
    • SQL テーブルのキー列の値が、SQL のレコード変数のキー・フィールドの値より大か等しい。
  • SQL レコードに対してキー・フィールドをまったく宣言しない場合や、複数のキー・フィールドを宣言しない場合、 レコード固有の defaultSelectCondition は検索基準のみを提供します。 また、open ステートメントはそれらの基準を満たすすべての行を検索します。
  • レコード・キーもデフォルトの選択条件も指定しない場合、open ステートメントはテーブル内のすべての行を選択します。
  • 選択された行はソートされません。
EGL open 文は、生成されたコードでは SQL SELECT または SQL SELECT FOR UPDATE 文が含まれるカーソル宣言によって表されます。デフォルトでは、以下の条件が当てはまります。
  • FOR UPDATE OF 文節には、読み取り専用のレコード・フィールドを含みません。
  • 特定のレコード用の SQL SELECT 文は、以下の文のようになります。
      SELECT column01, 
             column02, ... 
             columnNN
      INTO   :recordField01,
             :recordField02, ...
             :recordFieldNN
      FROM   tableName 
      WHERE  keyColumn01 = :keyField01
      FOR UPDATE OF
             column01, 
             column02, ... 
             columnNN

EGL の open 文に組み込み SQL 文を (#sql ディレクティブを使用して) 指定することにより、デフォルトをオーバーライドできます。

以下の例では、myCustomer という名前の SQL レコード変数を使用しています。

  myCustomer 用に myCustomerResults forUpdate を開きます。

  open x1 with
    #sql{
      SELECT customer_number,
             customer_name, 
             customer_balance
      FROM   Customer 
      WHERE  customer_number >= :myCustomer.customerNumber
      FOR UPDATE OF 
             :myCustomer.customerNumber, 
             :myCustomer.customerName,
             :myCustomer.customerBalance
    }

  open x2 with 
    #sql{
      SELECT customer_name, customer_balance
      FROM Customer
      WHERE customer_number = :myCustomer.customerNumber
    }
  for myCustomer;

  open x3 with
    #sql{
      call aResultSetStoredProc(:parameter)
    }
これは、hold キーワードを必要とする処理の流れの例です。
  1. EGL open 文でカーソルを宣言してオープンする。
  2. EGL get next 文で 1 つの行を取り出す。
  3. ループの中で以下のアクションを実行する。
    1. 何らかの方法でデータを処理する。
    2. EGL replace 文で行を更新する。
    3. sysLib.commit() システム関数で変更内容をコミットする。
    4. EGL get next 文で別の行を取り出す。

hold を指定しない場合は、カーソルが開いていないために、ステップ 3 の 4 番目の部分の最初の実行は失敗します。

エラー条件

以下のような状態は無効です。
  • SELECT に必要な文節を欠いた組み込み SQL 文を含める。 必要な文節は SELECT、FROM、および (forUpdate オプションを指定した場合は) FOR UPDATE OF です。
  • SQL レコード変数が、実行時に存在しないか、関連するレコード・フィールドとの互換性がない列に関連付けられている。
  • forUpdate オプションを指定しているとき、次のいずれかの種類の SQL レコードに対して、コードが open 文を実行しようとする。
    • 読み取り専用のレコード・フィールドしかない SQL レコード。
    • 複数の SQL テーブルに関連付けられている SQL レコード
次の両方の条件に当てはまる場合にも、問題が生じます。
  1. 更新のために EGL の open ステートメントをカスタマイズしたが、 特定の SQL テーブル列が更新に使用可能であることを指示していない。
  2. open 文に関連付けられた replace 文が列を変更しようとした。
この問題は、以下のいずれかの方法で解決できます。
  • EGL の open 文をカスタマイズする際に、SQL の SELECT 文の FOR UPDATE OF 文節に列名を組み込む。
  • EGL の replace 文をカスタマイズする際に、SQL の UPDATE 文の SET 文節内にある列への参照を除去する。
  • open 文と replace 文の両方について、EGL が生成する暗黙の SQL コードを受け入れる

互換性

各リレーショナル・データベース管理システム (RDBMS) は、独自のバージョンの SQL を持っています。 すべての実装環境ですべての SQL コマンドを使用できるとは限りません。 組み込み SQL をコーディングする前に、ご使用の RDBMS の資料を確認してください。

表 1. open および SQL の互換性に関する考慮事項
プラットフォーム 問題
Java 生成 hold オプションは、JDBC ドライバーが JDBC 3.0 以上をサポートしている場合にのみ Java プログラムに使用できます。
CICS® プログラムがセグメント化モードで実行している場合、open 文の hold キーワードを使用していても、 converse 文は、CICS トランザクションを終了し、プログラムがファイル位置やデータベース位置を保存しないようにします。
IMS/VS すべての converse 文はセグメント化モードで実行します。 その結果、open 文の hold キーワードを使用していても、 IMS™ トランザクションを終了して、プログラムがファイル位置やデータベース位置を保存しないようにします。
Cloudscape または Derby データベース EGL は、scroll フラグと forUpdate フラグの両方を使用する open 文をサポートしていません。どちらか一方のみを使用できます。

フィードバック