三崎レイナ
社会人1年目。新卒でITコンサルティングファームに就職。初配属がSAPプロジェクトにアサインされる。SAPがわからないことだらけで悩んでいたところ、会社の先輩にSAPラボの所長を紹介され、毎週末に所長とSAPのお勉強中!
博士
SAPラボの所長。SAP大好き博士!SAP導入プロジェクトを構想策定~運用保守まであらゆるフェーズを数多く経験。
いまは優しきおじいちゃんだが、プロマネバリバリの時代はかなり怖かったらしい。現在は引退し、SAPの後進育成と啓蒙活動に従事中!
登場人物紹介
三崎レイナ
社会人1年目。新卒でITコンサルティングファームに就職。初配属がSAPプロジェクトにアサインされる。SAPがわからないことだらけで悩んでいたところ、会社の先輩にSAPラボの所長を紹介され、毎週末に所長とSAPのお勉強中!
博士
SAPラボの所長。SAP大好き博士!SAP導入プロジェクトを構想策定~運用保守まであらゆるフェーズを数多く経験。
いまは優しきおじいちゃんだが、プロマネバリバリの時代はかなり怖かったらしい。現在は引退し、SAPの後進育成と啓蒙活動に従事中!
この記事を読むメリット
今回はABAPのデータベース操作(SQL操作)について説明するぞい!
データベース操作(SQL操作)はABAPプログラミングの基本であり、重要なスキルです。本記事では、SELECT命令、INSERT命令、UPDATE命令、DELETE命令の基本的な使い方について解説します。
新着のSAPフリーランス案件
【FI】
S/4HANAへのバージョンアップ支援(Jrコンサル可)
【PP】
メーカー向けSAP移行プロジェクト支援
【MM】
【SD】
製造業向けロジ領域の運用保守支援
【BASIS】
【MM】
【SD】
製造業向け運用保守支援支援
【CO】
【FI】
【MM】
【PP】
【SD】
大手メーカー社向けSAP導入支援
【FI】
商社向け基幹システムバージョン支援
【FI】
SAP運用業務支援
【FI】
SAP導入プロジェクト支援
【FI】
光学機器 S/4HANA導入テスト支援
【CO】
一般消費財メーカーS/4 HANAバージョンアップ
データベース操作の基本は、データの取得(SELECT)、データの挿入(INSERT)、データの更新(UPDATE)、データの削除(DELETE)です。それぞれの操作について、具体的な例を交えながら説明していきます。
SELECT命令はデータベースからデータを取得するための基本的かつ重要な命令です。
まずはSELECT命令じゃ。
基本の構文
SELECT 項目1
項目2
…
FROM テーブル名
INTO TABLE 内部テーブル.
※SELECTの後には取得したい項目を記載し、全項目取得したい場合は「*」を記載します。
※作業領域(ワークエリア)にデータを格納したい場合は「TABLE」を省略します。
SELECT命令の基本の使用例は以下の通りじゃ。
DATA: lt_sflight TYPE TABLE OF sflight.
SELECT *
FROM sflight
INTO TABLE lt_sflight.
WRITE: 'sflightテーブルから', sy-dbcnt, '件のデータを取得しました'.
このプログラムでは、’sflight’テーブルの全データが内部テーブル’lt_sflight’に格納されます。
パフォーマンスを悪化させない為にも、必要なフィールドのみをSELECTするようにするのじゃ。SELECT *は避け、以下のように必要な項目のみ指定するぞい!
TYPES: BEGIN OF ty_sflight,
carrid TYPE sflight-carrid,
connid TYPE sflight-connid,
fldate TYPE sflight-fldate,
END OF ty_sflight.
DATA: lt_sflight TYPE STANDARD TABLE OF ty_sflight,
ls_sflight TYPE ty_sflight.
SELECT carrid
connid
fldate
FROM sflight
INTO TABLE lt_sflight.
WRITE: 'sflightテーブルから', sy-dbcnt, '件のデータを取得しました'.
LOOP AT lt_sflight INTO ls_sflight.
WRITE: / ls_sflight-carrid, ls_sflight-connid, ls_sflight-fldate.
ENDLOOP.
このプログラムでは、’sflight’テーブルの’carrid’、’connid’、’fldate’項目の全データが内部テーブル’lt_sflight’に格納されます。
SELECT命令には様々なオプションがあるぞい!
特定の条件に基づいてデータをフィルタリングするには、WHEREオプションを使用します。
DATA: lt_sflight TYPE TABLE OF sflight.
SELECT *
FROM sflight
INTO TABLE lt_sflight
WHERE carrid = 'LH'.
WRITE: 'sflightテーブルから', sy-dbcnt, '件のデータを取得しました'.
このプログラムでは、’carrid’が’LH’のフライト情報のみを取得します。
‘SELECT SINGLE’や’UP TO n ROWS’を使用することで、データの取得する件数を指定することができます。
条件に該当するデータを1件だけ取得することができます。データの存在チェックに使用されることが多いです。
DATA: wa_sflight TYPE sflight.
SELECT SINGLE *
FROM sflight
INTO wa_sflight
WHERE carrid = 'LH' AND connid = '0400'.
WRITE: '航空会社:', wa_sflight-carrid, 'フライト番号:',wa_sflight-connid, '日付:', wa_sflight-fldate.
このプログラムでは、’sflight’テーブルから’carrid’が’LH’で’connid’が’0400’のデータを1件のみ作業領域’wa_sflight’に格納します。
「n」の部分に入れた数字分のデータを取得します。
SELECT SINGLEと同様に1件だけ取得して存在チェックをする場合に使用されることが多いです。
DATA: lt_sflight TYPE TABLE OF sflight.
SELECT *
FROM sflight
INTO TABLE lt_sflight UP TO 10 ROWS.
WRITE: 'sflightテーブルから', sy-dbcnt, '件のデータを取得しました'.
このプログラムでは、’sflight’テーブルから最大10件のデータを内部テーブル’lt_sflight’に格納します。
FOR ALL ENTRIESを使用すると、内部テーブルのデータを基に他のテーブルからデータを取得します。
DATA: lt_sflight TYPE TABLE OF sflight,
lt_sbook TYPE TABLE OF sbook.
SELECT *
FROM sflight
INTO TABLE lt_sflight
WHERE carrid = 'LH'.
IF lt_sflight IS NOT INITIAL.
SELECT * FROM sbook INTO TABLE lt_sbook
FOR ALL ENTRIES IN lt_sflight
WHERE carrid = lt_sflight-carrid
AND connid = lt_sflight-connid.
ENDIF.
WRITE: 'sbookテーブルから', sy-dbcnt, '件のデータを取得しました'.
このプログラムでは、’sflight’テーブルからデータを取得し、’carrid’と’connid’を基に’sbook’テーブルから関連データを取得します。
FOR ALL ENTRIESの注意点!
FOR ALL ENTRIES を使用する際には、内部テーブルが空の場合にすべてのレコードを取得してしまう可能性があります。これを防ぐために、必ず内部テーブルが空でないことを確認してください。
JOINは複数のテーブルから関連するデータを結合して1つの内部テーブルにデータを格納します。JOINにはいくつかの種類がありますが、最も一般的なものを以下に示します。
TYPES: BEGIN OF ty_itab,
carrid TYPE sflight-carrid,
connid TYPE sflight-connid,
fldate TYPE sflight-fldate,
bookid TYPE sbook-bookid,
customid TYPE sbook-customid,
END OF ty_itab.
DATA: itab TYPE STANDARD TABLE OF ty_itab.
SELECT sflight~carrid
sflight~connid
sflight~fldate
sbook~bookid
sbook~customid
INTO TABLE itab
FROM sflight
INNER JOIN sbook
ON sflight~carrid = sbook~carrid
AND sflight~connid = sbook~connid
WHERE sflight~carrid = 'LH' AND sflight~connid = '0400' AND sbook~fldate = '20230604'.
WRITE: 'sflightとsbookを結合(INNER JOIN)して', sy-dbcnt, '件のデータを取得しました'.
このプログラムでは、’INNER JOIN’を使用して’sflight’テーブルと’sbook’テーブルを’carrid’と’connid’項目で結合し、結合条件に一致するレコードを取得します。
SELECT sflight~carrid
sflight~connid
sflight~fldate
sbook~bookid
sbook~customid
INTO TABLE itab
FROM sflight
LEFT JOIN sbook
ON sflight~carrid = sbook~carrid
AND sflight~connid = sbook~connid
WHERE sflight~carrid = 'LH' AND sflight~connid = '0400' AND sflight~fldate = '20230604'.
WRITE: 'sflightとsbookを結合(LEFT JOIN)して', sy-dbcnt, '件のデータを取得しました'.
このプログラムでは、’sflight’テーブルの全レコードと一致する’sbook’テーブルのレコードを取得し、一致しない場合は’sbook’の列にNULLが入ります。
左右のテーブルを入れ替えてLEFT JOINを使用するのと同じの為、INNER JOINとLEFT JOINを覚えておけば問題ないぞい!
JOINの機能
データを集計する場合、GROUP BYとHAVINGを使用します。
GROUP BYを使用して指定したコンポーネントごとに集計することが可能です。HAVINGでGROUP BYの条件を指定することが可能です。
TYPES: BEGIN OF sflight_agg,
carrid TYPE sflight-carrid,
num_flights TYPE i,
END OF sflight_agg.
DATA: lt_aggregate TYPE TABLE OF sflight_agg,
ls_aggregate TYPE sflight_agg.
SELECT carrid
COUNT(*) AS num_flights
INTO TABLE lt_aggregate
FROM sflight
GROUP BY carrid
HAVING COUNT(*) > 1.
LOOP AT lt_aggregate INTO ls_aggregate.
WRITE: / '航空会社コード:', ls_aggregate-carrid, 'フライト数:', ls_aggregate-num_flights.
ENDLOOP.
このプログラムでは、’sflight’テーブルの’carrid’ごとにフライト数を集計し、2便以上のキャリアのみを取得します。
データを特定の順序で並べ替えるには、ORDER BYオプションを使用します。
DATA: lt_sflight TYPE TABLE OF sflight,
ls_sflight TYPE sflight.
SELECT *
FROM sflight
INTO TABLE lt_sflight
ORDER BY fldate DESCENDING.
WRITE: 'sflightテーブルから', sy-dbcnt, '件のデータを取得しました'.
LOOP AT lt_sflight INTO ls_sflight.
WRITE: / ls_sflight-carrid, ls_sflight-connid, ls_sflight-fldate.
ENDLOOP.
このプログラムでは、’sflight’テーブルのデータを’fldate’の降順で並べ替えて取得します。
複数のSELECT文の結果セットを結合して1つの内部テーブルを作成します。
UNIONには’UNION’と’UNION ALL’の2種類があります。
※ABAP7.4以降のS4HANAでの新構文でのみ使用可能です。
TYPES: BEGIN OF sunion,
carrid TYPE sflight-carrid,
connid TYPE sflight-connid,
END OF sunion.
DATA: lt_union TYPE TABLE OF sunion.
SELECT carrid, connid FROM sflight
UNION
SELECT carrid, connid FROM sbook
INTO TABLE @lt_union.
WRITE: sy-dbcnt, '件のデータを取得しました'.
LOOP AT lt_union INTO DATA(ls_union).
WRITE: / ls_union-carrid, ls_union-connid.
ENDLOOP.
このプログラムでは、’sflight’と’sbook’テーブルからデータを取得し、重複を排除して1つの内部テーブルに格納します。
SELECT carrid, connid FROM sflight
WHERE fldate = '20230604'
UNION ALL
SELECT carrid, connid FROM sbook
WHERE fldate = '20230604'
INTO TABLE @lt_union.
WRITE: sy-dbcnt, '件のデータを取得しました'.
LOOP AT lt_union INTO DATA(ls_union).
WRITE: / ls_union-carrid, ls_union-connid.
ENDLOOP.
このプログラムでは、’sflight’と’sbook’テーブルからデータを取得し、重複を排除せずに1つの内部テーブルに格納します。
UNIONの機能
次はINSERT命令じゃ。
新しいレコードをデータベーステーブルに挿入するには、INSERT命令を使用します。
基本の構文
・単一のレコードを挿入する場合
INSERT INTO テーブル名 VALUES 作業領域.
INSERT テーブル名 FROM 作業領域.
・複数のレコードを挿入する場合
INSERT テーブル名 FROM TABLE 内部テーブル名.
実際に使用例を見ていくぞい!
DATA: wa_zflight TYPE zflight.
wa_zflight-flight_id = 'FL004'.
wa_zflight-airline_id = 'LH'.
wa_zflight-arrival_airport = 'NRT'.
wa_zflight-seat_capacity = 250.
INSERT INTO zflight VALUES wa_zflight.
IF sy-subrc = 0.
WRITE: 'Record inserted successfully'.
ELSE.
WRITE: 'Failed to insert record'.
ENDIF.
このプログラムでは、INSERT命令を使用して’zflight’テーブルに新しいフライトデータを挿入します。その後、’sy-subrc’を使って挿入が成功したかどうかを確認しています。
DATA: lt_zflight TYPE TABLE OF zflight,
ls_zflight TYPE zflight.
ls_zflight-flight_id = 'FL005'.
ls_zflight-airline_id = 'BA'.
ls_zflight-arrival_airport = 'LHR'.
ls_zflight-seat_capacity = 300.
APPEND ls_zflight TO lt_zflight.
ls_zflight-flight_id = 'FL006'.
ls_zflight-airline_id = 'AF'.
ls_zflight-arrival_airport = 'CDG'.
ls_zflight-seat_capacity = 350.
APPEND ls_zflight TO lt_zflight.
INSERT zflight FROM TABLE lt_zflight.
IF sy-subrc = 0.
WRITE: 'Records inserted successfully'.
ELSE.
WRITE: 'Failed to insert records'.
ENDIF.
このプログラムでは、’zflight’テーブルに挿入したいデータを内部テーブルに格納して、その内部テーブルからINSERT命令を使用して’zflight’テーブルに複数データを挿入します。
INSERT命令は内部テーブル内にキー重複のデータがある場合にショートダンプしてしまいますが、重複キーエラーを許容し、エラーが発生しても処理を続行する場合には’ACCEPTING DUPLICATE KEYS’を使用します。また、S/4 HANA特有ですが’ACCEPTING DUPLICATE ENTRIES’を使用することも可能です。
挿入処理でエラーが発生した場合の処理を追加することが大切です。例えば、重複キーエラーの場合などです。
DATA: lt_flight TYPE TABLE OF zflight,
ls_flight TYPE zflight,
lt_failed TYPE TABLE OF zflight,
ls_failed TYPE zflight.
* データの準備
ls_flight-flight_id = 'FL007'.
ls_flight-airline_id = 'DL'.
ls_flight-arrival_airport = 'ATL'.
ls_flight-seat_capacity = 280.
APPEND ls_flight TO lt_flight.
ls_flight-flight_id = 'FL008'.
ls_flight-airline_id = 'UA'.
ls_flight-arrival_airport = 'ORD'.
ls_flight-seat_capacity = 300.
APPEND ls_flight TO lt_flight.
* データの挿入
LOOP AT lt_flight INTO ls_flight.
INSERT zflight FROM ls_flight.
IF sy-subrc <> 0.
APPEND ls_flight TO lt_failed.
ENDIF.
ENDLOOP.
* 挿入結果の確認
IF lt_failed IS INITIAL.
WRITE: 'Records inserted successfully'.
ELSE.
WRITE: 'Some records failed to insert'.
LOOP AT lt_failed INTO ls_failed.
WRITE: / 'Failed to insert: ', ls_failed-flight_id, ls_failed-airline_id, ls_failed-arrival_airport, ls_failed-seat_capacity.
ENDLOOP.
ENDIF.
このプログラムでは、’lt_flightという内部テーブルに準備されたフライトデータを、ループを使って一行ずつ’zflight’テーブルに挿入します。挿入の際にエラーが発生した場合(sy-subrcが0以外の場合)、エラーが発生したレコードをlt_failedという別の内部テーブルに追加します。すべての挿入処理が完了した後、lt_failedが空であれば「レコードが正常に挿入された」と出力し、空でない場合は「挿入に失敗したレコードがある」として、失敗したレコードの詳細を出力します。
次はUPDATE命令じゃ。
既存のレコードを更新するには、UPDATE命令を使用します。
基本の構文
・特定の項目を指定して更新する場合
UPDATE テーブル名 SET フィールド1 = 値1, フィールド2 = 値2 … WHERE 条件.
・作業領域を使用して更新する場合
UPDATE テーブル名 FROM 作業領域.
・内部テーブルを使用して更新する場合
UPDATE テーブル名 FROM TABLE 内部テーブル.
まずは簡単な使用例を見ていくぞい!
UPDATE zflight
SET arrival_airport = 'LAX'
WHERE flight_id = 'FL004'.
IF sy-subrc = 0 AND sy-dbcnt > 0.
WRITE: 'Record updated successfully'.
ELSEIF sy-subrc = 0 AND sy-dbcnt = 0.
WRITE: 'No matching record found to update'.
ELSE.
WRITE: 'Update failed due to an error'.
ENDIF.
このプログラムでは、’flight_id’が’FL004’の’arrival_airport’を’LAX’に更新します。更新の結果を’sy-subrc’と’sy-dbcnt’で判定し、適切なメッセージを出力します。
DATA: ls_flight TYPE zflight.
SELECT SINGLE * FROM zflight INTO ls_flight WHERE flight_id = 'FL003' AND airline_id = 'AF'.
ls_flight-arrival_airport = 'HND'.
ls_flight-seat_capacity = 290.
UPDATE zflight FROM ls_flight.
このプログラムでは、特定のフライト情報を選択し、その座席数を更新します。まず、フライトIDが’FL003’で航空会社IDが’AF’のフライト情報を取得し、その到着空港を’HND’、座席数を’290’に更新します。(更新結果の判定ロジックは記載を省略)
DATA: lt_flight TYPE TABLE OF zflight,
ls_flight TYPE zflight.
ls_flight-flight_id = 'FL001'.
ls_flight-airline_id = 'DL'.
ls_flight-arrival_airport = 'ATL'.
ls_flight-seat_capacity = 280.
APPEND ls_flight TO lt_flight.
ls_flight-flight_id = 'FL003'.
ls_flight-airline_id = 'UA'.
ls_flight-arrival_airport = 'ORD'.
ls_flight-seat_capacity = 300.
APPEND ls_flight TO lt_flight.
UPDATE zflight FROM TABLE lt_flight.
このプログラムでは、複数のフライト情報を内部テーブルに準備し、それらの情報を基に’zflight’テーブルを更新します。’FL001’および’FL003’のフライト情報を設定し、対応するフライトIDに基づいて更新します。(更新結果の判定ロジックは記載を省略)
データベースのレコードを削除するには、DELETE命令を使用します。
基本の構文
・WHERE句を使用して削除する場合
DELETE FROM テーブル名 WHERE 条件.
・作業領域を使用して削除する場合
DELETE テーブル名 FROM 作業領域.
・内部テーブルを使用して削除する場合
DELETE テーブル名 FROM TABLE 内部テーブル.
まずは簡単な使用例を見ていくぞい!
DELETE FROM zflight WHERE flight_id = 'FL002' AND airline_id = 'BA'.
IF sy-subrc = 0 AND sy-dbcnt > 0.
WRITE: 'Record deleted successfully'.
ELSEIF sy-subrc = 0 AND sy-dbcnt = 0.
WRITE: 'No matching record found to delete'.
ELSE.
WRITE: 'Delete failed due to an error'.
ENDIF.
このプログラムでは、’zflight’テーブルから’flight_id’が’FL002’で’airline_id’が’BA’のレコードを削除します。削除が成功したかどうかを’sy-subrc’と’sy-dbcnt’で判定し、適切なメッセージを出力します。
DATA: ls_flight TYPE zflight.
ls_flight-flight_id = 'FL004'.
ls_flight-airline_id = 'LH'.
DELETE zflight FROM ls_flight.
このプログラムでは、作業領域’ls_flight’の内容に基づいて’zflight’テーブルから対応するレコードを削除します。’flight_id’が’FL004’で’airline_id’が’LH’のレコードを削除します。(削除結果の判定ロジックは記載を省略)
DATA: lt_flight TYPE TABLE OF zflight,
ls_flight TYPE zflight.
ls_flight-flight_id = 'FL001'.
ls_flight-airline_id = 'DL'.
APPEND ls_flight TO lt_flight.
ls_flight-flight_id = 'FL003'.
ls_flight-airline_id = 'UA'.
APPEND ls_flight TO lt_flight.
DELETE zflight FROM TABLE lt_flight.
このプログラムでは、内部テーブル’lt_flight’の各行の内容に基づいてル’zflight’テーブルから対応する複数のレコードを削除します。’flight_id’が’FL001’か’FL003’でそれぞれ’airline_id’が’DL’と’UA’のレコードを削除します。(削除結果の判定ロジックは記載を省略)
DELETE FROM zflight.
このプログラムでは、’zflight’テーブルから全てのレコードを削除します。(削除結果の判定ロジックは記載を省略)
SY-SUBRC(System Subroutine Return Code)は、ABAPプログラム内で実行された操作の結果を示すシステム変数です。多くのABAP命令や汎用モジュールは、実行後にSY-SUBRCを設定します。一般的には、操作が成功したかどうかを判断するために使われます。
SY-DBCNT(Database Count)は、直前のデータベース操作で処理された行数を保持するシステム変数です。SELECT、INSERT、UPDATE、DELETEなどのデータベース操作を行った際に、その操作が影響を与えた行数を示します。
ここまででデータベース操作(SQL操作)についての基本的な説明をしたぞい!
ありがとうございます!自分でもいろいろ試して使ってみます!
ABAPのデータベース操作は、データベースと連携してSAPアプリケーションを効果的に開発するための基本です。SELECT命令、INSERT命令、UPDATE命令、DELETE命令の各命令を理解し、適切に使用することで、より効率的かつ効果的にデータ操作が可能となります。まず基本的な構文を練習し、徐々に複雑なデータベース操作に挑戦してみましょう!
新着のSAPフリーランス案件
【FI】
S/4HANAへのバージョンアップ支援(Jrコンサル可)
【PP】
メーカー向けSAP移行プロジェクト支援
【MM】
【SD】
製造業向けロジ領域の運用保守支援
【BASIS】
【MM】
【SD】
製造業向け運用保守支援支援
【CO】
【FI】
【MM】
【PP】
【SD】
大手メーカー社向けSAP導入支援
【FI】
商社向け基幹システムバージョン支援
【FI】
SAP運用業務支援
【FI】
SAP導入プロジェクト支援
【FI】
光学機器 S/4HANA導入テスト支援
【CO】
一般消費財メーカーS/4 HANAバージョンアップ
SAPラボでは、SAPの知識を活かして副業をしたい方を募集してるのじゃ!
SAPラボのライターの特徴
・ライティング初心者OK!
・報酬高単価!
・業務委託契約なので副業として最適!
SAP記事執筆者としての活動実績として利用可能なので、転職時や案件探しの際に企業へのアピール材料にもなります。
募集要項
・SAP導入や運用保守プロジェクトへの参画経験1年以上
ご応募/お問合せ先
info@sap-labo.com
少しでもご興味ある方、ぜひお気軽にご連絡下さい!
新卒でSAPエンジニアとしてABAPでの新規開発や保守業務を担当。
業務内容としてはロジ系(MM/SD)がメインで、ABAPの開発が最も得意。