SQL の get に関する考慮事項
SQL のコンテキストでは、get 文は、 結果セットからレコード・データを取り出します。
- get ステートメントにより結果セットを作成します。
- 以前の EGL open ステートメントで作成した結果セットから読み取ります (get ステートメントで absolute または next などの位置オプションを指定した場合)。
EGL は、get 文やその文にある SQL レコード変数のプロパティーに基づき、 生成したコードに SQL SELECT 文を作成します。 この暗黙の SQL コードについて詳しくは、SQL データ・アクセスを参照してください。 あるいは、#sql ディレクティブを使用して、 独自の組み込み SQL コードを作成することもできます (sql ディレクティブを参照)。EGL の prepare 文を使用して実行時に SQL コードをアセンブルし、get 文からそのコードを参照することもできます。 この動的 SQL の使用について詳しくは、SQL データ・アクセスを参照してください。
singleRow オプションを指定する場合、SQL SELECT 文はスタンドアロンになります。 singleRow を指定しない場合は、SQL SELECT がカーソル宣言 (SQL OPEN 文) の文節になります。 EGL が生成する SQL コードについて詳しくは、SQL データ・アクセス を参照してください。
EGL では、get 文で使用するさまざまな位置オプション (absolute および next など) を提供しています。 これにより、結果セットの現在の位置に相対的な特定レコードを取得できます。 これを行うには、cursor を使用して、現在の位置をトラッキングする必要があります。 結果セットのカーソルのある位置にアクセスするには、定位置の get を使用する前に EGL の open ステートメントを使用します。 get...forUpdate ステートメントを使用することもできますが、 これはあまり一般的ではありません。
get 文のターゲットが単一の SQL レコード変数である場合、 この文はユーザーが提供する基準 (暗黙または組み込み) に一致する最初のレコードを戻します。 また、SQL レコード変数の動的配列をステートメントのターゲットに指定することもできます。この場合、get ステートメントは、一致する各行を、配列内の要素として戻します。
構文

- SQLRecordVariable
- SQL レコード変数の名前。 レコード・パーツ・プロパティー keyItems および defaultSelectCondition の値に従ってデータベース行を見つける動作がデフォルトの動作です。
- forUpdate
- get 文を使用して新規の結果セットを作成し、 後で任意のデータベース行を置換または削除する予定である場合は、このキーワードを組み込み、結果セットに対応する行をロックします。 データベース・マネージャーは、コミットが実行されるまで、ロックされた行の変更を他のプログラムに対して許可しません。 コミット処理の詳細については、作業論理単位を参照してください。
- resultSetID
- get 文を使用して新規の結果セットを作成する場合、 forUpdate キーワードで任意の ID を指定することにより、 後続の EGL の replace、delete、execute、 または定位置の get 文、あるいは EGL の close 文中で、同じ結果セットを使用できます。
- singleRow
- このオプションは、get 文のキーが 1 行にのみ適用されることが確かであり、その行を更新または削除しない場合などに使用する、さらに効率的な SQL を生成します。 この場合、EGL はカーソルを作成しません。 キーが複数行に適用されるときにこのオプションを指定すると、実行時入出力エラーが発生します。
- #sql{ sqlSelectStatement }
- 経験豊かな SQL プログラマーであれば、独自の SQL SELECT 文を組み込むことにより、
EGL が生成する SQL コードをオーバーライドできます (『sql ディレクティブ』の解説を参照)。
#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 文節の列名に使用される修飾は、レコード・パーツ内の対応するフィールドで使用される修飾と一致する必要があります。
制約事項: 比較的複雑な SQL SELECT ステートメントをコーディングするとき、INTO 文節の作成を EGL 生成プログラムに依存するのではなく、ユーザーがこの文節を指定しなければならないことがあります。この状況は、(例として) 以下に示すように SELECT ステートメントで SQL CASE 式が使用される場合に発生します。SELECT CASE WHEN address1 <> '' THEN address1 WHEN address2 <> '' THEN address2 END...初期の SELECT 文節にあるすべての項目が以下のいずれかのカテゴリーから取得される場合、この状況は発生しません。- 列名
- リテラル
- CURRENT TIMESTAMP などの特殊レジスター
- 演算子 ||、+、-、*、/ のいずれかで結合された列名、リテラル、および特殊レジスター
しかし、SELECT 文節が複雑な場合、SQL レコードを使用する際に問題につながることがあります。これは、有効な INTO 節を生成するには、選択する内容と一致するように値を column プロパティーに割り当てる必要があるためです。例えば、以下の初期 SELECT 文節には、上記のカテゴリーの項目の組み合わせが含まれています。SELECT COLUMN01 || 10 + COLUMN02 * 5関連する SQL レコード・パーツを以下に示します。Record MyRecordPart type SQLRecord myField int { column = "COLUMN01 || 10 + COLUMN02 * 5" }; endこの最後のケースで、column プロパティーを設定せずに、独自の INTO 文節を書き込むことを検討してください。 この理由は、複雑な column プロパティー値にアクセスする EGL add または replace ステートメントをコーディングする場合、生成される SQL INSERT および SQL UPDATE ステートメントが無効になることがあるためです。
- into ... target
- この文節は、EGL が作成する暗黙の SQL コードの INTO 文節に相当します。
この INTO 文節により、結果セットから値を受け取る EGL 変数が識別されます。
個々の変数を指定することも、レコード名を指定することもできます。
レコード名を指定した場合、EGL はそのレコード内のすべてのフィールドを使用します。
この文節は、以下のいずれかの場合に SQL を処理するときに必要です。
- get 文で SQL レコード変数を指定しなかった。
- SQL レコード変数も組み込み SQL SELECT ステートメントも指定したが、ターゲットの SQL レコード変数に対応するフィールドを持たない SQL SELECT 文節に、 1 列以上の列がある。
into 文節の作成先は、EGL であって、SQL ではありません。 SQL 文のホスト変数の場合のように文節内の変数の名前をコロンで始めることはしないでください。 詳しくは、ホスト変数を参照してください。
- get positionOptionSQLDynamicArray とともに使用すると、レコード変数内の動的配列フィールド、または指定された出現個所がフィールドにある、構造化レコード内の動的配列フィールドをターゲットにすることができます。構造化レコードを使用すると、COBOL 生成におけるパフォーマンスを向上させることができます。関連付けられた rowSetSize が、構造化レコード内の出現フィールドに指定された要素より大きい場合に、get positionOption ステートメントが、出現した配列の最大索引を超える要素に値を埋めようとすると、IndexOutOfBoundException がスローされます。
- preparedStatementID
- この識別子は、実行時に SQL SELECT 文を準備する EGL prepare 文を指します。 get 文 SQL SELECT 文を動的に実行します。詳しくは、SQL の prepare に関する考慮事項を参照してください。
- using ... field
- この文節は、EGL が作成する暗黙の SQL コードの USING 文節に相当します。 この USING 文節により、実行時に準備済み SQL SELECT 文で使用可能な EGL 変数が識別されます。 using 文節の作成先は、EGL であって、SQL ではありません。 SQL 文のホスト変数の場合のように文節内の変数の名前をコロンで始めることはしないでください。 詳しくは、ホスト変数を参照してください。
- usingKeys ... field
- ここで、SQL レコードのフィールド名を指定して、そのレコード定義で指定したキー・フィールドをオーバーライドできます。
例えば、CustomerRecord で定義したキー・フィールドは customerNumber であるが、customerName でレコードを検索したいという場合は、以下のコードを使用することができます。
または、全く別のレコードのフィールドに基づいて検索することもできます。get myCustomer usingKeys myCustomer.customerName;get myCustomer usingKeys myOrders.customerName;usingKeys で指定するフィールド (複数可) は、 EGL が get 文から生成する暗黙の SQL 文の WHERE 文節に挿入されます。 その文の後に組み込み SQL コードを続ける場合は、その組み込みコードにより暗黙のコードがオーバーライドされます。
動的配列の場合、usingKeys 文節のフィールド (または SQL レコードのホスト変数) は、動的配列の基礎である SQL レコード変数に存在していてはなりません。
forUpdate キーワードを指定すると、キー項目に関連付けられた列は、FOR UPDATE OF 文節でリストされる列から除外されます。
- positionOption
- 新規の結果セットを作成するのではなく、既存の結果セットからデータを取り出す場合に、このオプションを使用します。 使用可能なオプションおよび詳細については、このトピックの『位置オプションの使用』を参照してください。
- from resultSetID
- 位置オプションを使用する場合、resultSetID を使用して、 位置によりレコード情報を検索する対象としての結果セットを指定することができます。 この ID は前の open 文や get 文で割り当てたものです。 結果セットを指定しない場合は、EGL はコンテキストから現在の結果セットを判別します。 このトピックの『位置オプションの使用』を参照してください。
- SQLDynamicArray
- この変数は、SQL レコード変数によって構成される動的配列に名前を付けます。 EGL は結果セットから一致するすべての行を取得し、それらの値を配列の個々のレコード変数要素に挿入します。 配列の maxSize プロパティーを設定することにより、 プログラムが処理可能な量よりも多くのデータを一度に取り出さないようにできます。 配列がその最大サイズに達すると、EGL は結果の取得を停止します。 動的配列プロパティー を参照してください。
- positionOption とともに使用すると、SQLDynamicArray 変数宣言または open ステートメントに指定された、rowSetSize プロパティーに基づいて、その次の行セットが動的配列に返されます。これが get positionOption の初回の実行である場合には、配列要素が作成されます。これが get positionOption の 2 回目以降の実行である場合には、要素が配列内に配置されます。
- sqlCallStatement
- データベース管理システムでのストアード・プロシージャーの呼び出しです。 プロシージャーは、結果セットを必ず 1 つ返す必要があります。例については、『ストアード・プロシージャーの呼び出し』を参照してください。
位置オプションの使用
- #sql ディレクティブに SQL を組み込むことはできません。
- singleRow オプションは使用できません。
- forUpdate オプションは使用できません (これは、結果セットを作成した文に設定される場合とされない場合があります)。
- 準備済みの文は使用できません。
- EGL の open 文を使用して結果セットを作成した。
- open 文に指定して scroll オプションを使用した。
next 位置オプションは、他の状況においても使用することができます。
- absolute (position)
- 結果セットの先頭から順方向にカウントする (正の値を指定する場合) か、結果セットの終わりから逆方向にカウントする (負の値を指定した場合) 数で指定する行を検索します。
- current
- 現行カーソル位置の行を検索します。
- first
- 結果セットの最初の行を検索します。
- last
- 結果セットの最後の行を検索します。
- next
- 現行カーソル位置に続く、最初の行を検索します。
- previous
- 現行カーソル位置の前の、最後の行を検索します。
- relative (position)
- 現行カーソル位置から順方向にカウントする (正の値を指定する場合) か、現行カーソル位置から逆方向にカウントする (負の値を指定した場合) 数で指定する行を検索します。 値がゼロの場合、現行カーソル位置のレコードを検索します。 これは、current オプションと同じです。
結果セットでのカーソル (または位置標識) の初期位置は、結果の最初の行の前です。 通常、プログラムは forEach 文を使用するか、get next を繰り返し使用して、結果内で反復的に処理を行います。
暗黙の SQL SELECT 文
SQL レコード変数を get 文に指定したが、#sql ディレクティブで組み込み SQL 文を指定しない場合は、 暗黙の SQL コードを作成します。暗黙の SQL SELECT には、次の特性があります。
- SQL テーブルの各キー列の値が SQL レコード変数の対応するキー・フィールドの値と等しい限り、get 文が選択するテーブル行は、defaultSelectCondition レコード固有プロパティーによって決まります。 レコード・キーもデフォルトの選択条件も指定しなかった場合は、結果セットにすべてのテーブル行が含まれます。 複数のテーブル行が選択され、単一の SQL レコード変数 (レコード変数の配列ではなく) を get 文のターゲットとして指定した場合は、 最初に検索された行がレコード変数に入ります。
- レコード定義におけるレコード・フィールドと SQL テーブル列の関連付けの結果として、特定のフィールドが、関連する SQL 結果セット列のコンテンツを受け取ります。
- forUpdate オプションを指定した場合、SQL SELECT FOR UPDATE 文には読み取り専用のレコード・フィールドが含まれません。
- 特定のレコード用の SQL SELECT 文は、以下の文のようになります。
ただし、FOR UPDATE OF 文節は、get 文に forUpdate オプションが含まれる場合にのみ表示されます。
SELECT column01, column02, ... columnNN FROM tableName WHERE keyColumn01 = :keyField01 FOR UPDATE OF column01, column02, ... columnNNスタンドアロンの SQL SELECT またはカーソルに関連する FETCH 文の SQL INTO 文節は、 以下の文節のようになります。INTO :recordField01, :recordField02, ... :recordFieldNNINTO 文節を指定しておらず、SQL レコード変数に組み込み SQL SELECT 文が付いている場合、EGL は SQL INTO 文節を派生します。 派生した INTO 文節のフィールドは、SQL 文の SELECT 文節にリストされた列と関連付けられたフィールドです。 (フィールドと列との関連付けは、カスタム SQL レコード・パーツ内で行われます。SQLRecord ステレオタイプを参照してください。) 列がフィールドと関連付けられていない場合は、EGL INTO 文節が必要です。
- 照会のキー値コンポーネントは、より大か等しい条件に基づく関係の集合です。
keyColumn01 >= :keyField01 & keyColumn02 >= :keyField02 & ... keyColumnNN >= :keyFieldNN - usingKeys 文節中のフィールド (または SQL レコード中のホスト変数) は、 動的配列の基礎である SQL レコード変数に存在してはなりません。
例
try
get myCustomer singleRow into customerName with
#sql{
SELECT customer_name
FROM Cusomter
WHERE customer_number = :myCustomer.customerNumber
};
onException(sqlEx SQLException)
myErrorHandler(8);
end
try
get myCustomer forUpdate into customerName with
#sql{
SELECT customer_name
FROM Cusomter
WHERE customer_number = :myCustomer.customerNumber
};
onException(sqlEx SQLException)
myErrorHandler(8); // プログラムを終了する
end
myCustomer.customerName = newName; // ユーザーが入力した名前変更
try
replace myCustomer;
onException(sqlEx SQLException)
myErrorHandler(12);
end
employees Employee[0]{rowsetsize=10};
Open resultset1 scroll with #sql{
select eID, uName, PASSWORD, fName, lName, office, sex, EMail
from EMPLOYEETEST
} for employees;
Get Next employees; //this empties the employees array and
// populates with up to the next 10 rows from the result set
または
eIDs INT[0]{};
uNames CHAR(20)[10]{};
Get Next employees into eIDs, uNames;
または
DynamicEmployee DynamicEmployee;
Get Next employees into DynamicEmployee;
Record DynamicEmployee
eIDs INT[10];
uNames CHAR(20)[10];
end
または
structuredEmployee StructuredEmployee;
Get Next employees into structuredEmployee.eIDs, structuredEmployee.uNames; //
Get Next employees into structuredEmployee;
Record StructuredEmployee
1 eIDs INT[10];
1 uNames CHAR(20)[10];
end
エラー条件
- SELECT 以外の型の SQL 文を指定する。
- SQL SELECT 文に直接 SQL INTO 文節を指定する。
- SQL INTO 文節以外に、SQL SELECT 文の文節のうち、必要な一部 (全部ではない) を指定する。
- 存在しないか、関連するホスト変数との互換性がない列に関連付けられている SQL SELECT 文を指定する (または受け入れる)。
- 複数のテーブルを更新する意図を示す SQL 文を指定する (または受け入れる) 場合。
- すべてのレコード・フィールドが読み取り専用である SQL レコード変数を使用する場合。
- forUpdate オプションを指定して EGL の get 文をカスタマイズしたが、 特定の SQL テーブル列が更新に使用可能であることを示していない場合。
- get 文に関連付けられた replace 文が列を変更しようとした。
- EGL get 文をカスタマイズする際に、SQL SELECT 文の FOR UPDATE OF 文節に列名を組み込む。
- EGL の replace 文をカスタマイズする際に、SQL UPDATE 文の SET 文節内にある列への参照をすべて除去する。
- get 文と replace 文の両方について、デフォルトを受け入れる。
互換性
各リレーショナル・データベース管理システム (RDBMS) は、独自のバージョンの SQL を持っています。 すべての実装環境ですべての SQL 文を使用できるとは限りません。 組み込み SQL をコーディングする前に、ご使用の RDBMS の資料を参照してください。
| プラットフォーム | 問題 |
|---|---|
| iSeries COBOL | absolute オプションはサポートされていません。 |