# CHAPTER 5: ダイナミック SQL

## 5.1 はじめに

多くのデータベースアプリケーションでは、データベース上で 実行する処理は前もって知らされています。また、アプリケーションを 作成する場合は、おそらくあらかじめテーブルの名前や各テーブルの アトリビュート名およびその数は知っているはずです。 これらを知っていることは、アプリケーションに必要である正確なSQL文を書く ことが可能であり、そのSQL はアプリケーションの実行中では変更する必要がありません。 このようなアプリケーションは、スタティック(静的)SQLステートメント (つまり、ステートメントは変更できない)をアプリケーションに埋め込み、 プリコンパイラによって C のルーチンに変換し、実現します。

しかし、ある環境下ではプリコンパイルする前にSQLステートメントの正確な 構成を知ることができない場合があります。 このようなアプリケーションでは、 実行時に SQL ステートメントを作成し、処理することができなければなりません。 このようなステートメントは、 アプリケーションの実行中に変更することができるため、 ダイナミック(動的な)SQLステートメントといえます。 また、これらのステートメントは C のルーチンにプリコンパイルすることができないため、 アプリケーション実行中に構文解析され、実行されます。

コマンドについては、前の章のスタテック SQL コマンドにおいて記述しましたが、 ダイナミック SQL コマンドは、 別の章として"ダイナミック SQL コマンドリファレンス"で記述されています。

### 5.1.1 ダイナミック vs スタテック SQL

スタテック SQL ステートメントの構成は、 プリコンパイラがステートメントを解析し、C ルーチンに置き換えることにより、 プリコンパイルする時点でわかっています。 ステートメントの構造は、実行時に変更はできませんが、 テーブル(またはビュー)やアトリビュートの名前は変更することは可能です。 また、埋め込み SQL ステートメントが テーブルやアトリビュート名をプログラム中に埋め込む(ハードコーディング)代わりに 変数を使用する場合、 `WHERE`句中の実行時に比較するためのアトリビュートとその値 にも変数を使用することができます。 この場合は、実行時にSQLの解析は行われません。

以下の例ではスタテック SQL を使用し、変数を埋め込むことができます。 (変数名の前には":"が付けられます。)

       SELECT :att1, :att2 FROM :tab1 WHERE :att1 = :val1;

しかし、例えば、 アクセスするためにアトリビュートの数や また、ジョインをするためのテーブル数を知らない場合は ダイナミック SQL ステートメントを使用する必要があります。

ダイナミック SQL を使用したアプリケーションは、 スタテックSQL を使用したものに比べ、さらに用途は広く利用できます。 実行時にダイナミック SQL ステートメントは作成されるため、 アプリケーションの稼動中にそれを変更することができます。

ダイナミック SQL は実行時に文字列からステートメントを作成します。 例えば、 検索するアトリビュートや`WHERE`句を指定することをユーザーに行わせる場合に、 ユーザーによってキーボードから入力される一部のステートメント含む 文字列から`SELECT`ステートメントを作成することができます。

ダイナミック SQL は、柔軟性を提供しますが、それに対し、 SQLステートメントを作成することは複雑なコーディングが 必要な場合があります。 ダイナミック SQL ステートメントは実行時にSQL の構文解析が行われるため 通常、スタティク SQL ステートメントに比べ処理時間が多少かかります。

以下のすべての条件に適合した場合、スタティク SQL を使用してください。

- SQL ステートメントは、プリコンパイルの間に知らされます。
- ステートメントの変数の数を知らされています。
- SQL　オペレーションは `SELECT`、 `INSERT`、 `UPDATE`、 `DELETE`,
  またはトランザクションコマンドです。

上記の条件に適合しない場合は、ダイナミックSQLを使用してください。

アプリケーションはスタティクおよびダイナミックコマンドの両方を 混ぜて使用することができます。

## 5.2 ダイナミックSQLの変数

スタティク SQL では、 埋め込み変数のC のデータタイプは Empressのデータタイプと対応されています。 不正なデータタイプを使用した場合、間違った結果を得ます。 例えば、C の 4 バイトのinteger 変数を使用して、 Empressの`INTEGER`値(2バイトからなる)を読む場合、 呼んだ値は正しくありません。

ダイナミック SQL では、 Empressは、要求されたどのようなデータタイプの変換も実行します。 例えば、 Empressの`DECIMAL`データタイプのアトリビュート値に C の float 変数を割り当てるために使用することができ、 Empress は、floatの値の変換を試みます。 この値がアトリビュートの有効な範囲以外の値である場合は 変換は失敗します。 ただし、制御変数のデータタイプは、常に C　の short integer である必要があります。

任意のEmpressデータタイプを取得や値を割り当てるために 文字列を使用することができます。 この場合、Empressはデータとして外部フォーマットを使用します。

## 5.3 予約キーワード

以下のキーワード(大文字と小文字のどのような組み合わせでもよい) は埋め込み SQL 変数の名前として使用することはできませんが、 これらは、他の目的では使用することができます。(例えば通常の C 変数、関数名など)

`-` | `*` | `+`
`=` | `?` | `ADD`
`ADMIN` | `AFTER` | `AGGREGATE`
`ALIAS` | `ALL` | `ALLOCATE`
`ALTER` | `AND` | `ANY`
`AS` | `ASC` | `ASCENDING`
`AT` | `ATTR` | `ATTRIBUTE`
`BEFORE` | `BEGIN` | `BETWEEN`
`BODY` | `BTREE` | `BY`
`BYPASS` | `BYPASS_LOCK` | `CALL`
`CASCADE` | `CHANGE` | `CHECK`
`CHECKSUM` | `COMMENT` | `COMPARISON`
`CONSTRAINT` | `CONVERT` | `CORRESPONDING`
`COUNT` | `CREATE` | `CROSS`
`CURRENT` | `DATABASE` | `DB`
`DBA` | `DECLARE` | `DELETE`
`DESC` | `DESCENDING` | `DIRECT_FROM`
`DIRECT_INTO` | `DIRECT_ONTO` | `DISABLE`
`DISPLAY` | `DISTINCT` | `DOUBLE`
`DROP` | `DUMP` | `EACH`
`EDIT` | `EMPTY` | `ENABLE`
`END` | `EQUALITY` | `ESCAPE`
`EXCEPT` | `EXCL` | `EXCLUSIVE`
`EXECUTE` | `EXISTS` | `EXIT`
`EXPRESSION` | `FOR` | `FOREIGN`
`FROM` | `FULL` | `FUNCTION`
`GENERAL` | `GENERIC` | `GRANT`
`GROUP` | `HAVING` | `IN`
`INCL` | `INCLUSIVE` | `INDEX`
`INFIX` | `INNER` | `INOUT`
`INSERT` | `INTERSECT` | `INTO`
`IS` | `JOIN` | `LANGUAGE`
`LEFT` | `LEVEL` | `LIKE`
`LIST` | `LOCATE` | `LOCK`
`MASTER` | `MASTERS` | `MINUS`
`MODE` | `MODULE` | `NATURAL`
`NOT` | `NULL` | `OF`
`OJ` | `ON` | `ONTO`
`OPERATOR` | `OPTION` | `OR`
`ORDER` | `OUT` | `OUTER`
`PARAMETER` | `POSTFIX` | `PREFIX`
`PRIMARY` | `PRINT` | `PRIORITY`
`PRIV` | `PRIVILEGE` | `PROCEDURE`
`RANGE` | `REFER` | `REFERENCES`
`REFERENTIAL` | `RENAME` | `REPLICATE`
`REPLICATES` | `REPLICATION` | `REPORT`
`RESTRICT` | `RETURNS` | `REVOKE`
`RIGHT` | `ROLE` | `ROUTINE`
`ROW` | `RUN` | `SELECT`
`SET` | `SOME` | `SORT`
`SQL` | `STOP` | `STYLE`
`SUBSET` | `TABLE` | `TIMESERIES`
`TO` | `TRIGGER` | `TRIGGERS`
`UNION` | `UNIQUE` | `UNSET`
`UPDATE` | `USER` | `USING`
`VALUES` | `VIEW` | `WHEN`
`WHERE` | `WIDTH` | `WITH`
`WORKSPACE` | `WRAPMARGIN` | `{`
`{D` | `{TS` | `}`

加えて、開発者は以下の標準 SQL キーワードを使用しないことを強く推奨します。

|  |  | type indicator length name data

これらは現在のEmpress埋め込み SQLでの予約キーワードではありませんが、 将来、キーワードとなる可能性があります。