SQL データ
SQL (3 つの文字をばらばらに発音します) は、リレーショナル・データベース管理システム (DBMS) と通信するための言語です。一方、DBMS は、相互に接続された表でビジネス情報を管理するデータベースを制御するシステムです。
- 一般的で単純な作業を行っている場合は、EGL ステートメントを使用してすべての入出力操作を実行します (レコードの読み取りと書き込みを参照してください)。この場合は、実際の SQL ステートメントがすべて EGL によって作成されます。
- #sql ディレクティブを使用して、独自の SQL ステートメントを EGL コードに組み込みます。
EGL を使用すれば、2 つのスタイルを組み合わせることもできます。ユーザーは、EGL が EGL コードから生成した SQL ステートメントにアクセスし、変更することができます (暗黙の SQL ステートメントの表示を参照してください)。
- EGL を SQL データベースに接続するための説明 (SQL データベース接続の作成を参照)
- SQL レコードを作成するためのショートカット (SQL テーブル・データの検索を参照)
- 完全な SQL アプリケーションを作成するためのショートカット (データ・アクセス・アプリケーションの作成を参照)
EGL の方式
下の表に、EGL を使用してリレーショナル・データベースと対話する方法の概略を示します。
| SQL の目的 | EGL によるアプローチ |
|---|---|
| 簡単な SQL データ操作 (SELECT、UPDATE、INSERT、DELETE)。主キー・コントロール WHERE および ORDER BY。 | EGL キーワード (get、replace、add、delete) を使用して、EGL で暗黙的 SQL を生成します。 |
| 再使用可能なカスタム WHERE 文節による、簡単な SQL データ操作。 | カスタムの WHERE 文節を defaultSelectCondition プロパティーに指定します。 |
| カスタムの WHERE 文節を含む SQL SELECT ステートメント。 | #sql ディレクティブを介して、明示的 SQL を使用します。 |
| SQL テーブルの JOIN ステートメント。 | ワークベンチで「SQL を検索」機能を使用して defaultSelectCondition プロパティーを作成し、主キーおよび外部キーでテーブルが正しく結合されるように使用します。
|
| SELECT コマンド内の派生データ (MAX()、AVG() など) | #sql ディレクティブを介して明示的 SQL を使用し、派生フィールドを中括弧内に指定します。 |
| 個々のフィールドの column プロパティーで派生式または計算式を指定する、カスタム SQLRecord を作成します。 | |
| 複雑な、あるいはカスタムの、SQL UPDATE、INSERT、または DELETE ステートメント。 | EGL の replace、add、または delete の各ステートメントを、明示的 SQL (#sql ディレクティブ) とともに使用します。 |
| execute #sql ステートメントを介して、明示的 SQL を使用します。 | |
| 簡単なデータ操作以外の SQL ステートメント (CREATE TABLE など)。 | execute #sql ステートメントを介して、明示的 SQL を使用します。 |
| 動的 SQL (準備済み SQL ステートメント)。 | execute #sql ステートメントを介して、明示的 SQL を使用します。 |
| ストアード・プロシージャー。 | 次のような明示的 SQL を使用します。 |
| SQL SELECT ステートメントの結果セットの行を個別に処理。 | EGL open コマンドを使用して結果セットを開き、以下のいずれかのステートメントを使用してループを開始します。
|
| オンライン検索のためのプログラマチック・ページング。 | 「データ・アクセス・アプリケーション」ウィザードを使用します。 |
| SQL テーブルへのデータの追加。 | ワークベンチのデータ・パースペクティブで、テーブル・エディターを使用します。 |
| SQL ステートメントの妥当性検査 | EGL エディターのコンテキスト・メニューで、「SQL の妥当性検査」を選択します。 |
| ワークベンチのデータ・パースペクティブで SQL エディターを使用して、対話式 SQL を実行します。 |
結果セット処理
- forUpdate オプションを使用して EGL open ステートメントを実行することで、カーソルを宣言して開きます。このオプションにより、選択された行は、これ以降の更新または削除のためにロックされます。
- EGL get next ステートメントを実行することで、1 つの行を取り出します。
- forEach ループで、以下のアクションを実行します。
- データを結果セットからホスト変数内に取り出します。 ホスト変数は SQL ステートメントの変数で、冒頭にコロン文字 (:) を追加することにより、ホスト言語 (この場合、EGL が SQL ステートメントをホストします) の変数と同じ名前になります。
- EGL replace または EGL delete ステートメントを実行することで、行を更新または削除します。
- EGL get next ステートメントを実行することで、別の行を取り出します。
- EGL commit() 関数を実行することで、変更をコミットします。
カーソルを開き、そのカーソルの行で動作するステートメントは、結果セット ID によってお互いに関連しています。この ID は、プログラム内のすべての結果セット ID およびプログラム変数の中で固有でなければなりません。カーソルを開く open ステートメントでその ID を指定し、 ループを作成する forEach ステートメントで同じ ID を参照します。 また、個々の行に影響を与える get next、delete、および replace ステートメントや、 カーソルを閉じる close ステートメントで、その ID を参照します。
try
open selectEmp forUpdate for emp;
onException(sqlx SqlException)
myErrorHandler(sqlx); // プログラムを終了する
end
foreach(emp)
emp.empname = emp.empname :: " " :: "III";
try
replace emp;
onException(sqlx SqlException)
myErrorHandler(sqlx); // プログラムを終了する
end
end // end while; 結果セットの最後の行が読み取られると
// カーソルは自動的にクローズされる
sysLib.commit();
EGL open ステートメントを処理するときに (SQL レコードを使用しているかどうかに関係なく) 定期的に変更をコミットするには、hold ステートメント・オプションを使用し、これによってコミット後もカーソル位置は保持されます。ただし、CICS® を 宛先としたプログラムがセグメント化されている場合、セグメント化されたプログラム の converse によって CICS トランザクションが終了し、プログラムがファイルやデータベースの位置を保存しないため、hold オプションは効果がありません。
SQL レコードおよびその使用法
add myEmpRecord;
try
add myEmpRecord;
onException(sqlx SqlException)
if (myEmpRecord is unique) // テーブル行が同じキーを持った場合
myErrorHandler(sqlx);
end
end
- SQLRecord パーツを定義して、関連するレコード変数を宣言します。
- SQL レコードを使用して入出力を実行する EGL ステートメントを書き込みます。
- EGL ステートメントのデフォルトの振る舞いを受け入れるか (ほとんどの場合、これで必要な状態が提供される)、またはビジネス・ロジックに適した SQL 変更を行います。
SQLRecord パーツと関連レコードの定義
SQLRecord パーツを定義し、各フィールドとリレーショナル・テーブルまたはビューの列を関連付けます。EGL は自動的にこれを行うことができます。 SQL テーブル・データの検索を参照してください。
- 他の SQL レコード。各レコードは、親テーブルと子テーブルの間の 1 対 1 の関係を表します。
- SQL レコードの配列。各レコードは、親テーブルと子テーブルの間の 1 対多の関係を表します。
プリミティブ型のフィールドのみが、データベース列を表すことができます。
- 各 SQLRecord パーツの構造は、フラット (階層なし) でなければなりません
- すべてのフィールドはプリミティブ・フィールドでなければなりません。ただし、BLOB 型、CLOB 型、または STRING 型であってはなりません
- どのレコード・フィールドも、構造化フィールド配列にすることはできません
SQLRecord パーツの定義後、そのパーツに基づいたレコード変数を宣言します。
SQL 関連の EGL ステートメント
各ステートメントがレコード変数をステートメントの入出力オブジェクトとして使用する、一連のステートメントを作成することができます。各ステートメントに対して、EGL は暗黙の SQL ステートメントを提供します。このステートメントは、ソースにはありませんが、レコード変数と EGL ステートメントの組み合わせによって暗黙で存在します。 例えば、EGL add ステートメントの場合、暗黙 の SQL INSERT ステートメントは特定のレコード内のフィールド値を、関連付けられたテーブル列に配置します。レコード変数に、テーブル列が割り当てられていないフィールドが含まれている場合、フィールド名が列名と同一であるという前提で、EGL は暗黙の SQL ステートメントを形成します。
以下の EGL ステートメントは、示された SQL ステートメントに対応します。
| EGL ステートメント | SQL ステートメント |
|---|---|
| add | INSERT |
| delete | DELETE |
| get、open | SELECT |
| replace | UPDATE |
暗黙の SELECT ステートメント
Record Employee type sqlRecord
{ tableNames = [["EMPLOYEE"]],
keyItems = ["empnum"] }
empnum decimal(6,0);
empname char(40);
end
myEmpRecord Employee;
get myEmpRecord;
SELECT empnum, empname
FROM EMPLOYEE
WHERE empnum = :empnum
INTO :empnum, :empname
- defaultSelectCondition レコード・プロパティーに指定した値。
- 以下の 2 組の値の間の関係 (同等など)。
- テーブル・キーを構成する列の名前。
- レコード・キーを構成するホスト変数の値。
暗黙の SELECT ステートメントについて詳しくは、「EGL 言語解説書」の個々のキーワード・トピックを参照してください。
カーソルによる SQL レコード
SQL レコードを使用する場合、結果セット ID を使用して関連付けるのとほぼ同じ方法で、いくつかの EGL ステートメントに同じレコード変数を使用することで、カーソル処理ステートメント を関連付けすることができます。しかし、結果セット ID によって示されるどのステートメント間の関係も、レコード変数によって示される関係に優先します。場合によっては、resultSetID を 指定する必要があります。
また、特定のレコード変数に対して 1 つのカーソルのみを開くことができます。 EGL ステートメントによってカーソルが開かれる場合、同じレコード変数に対して別のカーソルが開かれていると、生成されたコードによって最初のカーソルは自動的に閉じます。
SQL ステートメントのカスタマイズ
- 暗黙の SQL ステートメントを受け入れます。この場合、SQLRecord パーツに対する変更は、実行時に使用される SQL ステートメントに影響を与えます。例えば、後に別のフィールドを SQL レコードのキーとして使用することを示した場合、EGL によって SQLRecord パーツに基づいた任意のカーソル宣言で使用される暗黙の SELECT ステートメントが変更されます。
- 代わりに、SQL ステートメントを明示的にすることを選択します。EGL は、ユーザーの
コードに暗黙の SQL ステートメントを挿入し、ユーザーがそれらのステートメントを変更できるよう
にします。
この場合、その SQL ステートメントの詳細は SQLRecord パーツとは分離しており、SQLRecord パーツに対するこれ以降の変更は、実行時に使用される SQL ステートメントに影響を与えません。
ソースから明示的な SQL ステートメントを除去すれば、暗黙の SQL ステートメントが (もしあれば) 生成時に再び使用可能になります。
レコード内のレコードの使用例
DataItem DeptNo { column = "deptNo" } end
Record Dept type SQLRecord
deptNo DeptNo;
managerID CHAR(6);
employees Employee[];
end
Record Employee type SQLRecord
employeeID CHAR(6);
empDeptNo DeptNo;
end
Function getDeptEmployees(myDeptRecord Dept)
get myDeptRecord.employees usingKeys myDeptRecord.deptNo;
end
NULL テストおよび設定
Record Employee type SQLRecord
employeeID CHAR(6);
empDeptNo INT?;
end
if (myEmpRecord.empDeptNo == null)
...
end
myEmpRecord.empDeptNo = null;
set myEmpRecord.empDeptNo empty;
互換性
| プラットフォーム | 問題 |
|---|---|
| CICS for z/OS®、z/OS バッチ、iSeriesC | 生成されたコードは、DB2® UDB に直接アクセスできます |
| AIX®、HP-UX、iSeriesJ、Linux、Solaris、z/OS UNIX システム・サービス、Windows 2000/NT/XP | JDBC は DB2 UDB、Oracle、Informix®、または Microsoft SQL Server へのアクセスを提供します |