17

Can I safely delete the active row while looping over an internal table?

As an example, consider this code:

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.

Is it safe to delete records like this or will this logic not behave as intended?

Should I instead store the unique identifier for the rows in a temporary itab and run a DELETE lt_itab WHERE after the loop?

I assume that delete operations on records other than the one that is loaded in the current iteration will definitely cause issues but I'm unsure if this is a valid, let alone good practice.

Suncatcher
  • 10,355
  • 10
  • 52
  • 90
Lilienthal
  • 4,327
  • 13
  • 52
  • 88

2 Answers2

25

Whether it is safe or not depends largely on your coding skills. It has a defined result, and it's up to you to use the commands correctly. It is usually safe if nothing else happens after the DELETE statement within the loop. You can issue a CONTINUE statement right after the deletion to make sure that this is the case.

Do not use DELETE lt_itab INDEX sy-tabix. If you use some statement within your check that changes sy-tabix as a side effect (for example, looking up some entry in a check table - or calling a function module/method that does so), you will end up deleting the wrong lines.

Be aware that you can simply use the statement DELETE lt_itab. in your example since the line to delete is the current one.

If your table can have multiple identical lines, your second variant DELETE lt_itab FROM ls_wa. will delete all of them, not just the current one - whether that is intended depends on your requirements.


EDIT: To reiterate the "defined result": The current line is deleted. There is no "continuing with the next line" - with the addition INTO var you actually copied the entire line into your variable. That variable won't be touched, it's just out of sync with the table. This might be intentional - the system has no way of knowing this. If you use a field symbol instead, it will be UNASSIGNED, which - again - might be what you intended - and then again maybe not.

vwegert
  • 18,371
  • 3
  • 37
  • 55
  • So the defined result you mention is that the current line is deleted with the loop continuing with the next line of the table without skipping lines or ending prematurely? In other words, is looping over an internal table to delete a subset of its lines a good practice when `DELETE ... WHERE` is not an option and no other logic is included in the loop? – Lilienthal May 13 '14 at 13:49
  • 1
    I've added some more details on the "defined result" - but I'd say that yes, this is common and good practice when implemented correctly. – vwegert May 13 '14 at 14:12
  • Hello, just a remark-question - is your answer also valid, if I delete not current row, but some furhter arbitrary ones? E.g. LOOP AT itab ASSIGNING WHERE cond = X. DELETE itab WHERE id -id = id AND cond <> X. ENDLOOP. Thank you! – 87element Dec 01 '15 at 16:36
  • 2
    @87element Basically yes. Bottom line: If you change the dataset you're currently iterating through, you'd better make sure you know what you're doing. – vwegert Dec 01 '15 at 17:25
-3

Try this:

GET CURSOR LINE SY-CUROW .
DELETE ST_MAT INDEX SY-CUROW.
Pang
  • 9,564
  • 146
  • 81
  • 122
  • Generally, advising to use `GET CURSOR LINE` without any list processing information (that the OP did not give) is at least misleading and very probably just wrong. – vwegert May 24 '18 at 05:41