このトピックでは、OpenSQLによりDBデータを検索する方法を取り上げて説明します。
SELECT命令
DBデータを検索するには、SELECT命令を使用します。SELECT命令は以下のような分類があります。
- 「SELECT SINGLE」命令: 一行読込
- 「SELECT・・・ENDSELECT」命令:一件ずつ複数行読込
- 「SELECT INTO TABLE」命令:内部テーブルによる複数行一括読込
- 「SELECT INTO TABLE PACKAGE SIZE ・・・ENDSELECT」命令:内部テーブルによる複数行分割読込
- 「OPEN CURSOR FOR SELECT」命令: カーソルによる読込
SELECT SINGLE
構文:
SELECT SINGLE 項目 INTO wa FROM テーブル名 ~.
この命令は、指定したデータベーステーブルから、指定した条件と一致するデータを1件のみ取得します。。INTO句の後ろでは、構造(wa)を指定する必要があります。
取得する事ができれば、システム項目「SY-SUBRC」には0が入ります。取得できたデータの件数(取得できていれば1)は、システム項目「SY-DBCNT」に格納されます。
SELECT...ENDSELECT
構文:
SELECT 項目 INTO wa FROM テーブル名 ~. 処理内容 ENDSELECT.
この命令は、指定したデータベーステーブルから、指定した条件と一致するデータを1件ずつ取得します。条件と一致するデータがなくなるまで、「ENDSELECT.」の間をループします。NTO句の後ろでは、構造(wa)を指定する必要があります。
1件でもデータを取得する事ができれば、システム項目「SY-SUBRC」には0が入ります。取得できたデータの件数は、システム項目「SY-DBCNT」に格納されます。
SELECT INTO TABLE
構文:
SELECT 項目 INTO TABLE it FROM テーブル名 ~.
この命令は、指定したデータベーステーブルから、指定した条件と一致するデータを一括で取得します。データをプログラム内で溜めて利用する事ができるのが特徴です。INTO句の後ろでは、内部テーブル(it)を指定する必要があります。
1件でもデータを取得する事ができれば、システム項目「SY-SUBRC」には0が入ります。取得できたデータの件数は、システム項目「SY-DBCNT」に格納されます。
SELECT INTO TABLE PACKAGE SIZE...ENDSELECT
構文:
SELECT 項目 INTO TABLE it. FROM テーブル名 PACKAGE SIZE 行数 ~. 処理内容 LOOP AT it into wa. 処理内容 ENDLOOP. 処理内容 ENDSELECT.
この命令は、指定したデータベーステーブルから、指定した条件と一致するデータを、PACKAGE SIZEで指定された行数単位で、複数のパッケージに分けて内部テーブルに読み込みます。
読み込むパッケージがなくなるまで、SELECT~ENDSELECTの間をループします。なお、内部テーブルには常に、いま読み込まれたパッケージの行のみが格納されます。(INTOの代わりにAPPENDINGキーワードを使えば、内部テーブルには各パッケージの行がどんどん溜まっていくことになります)
OPEN CURSOR FOR SELECT
構文:
OPEN CURSOR c FOR SELECT 項目 FROM テーブル名 ~. DO. FETCH NEXT CURSOR c INTO wa. 処理内容 ENDDO. CLOSE CURSOR c
記述詳細
WHERE句
全ての命令のSQL文ではWHERE句を記述することが可能です。
「SELECT SINGLE」命令では、WHERE句でプライマリキーが特定できない場合に警告が出力されます。
ORDERBY句
下記のように「○」が付いている命令のSQL文では、ORDERBY句を記述することが可能です。
- 「SELECT SINGLE」:×
- 「SELECT・・・ENDSELECT」:○
- 「SELECT INTO TABLE」:○
- 「SELECT INTO TABLE PACKAGE SIZE ・・・ENDSELECT」:○
- 「OPEN CURSOR FOR SELECT」:○
結合検索
全ての命令のSQL文では下記のような結合検索を記述することが可能です。
- INNER 別テーブル名 ON 結合条件
- LEFT OUTER JOIN 別テーブル名 ON 結合条件
集計問い合わせ
全ての命令では、下記の集計関数や句を含める集計問い合わせを記述することが可能です。
- COUNT
- SUM
- AVG
- MAX
- MIN
- GROUPBY句
- HAVING句
DISTINCT
下記のように「○」が付いている命令のSQL文では、DISTINCTを記述することが可能です。
- 「SELECT SINGLE」:×
- 「SELECT・・・ENDSELECT」:○
- 「SELECT INTO TABLE」:○
- 「SELECT INTO TABLE PACKAGE SIZE ・・・ENDSELECT」:○
- 「OPEN CURSOR FOR SELECT」:○
読み取る行数を制御
下記のように「○」が付いている命令のSQL文では、[UP TO <n> ROWS]オプションで読み込まれる行数を制限することが可能です。
- 「SELECT SINGLE」:×
- 「SELECT・・・ENDSELECT」:○
- 「SELECT INTO TABLE」:○
- 「SELECT INTO TABLE PACKAGE SIZE ・・・ENDSELECT」:○
- 「OPEN CURSOR FOR SELECT」:○
テーブル条件
SELECT 命令の WHERE 句には特殊バリアントがあり、内部テーブルの行および列から条件を導くことができます。
SELECT ...FOR ALL ENTRIES IN <itab> WHERE <cond> ...
<cond> は前述の方法で指定します。内部テーブル <itab> の項目を、条件のオペランドとして指定する場合は、内部テーブルのすべての行をアドレス指定します。その後で、内部テーブルの各行に対して比較が実行されます。各行に対して、条件を満たすデータベーステーブルからの行を選択します。SELECT 命令の結果セットは、内部テーブルの各行に対する個々の選択を結合したものです。重複する行は自動的に結果セットから除外されます。<itab> が空白の場合、オプション FOR ALL ENTRIES が無視され、すべてのエントリが読み込まれます。
内部テーブル <itab> には構造化された行データ型が必要であり、条件 <cond> に登場する各項目は、比較対象のデータベースの列と互換性がなければなりません。内部テーブル項目を使用する比較では、演算子 LIKE 、BETWEEN 、IN を使用しないでください。同じ SELECT 命令では ORDER BY 句を使用しません。
オプション FOR ALL ENTRIES を使用して、ネストされた選択ループを内部テーブルでの操作で置き換えます。これにより、選択したデータの多数のセットに対するパフォーマンスが大幅に向上します。
WHERE句での選択テーブルの使用
WHERE 句で選択テーブルを使用するには、次のように記述します。
......... WHERE <f> IN <seltab>.
<f> はデータベース列の名前で、<seltab> はその項目に割り当てられた選択テーブルです。このように WHERE 句を指定した OPEN SQL 命令は、データベーステーブルの列のうち、項目<f> の内容が <seltab> に格納されている選択基準に合致しているものだけにアクセスします。
REPORT DEMO. DATA WA_CARRID TYPE SPFLI-CARRID. SELECT-OPTIONS AIRLINE FOR WA_CARRID. SELECT CARRID FROM SPFLI INTO WA_CARRID WHERE CARRID IN AIRLINE. WRITE WA_CARRID. ENDSELECT.
選択テーブル AIRLINE はデータベーステーブル SPFLI の CARRID 列にリンクされています。SELECT 命令の WHERE 句により、CARRID 列の内容が AIRLINE に格納された選択基準を満たしているかどうかがチェックされます。
選択テーブルが次のように入力されているとします
SIGN | OPTION | LOW | HIGH |
---|---|---|---|
I | BT | DL | UA |
E | EQ | LH | - |
WHERE句でのRANGES テーブルの使用
RANGES テーブルは選択テーブルと同じデータ型を持ちますが、選択画面の入力項目にリンクされていません。
各命令の使い分け
下記のように目的に応じて各命令を使い分けることができます。
- 最大1件のみを取得する場合は「SELECT SINGLE」命令を使います。
- 複数件を取得し、且つ取得可能な件数が必ず一定の範囲に収まる場合は「SELECT INTO TABLE」命令を使います。
- 複数件を取得し、取得可能な件数は一定ではない場合は、基本的に「SELECT INTO TABLE PACKAGE SIZE ・・・ENDSELECT」命令を使います。
- 複数件を取得し、前の行の値によって次の行を取得するかどうかを判断する必要な場合は、「OPEN CURSOR FOR SELECT」命令を使います。
- 「SELECT・・・ENDSELECT」命令は、基本的に使いません。