COMMIT WORK/ROLLBACK WORK命令
21.2 COMMIT WORK/ROLLBACK WORK命令
DB更新(INSERT/UPDATE/DELETE)による変更は「トランザクション」として扱われ、変更を確定するにはコミット、元に戻すにはロールバックが必要です。
トランザクションは「ここからここまでワンセット」な処理単位を指します。
ABAPにおいては、構造に格納されたデータをDBテーブルへINSERT 、UPDATE、 DELETE 命令で行う処理までが一つのトランザクション(一連の処理)です。
このトランザクションによって変更が加えられたDBテーブルの状態を確定する場合は、
・コミット
という処理が必要となります。
そして、トランザクション(一連の処理)にて変更が加えられたDBテーブルの状態を変更前に戻したい場合は、
・ロールバック
という処理が必要となります。
明示的/暗黙的について
ABAPでは、コミット/ロールバックをソースコード内部に命令として記述する(明示的)ことも、
システムの都合で自動的に確定/破棄される(暗黙的)こともできます。
ただし意図したタイミングで処理結果を確定するため、基本は明示的に COMMIT WORK / ROLLBACK WORK を記述する前提で理解しましょう。
明示的コミット/暗黙的コミットについて
コミット(COMMIT WORK)は、DB更新による変更を確定する命令です。
INSERT/UPDATE/DELETE が成功しても、その時点では「確定済み」とは限りません。
後続処理で「確定後のDBの値」を前提に処理を続けたい場合は、AND WAIT を使用します。
明示的コミット
ソースコード内でCOMMIT WORK AND WAIT を使用すると、コミットが完了するまで処理を待機します。
後続処理で、DB 更新後の値を確実に参照したい場合に利用します。
教材では、コミットの成否を COMMIT自体のSY-SUBRCで判定するのではなく、
INSERT/UPDATE/DELETE命令のSY-SUBRCを判定した上で COMMIT/ROLLBACK を選ぶ、という流れで統一すると分かりやすくなります。
データベースの変更を前提としている処理が後続に控えている場合、 AND WAITオプションを利用して確実にデータベースの更新を確定させる必要があります。
サンプルコード
REPORT Z_SAMPLE211_INSERT.
" 選択画面:登録する名前(必須)
PARAMETERS P_NAME TYPE NAME OBLIGATORY.
START-OF-SELECTION.
" 登録用の作業データ(VALUE で必要項目だけ設定)
DATA(LS_DB) = VALUE ZDBTBL_TEST_DBOP(
NAME = P_NAME ).
" 1行 INSERT
INSERT INTO ZDBTBL_TEST_DBOP VALUES @LS_DB.
" 実行結果を確認(0:成功、それ以外:失敗)
IF SY-SUBRC = 0.
COMMIT WORK AND WAIT.
WRITE: / |INSERT 成功:NAME={ LS_DB-NAME }|.
ELSE.
ROLLBACK WORK.
WRITE: / |INSERT 失敗:SY-SUBRC={ SY-SUBRC }|.
ENDIF.
補足
SY-SUBRC
• 0・・・AND WAITオプションが指定されている&更新が正常終了
• 4・・・AND WAITオプションが指定されている&更新失敗
暗黙的コミット
通常は、DB更新(INSERT/UPDATE/DELETE)の結果を確定するには COMMIT WORKを明示的に実行します。一方、画面を持つ処理(オンライン処理)では、処理の区切り(ダイアログステップの終了など)に関連して、システム側でコミットが行われる場合があります(暗黙的コミット)
❏暗黙的コミットが発生するタイミング
・プログラム(処理)が正常終了したとき
・ダイアログステップが終了したとき(次のユーザー操作待ちになるとき)
・メッセージ表示などで処理が区切られる場合
(メッセージの種類や画面処理の流れによって、ダイアログステップが終了・中断されることがあります)
補足:ダイアログ/ダイアログステップとは
ABAP では、画面を持つ処理(オンライン処理)では、プログラムの実行がずっと続くのではなく、
「ユーザーの操作(ボタン押下やEnter)ごとに処理が区切られる」という特徴があります。
このとき、ユーザーの1回の操作から次の操作待ちになるまでのまとまりを、ダイアログステップと呼びます。
ダイアログステップが終わると、画面制御の都合で処理がいったん区切られます。
明示的ロールバック
ロールバック(ROLLBACK WORK)は、未確定の変更を破棄し、変更前の状態に戻す命令です。
たとえば、複数のDB更新を行う処理で途中の命令が失敗した場合、それまでに成功した更新が残ってしまう可能性があります。
そのような場合に、確実に変更を破棄したいときはROLLBACK WORKを実行します。
なお、ロールバックできるのはコミットされる前までです。コミット後に元へ戻すことはできません。
構文
サンプルコード
REPORT ZTEST_PROGRAM_DBOP_INSERT.
* 選択画面
PARAMETERS:
P_NAME TYPE NAME OBLIGATORY. " 名前(※必須項目)
* 変数
DATA:
WK_DB TYPE ZDBTBL_TEST_DBOP.
* 主処理
START-OF-SELECTION.
WK_DB-NAME = P_NAME. " 名前
INSERT INTO ZDBTBL_TEST_DBOP VALUES WK_DB.
* 正常終了ならコミット
IF SY-SUBRC = 0.
COMMIT WORK AND WAIT.
ELSE.
ROLLBACK.
ENDIF.
END-OF-SELECTION.
INSERT命令などが失敗したとしても、レコードに一部が入ってしまっている場合などがあります。 その変更を確実に破棄し、INSERT命令実行前の状態に戻したい場合は必ずROLLBACK WORK命令を実行します。
暗黙的ロールバック
ロールバックは「ROLLBACK WORK」を明示的に書かなくても、処理が継続できない状況では暗黙的に行われる場合があります。
代表的なのは、実行時エラー(ショートダンプ)などにより、プログラムが正常に処理を続けられないときです。
ただし、ロールバックで元に戻せるのは コミットされる前の未確定の変更だけです。
一度「COMMIT WORK」により確定した変更は、暗黙的ロールバックでも取り消すことはできません。
■ 暗黙的ロールバックが発生する代表例
・実行時エラー(ショートダンプ)が発生したとき
(処理の継続が不可能なため、未確定の変更が破棄されることがあります)
・プログラムが強制終了されたとき
(例:システム障害、セッション終了などにより、処理が途中で終了した場合)
※注意:すべてのエラーが暗黙的ロールバックになるわけではありません。
たとえば、エラーメッセージを表示して処理を終了するだけの場合など、状況によって扱いが異なります。
更新を確実に取り消したい場合は、条件分岐でROLLBACK WORKを明示的に実行するのが基本です。