内部テーブルは、ABAPの中核をなすデータ構造です。メモリ上に表形式でデータを保持し、データベースから取得した結果を加工したり、集計したりするのに使います。ABAPプログラムの大半は、内部テーブルの操作で成り立っています。
3つのテーブル種類
内部テーブルには3種類あり、内部の実装とアクセス性能が異なります。
| 種類 | キー | 検索方式 | 重複 | 主な用途 |
|---|---|---|---|---|
| STANDARD TABLE | 非ユニーク | 線形探索 | 可 | 順次処理、行番号アクセス |
| SORTED TABLE | ユニークまたは非ユニーク | 二分探索 | 設定次第 | キー検索が多い、常にソート状態を保ちたい |
| HASHED TABLE | ユニーク必須 | ハッシュ | 不可 | 完全キーでの高速検索 |
" 標準テーブル(最も一般的)
DATA lt_std TYPE STANDARD TABLE OF ty_item.
" ソート済テーブル
DATA lt_srt TYPE SORTED TABLE OF ty_item
WITH UNIQUE KEY matnr.
" ハッシュテーブル
DATA lt_hsh TYPE HASHED TABLE OF ty_item
WITH UNIQUE KEY matnr.行の追加
" 作業領域から追加
ls_item-matnr = 'MAT-001'.
ls_item-menge = 10.
APPEND ls_item TO lt_items.
" ソート済/ハッシュテーブルへの追加(APPENDは使えない)
INSERT ls_item INTO TABLE lt_sorted.
" 位置を指定して挿入
INSERT ls_item INTO lt_items INDEX 1.
" 別のテーブルからまとめて追加
APPEND LINES OF lt_source TO lt_target.
" VALUE式でまとめて構築(7.4以降)
DATA(lt_items) = VALUE ty_items(
( matnr = 'MAT-001' menge = 10 )
( matnr = 'MAT-002' menge = 20 ) ).ソート済テーブルとハッシュテーブルにはAPPENDが使えません。順序がキーによって決まるため、末尾に追加するという概念がないからです。INSERT ... INTO TABLE を使います。
行の読み取り
" キーで検索(作業領域へ)
READ TABLE lt_items INTO ls_item
WITH KEY matnr = 'MAT-001'.
IF sy-subrc = 0.
" 見つかった
ENDIF.
" フィールドシンボルで参照(コピーなし)
READ TABLE lt_items ASSIGNING FIELD-SYMBOL(<fs_item>)
WITH KEY matnr = 'MAT-001'.
" インデックスで読む
READ TABLE lt_items INTO ls_item INDEX 1.
" 存在確認だけ(読み込まない・高速)
READ TABLE lt_items TRANSPORTING NO FIELDS
WITH KEY matnr = 'MAT-001'.
" テーブル式(7.4以降、見つからないと例外)
DATA(ls_found) = lt_items[ matnr = 'MAT-001' ].行の変更と削除
" キーで特定して更新
MODIFY lt_items FROM ls_item
TRANSPORTING menge
WHERE matnr = 'MAT-001'.
" ループ内で更新(ASSIGNINGなら直接書き換え可)
LOOP AT lt_items ASSIGNING FIELD-SYMBOL(<fs>).
<fs>-menge = <fs>-menge * 2.
ENDLOOP.
" 条件で削除
DELETE lt_items WHERE menge = 0.
" 重複の削除(事前にSORTが必要)
SORT lt_items BY matnr.
DELETE ADJACENT DUPLICATES FROM lt_items COMPARING matnr.
" 全件クリア
CLEAR lt_items.
FREE lt_items. " メモリも解放集計と加工
" ソート
SORT lt_items BY matnr ASCENDING menge DESCENDING.
" 制御レベル処理(キーの切り替わりを検出)
SORT lt_items BY matnr.
LOOP AT lt_items INTO ls_item.
AT NEW matnr.
lv_subtotal = 0.
ENDAT.
lv_subtotal = lv_subtotal + ls_item-menge.
AT END OF matnr.
WRITE: / ls_item-matnr, lv_subtotal.
ENDAT.
ENDLOOP.
" 件数
DATA(lv_count) = lines( lt_items ).
" REDUCEによる集計(7.4以降)
DATA(lv_total) = REDUCE i( INIT s = 0
FOR ls IN lt_items
NEXT s = s + ls-menge ).AT NEW/AT END OF は制御レベル処理と呼ばれ、ソート済みのデータをキーごとに区切って集計するための構文です。小計・中計・合計を出す帳票プログラムで頻繁に使われます。