web-dev-qa-db-ja.com

ループ内の内部テーブルから現在の行を削除します

内部テーブルをループしながらアクティブ行を安全に削除できますか?

例として、次のコードを検討してください。

LOOP AT lt_itab INTO ls_wa.
    IF [...] . " A check that can't be done inside a 'DELETE lt_itab WHERE'
        DELETE lt_itab INDEX sy-tabix
        " OR
        DELETE lt_itab FROM ls_wa.
    ENDIF.
ENDLOOP.

このようなレコードを削除しても安全ですか、それともこのロジックは意図したとおりに動作しませんか?

代わりに、行の一意の識別子を一時itabに保存し、DELETE lt_itab WHEREループの後?

現在の反復でロードされたレコード以外のレコードの削除操作は間違いなく問題を引き起こすと思いますが、これが有効かどうかはわかりません。

15
Lilienthal

安全かどうかは、コーディングスキルに大きく依存します。定義された結果があり、コマンドを正しく使用するかどうかはユーザー次第です。ループ内のDELETEステートメントの後に他に何も起こらなければ、通常は安全です。削除直後にCONTINUEステートメントを発行して、これが正しいことを確認できます。

DELETE lt_itab INDEX sy-tabixを使用しないでください。副作用としてsy-tabixを変更するチェック内のステートメントを使用する場合(たとえば、チェックテーブルでのエントリの検索-または呼び出しそうする汎用モジュール/メソッド)、間違った行を削除することになります。

削除する行は現在のものであるため、この例ではステートメントDELETE lt_itab.を単純に使用できることに注意してください。

テーブルに複数の同一行を含めることができる場合、2番目のバリアントDELETE lt_itab FROM ls_wa.は、現在の行だけでなく、それらすべてを削除します-意図するかどうかは要件によって異なります。


編集:「定義された結果」を繰り返すには:現在の行が削除されます。 「次の行に続く」ことはありません-INTO varを追加すると、実際にはコピー済み変数への行全体が追加されます。その変数は変更されず、テーブルと同期していません。これは意図的なものかもしれません-システムはこれを知る方法がありません。代わりにフィールドシンボルを使用する場合、それはUNASSIGNEDになります。これは-再び-意図したものかもしれませんが、そうでない場合もあります。

19
vwegert