内部テーブルの種類
14.2 内部テーブルの種類
2. 内部テーブルの種類
内部テーブルには、以下の3種類があります。
- 標準テーブル
- ソートテーブル
- レンジテーブル
標準テーブル
標準テーブルは、もっとも基本の内部テーブルです。
追加した順(挿入順)のままデータが並ぶため、一覧表示・順番を保ったまま処理したい場面でよく使います。
順序やキーに関係なく、抽出したデータがそのままの形で格納されています。
また単に、「TYPE TABLE OF」と記述した時は、標準テーブルの宣言とみなされます。
※ただし、可読性から標準テーブルは、略さず「TYPE STANDARD TABLE OF」と宣言することが通例となっています。
(案件によって違います。
)
内部テーブル:標準テーブル
※DBテーブルはデータ型ではないが、SAPシステム上ではDBテーブルの構造を参照するようにSAPシステムの仕様として構築されており、DBテーブルを型として指定すると内部テーブルを作成します。
※アクセス時間は、標準テーブル内のデータの数に比例します。
「サンプルコード」①
REPORT ZFUJII_SAMPLE141_NEW.
" 1行の型(行タイプ)はDDICテーブル/構造を参照するのが実務では一般的
TYPES TY_CUSTOMER_TAB TYPE STANDARD TABLE OF ZFUJII_DB01 WITH EMPTY KEY.
START-OF-SELECTION.
" DBから複数行を取得
SELECT *
FROM ZFUJII_DB01
INTO TABLE @DATA(LT_CUSTOMERS).
" 一覧表示(簡易)
LOOP AT LT_CUSTOMERS INTO DATA(LS_CUSTOMER).
WRITE: / LS_CUSTOMER-KUNNR, LS_CUSTOMER-NAME1, LS_CUSTOMER-NAME2.
ENDLOOP.
END-OF-SELECTION.
実行結果
ソートテーブル
ソートテーブルは、指定したキー順で並ぶ状態を内部的に維持する内部テーブルです。
格納されているデータを、あるキーによって並び替えることができます。
データを格納する際に、指定したキーでソートをかけてから格納するため、標準テーブルと比べて時間がかかってしまいます。
その反面、ソートテーブル内のデータを条件に指定して読み込む場合は、処理効率は良くなります。
内部テーブル:ソートテーブル
キーを元に宣言しているため、ソートテーブル宣言時には、キーの設定をする必要があります。
「サンプルコード」①
REPORT Z_SAMPLE142_NEW.
*内部テーブル定義
*得意先名称(NAME1)でソート(NON-UNIQUE)
DATA GT_ZFUJII_DB01 TYPE SORTED TABLE OF ZFUJII_DB01 WITH NON-UNIQUE KEY NAME1.
START-OF-SELECTION.
"※SELECTで全行を取得すると重いので、教材用途なら件数制限を推奨(必要なら外してOK)
SELECT *
FROM ZFUJII_DB01
INTO TABLE @GT_ZFUJII_DB01.
LOOP AT GT_ZFUJII_DB01 INTO DATA(GS_ZFUJII_DB01).
WRITE: / GS_ZFUJII_DB01-MANDT,
GS_ZFUJII_DB01-KUNNR,
GS_ZFUJII_DB01-NAME1,
GS_ZFUJII_DB01-NAME2.
ENDLOOP.
END-OF-SELECTION.
実行結果
レンジテーブル
レンジテーブルとは、内部テーブルの一種ですが、前述のテーブルとは格納方法が異なります。
レンジテーブルは、標準/ソートのように「データを貯める」のではなく、WHERE条件(範囲条件)を行として持つために使います。
(WHERE <フィールド>IN <レンジテーブル>)
つまり、テーブルの中にある情報は抽出条件のようなものです。
レンジテーブルの1行には、次の4項目があります。
●SIGN:含める(I) / 除外する(E)
●OPTION:条件(EQ=等しい、BT=範囲、GE=以上…)
●LOW:下限/値
●HIGH:上限(OPTION=BTのとき使用)
内部テーブル:レンジテーブル
その他のテーブル宣言と同様に、定義したいテーブルの種類を含めて宣言をします。
レンジテーブルを宣言する時は、データ型を参照せずに項目名を参照します。
それにより、その項目の範囲を選択し、レンジテーブルに格納することができます。
レンジテーブルにおける構文はとなります。
「サンプルコード」①
REPORT ZFUJII_SAMPLE143.
*&---------------------------------------------------------------------*
* レンジテーブル型定義
*&---------------------------------------------------------------------*
TYPES TYP_SAL TYPE RANGE OF ZFUJII_DB02-ZAMT_SAL.
*&---------------------------------------------------------------------*
* レンジテーブル定義
*&---------------------------------------------------------------------*
DATA R_SAL TYPE TYP_SAL.
*&---------------------------------------------------------------------*
* レンジテーブルの構造定義
*&---------------------------------------------------------------------*
DATA RH_SAL LIKE LINE OF R_SAL.
*&---------------------------------------------------------------------*
* 内部テーブル定義
*&---------------------------------------------------------------------*
DATA IT_ZFUJII02_TAB TYPE ZFUJII02_TAB. "データ抽出用
*&---------------------------------------------------------------------*
* 構造定義
*&---------------------------------------------------------------------*
DATA ST_ZFUJII02 TYPE ZFUJII02. "データ抽出用
*&---------------------------------------------------------------------*
* 主処理
*&---------------------------------------------------------------------*
START-OF-SELECTION.
*初期化
CLEAR: R_SAL, RH_SAL, IT_ZFUJII02_TAB, ST_ZFUJII02.
*値の代入
RH_SAL-SIGN = 'I'. "指定した範囲を含む
RH_SAL-OPTION = 'GE'. "LOWで指定する値以上
RH_SAL-LOW = 1000000.
*レンジテーブルへデータを格納
APPEND RH_SAL TO R_SAL.
*データ抽出
*売上金額が100万以上のデータを抽出
SELECT * FROM ZFUJII_DB02 INTO TABLE IT_ZFUJII02_TAB
WHERE ZAMT_SAL IN R_SAL.
*出力処理
LOOP AT IT_ZFUJII02_TAB INTO ST_ZFUJII02.
WRITE ST_ZFUJII02-MANDT. "クライアント
WRITE ST_ZFUJII02-GRAC_YYYYMM. "年月
WRITE ST_ZFUJII02-ZAMT_SAL. "売上金額
WRITE ST_ZFUJII02-CURRENCY. "通貨
WRITE /.
ENDLOOP.
END-OF-SELECTION.
実行結果
補足:LIKE LINE OFオプションについて
サンプルで使用しているLIKE LINE OFというキーワードは、レンジテーブルで構造を宣言する場合に
しばしば用いられます。
LIKE LINE OFを使用することで、レンジテーブルと同じ形の構造を宣言することができます。
今回のサンプルの場合、
DATA R_SAL TYPE TYP_SAL.
DATA RH_SAL LIKE LINE OF R_SAL.
上記で構築されています。
また、DATA命令だけでなく、TYPES命令でもLIKE LINE OFを使用することができます。
内部テーブル:レンジテーブル(新構文)
レンジテーブルでも、インライン宣言が可能です。VALUE命令を使うことで構造の宣言が不要になります。
インライン宣言を用いた構文は以下の通りです。
また、共通の値をセットする場合は、以下の通りに記述することも可能です。
詳しくは、サンプルコード③を確認してみましょう。
「サンプルコード」①
REPORT Z_SAMPLE143.
*&---------------------------------------------------------------------*
* レンジテーブル定義(売上金額用)
*&---------------------------------------------------------------------*
TYPES TY_R_AMT TYPE RANGE OF ZFUJII_DB02-ZAMT_SAL.
*&---------------------------------------------------------------------*
* データ定義
*&---------------------------------------------------------------------*
DATA:
GR_AMT TYPE TY_R_AMT, "売上金額レンジテーブル
GS_AMT LIKE LINE OF GR_AMT, "レンジ1行分(SIGN/OPTION/LOW/HIGH)
GT_DB02 TYPE STANDARD TABLE OF ZFUJII_DB02, "抽出結果
GS_DB02 TYPE ZFUJII_DB02. "抽出結果(1行)
*&---------------------------------------------------------------------*
* 主処理
*&---------------------------------------------------------------------*
START-OF-SELECTION.
" レンジ条件:100万以上(GE)
" SIGN : I = 含める(Include)
" OPTION : GE = 以上(Greater or Equal)
" LOW : 下限値
GS_AMT-SIGN = 'I'.
GS_AMT-OPTION = 'GE'.
GS_AMT-LOW = 1000000.
APPEND GS_AMT TO GR_AMT.
"データ抽出:売上金額が100万以上
SELECT *
FROM ZFUJII_DB02
INTO TABLE GT_DB02
WHERE ZAMT_SAL IN GR_AMT.
"出力
LOOP AT GT_DB02 INTO GS_DB02.
WRITE: / GS_DB02-MANDT, "クライアント
GS_DB02-ZYEARMONTH, "年月
GS_DB02-ZAMT_SAL, "売上金額
GS_DB02-CURRENCY. "通貨
ENDLOOP.
実行結果
「サンプルコード」③
REPORT Z_SAMPLE143_NEW.
*&---------------------------------------------------------------------*
* レンジテーブル定義
*&---------------------------------------------------------------------*
DATA GR_AMT TYPE RANGE OF ZFUJII_DB02-ZAMT_SAL.
*&---------------------------------------------------------------------*
* 内部テーブル定義
*&---------------------------------------------------------------------*
DATA IT_ZFUJII02_TAB TYPE STANDARD TABLE OF ZFUJII02_TAB. "データ抽出用
*&---------------------------------------------------------------------*
* 主処理
*&---------------------------------------------------------------------*
START-OF-SELECTION.
*レンジテーブルへデータを格納
GR_AMT = VALUE #(
( SIGN = 'I' OPTION = 'BT' LOW = 500000 HIGH = 1000000 )
( SIGN = 'E' OPTION = 'EQ' LOW = 550000 )
).
*初期化
CLEAR RH_SAL.
*データ抽出
*売上金額が50万~100万円の間で、55万円を含まないデータを抽出
SELECT *
FROM ZFUJII_DB02
INTO TABLE @DATA(GT_DB02)
WHERE ZAMT_SAL IN @GR_AMT.
*出力処理
LOOP AT GT_DB02 INTO DATA(GS_DB02).
WRITE: / GS_DB02-MANDT, "クライアント
GS_DB02-ZYEARMONTH, "年月
GS_DB02-ZAMT_SAL, "売上金額
GS_DB02-CURRENCY. "通貨
ENDLOOP.
実行結果