ABAP Forum
cancel
Turn on suggestions
Showing results for
Search instead for
Did you mean:
The next set of progression badges have been announced! Let's Discuss!
Read only

Syntax error cannot change itab inside LOOP AT itab GROUP BY ...

Sandra_Rossi
Active Contributor

‎2025 Oct 19 1:19 PM

913

I get this syntax error (the message is different depending on the ABAP version - NB: the message ID is MESSAGEGAC in table TRMSG):

  • ABAP 7.40: You may not delete or overwrite table "ITAB" within a LOOP over itself. that internal optimization can take place.
  • ABAP 7.58: The table "ITAB" cannot be deleted or overwritten within a loop across itself.

It happens in the line 6 (DELETE itab) of this code, used to delete the lines which are not of type 'E':

DATA(itab) = VALUE bapirettab( ( type = 'S' ) ( type = 'S' ) ( type = 'E' ) ).
LOOP AT itab REFERENCE INTO DATA(line)
 GROUP BY line->type.
 IF line->type <> 'E'.
 LOOP AT GROUP line TRANSPORTING NO FIELDS.
 DELETE itab INDEX sy-tabix.
 ENDLOOP.
 ENDIF.
ENDLOOP.

NB: of course, this code may be reduced to one line, its only goal is to support the question, my original code is much more complex.

Thanks.

Sandra

For information, I did other tests with other statements to change the internal table:

  1. The same syntax error happens if these statements are used: APPEND, INSERT, FREE, REFRESH, CLEAR itab, SORT.
  2. This other syntax error may happen if MODIFY itab FROM VALUE #( ) is used instead of DELETE: "The implicit variants "DELETE itab." and "MODIFY itab FROM wa." cannot be used in a "LOOP AT itab ... USING KEY keyname ..." (message MESSAGEGJI in the table TRMSG).
  3. If the table is modified indirectly (via a subroutine, a reference, a field symbol or whatever), a short dump happens instead (TABLE_ILLEGAL_STATEMENT, TABLE_FREE_IN_LOOP, etc.)
  4. The only case which works is this one: MODIFY itab FROM VALUE #( ) INDEX idx.
1 ACCEPTED SOLUTION
Read only

Sandra_Rossi
Active Contributor

‎2025 Oct 19 1:21 PM - edited ‎2025 Oct 19 6:32 PM

910

The syntax error is because "The internal table itab cannot be modified in the group loop [...]" (LOOP AT itab, GROUP BY | ABAP Keyword Documentation).

NB: the sentence is completed with "unless the addition WITHOUT MEMBERS is specified", because in that case the group keys are determined before the loop starts (grouping phase), then the loop starts on the group keys (Group Loop phase), so any modification to itab is valid because internally it's no more a loop on the itab lines (it was one only during the grouping phase), it's a loop on the group keys.

Now, the solution is simply to delay the modifications after the loop. There are two solutions:

Solution 1

During the loop, you need to save what is to be done to the internal table in a journal.

NB: it's important to delete from the end otherwise you would delete the wrong lines because the table indexes of the lines after the deleted line are changed.

DATA(itab) = VALUE bapirettab( ( type = 'S' ) ( type = 'S' ) ( type = 'E' ) ).
DATA itab_tabix TYPE TABLE OF sytabix. "<====== add
LOOP AT itab REFERENCE INTO DATA(line)
 GROUP BY line->type.
 IF line->type <> 'E'.
 LOOP AT GROUP line TRANSPORTING NO FIELDS.
 INSERT sy-tabix INTO TABLE itab_tabix. "<====== add
 ENDLOOP.
 ENDIF.
ENDLOOP.
SORT itab_tabix BY table_line DESCENDING. "<====== add these 4 lines
LOOP AT itab_tabix INTO DATA(tabix).
 DELETE itab INDEX tabix.
ENDLOOP.

EDIT enhanced solution proposed by @wridgeu : SORT not needed if using STEP -1, instead of the 4 last lines:

LOOP AT itab_tabix INTO DATA(tabix) STEP -1.
 DELETE itab INDEX tabix.
ENDLOOP.

Solution 2

If the internal table is small you may duplicate the internal table, do the changes immediately to the duplicated, and after the loop transfer back the values to the original internal table.

DATA(itab) = VALUE bapirettab( ( type = 'S' ) ( type = 'S' ) ( type = 'E' ) ).
DATA(itab_duplicate) = itab. "<====== add
LOOP AT itab REFERENCE INTO DATA(line)
 GROUP BY line->type.
 IF line->type <> 'E'.
 LOOP AT GROUP line TRANSPORTING NO FIELDS.
 DELETE itab_duplicate INDEX sy-tabix. "<====== add
 ENDLOOP.
 ENDIF.
ENDLOOP.
itab = itab_duplicate. "<====== add
2 REPLIES 2
Read only

Sandra_Rossi
Active Contributor

‎2025 Oct 19 1:21 PM - edited ‎2025 Oct 19 6:32 PM

911

The syntax error is because "The internal table itab cannot be modified in the group loop [...]" (LOOP AT itab, GROUP BY | ABAP Keyword Documentation).

NB: the sentence is completed with "unless the addition WITHOUT MEMBERS is specified", because in that case the group keys are determined before the loop starts (grouping phase), then the loop starts on the group keys (Group Loop phase), so any modification to itab is valid because internally it's no more a loop on the itab lines (it was one only during the grouping phase), it's a loop on the group keys.

Now, the solution is simply to delay the modifications after the loop. There are two solutions:

Solution 1

During the loop, you need to save what is to be done to the internal table in a journal.

NB: it's important to delete from the end otherwise you would delete the wrong lines because the table indexes of the lines after the deleted line are changed.

DATA(itab) = VALUE bapirettab( ( type = 'S' ) ( type = 'S' ) ( type = 'E' ) ).
DATA itab_tabix TYPE TABLE OF sytabix. "<====== add
LOOP AT itab REFERENCE INTO DATA(line)
 GROUP BY line->type.
 IF line->type <> 'E'.
 LOOP AT GROUP line TRANSPORTING NO FIELDS.
 INSERT sy-tabix INTO TABLE itab_tabix. "<====== add
 ENDLOOP.
 ENDIF.
ENDLOOP.
SORT itab_tabix BY table_line DESCENDING. "<====== add these 4 lines
LOOP AT itab_tabix INTO DATA(tabix).
 DELETE itab INDEX tabix.
ENDLOOP.

EDIT enhanced solution proposed by @wridgeu : SORT not needed if using STEP -1, instead of the 4 last lines:

LOOP AT itab_tabix INTO DATA(tabix) STEP -1.
 DELETE itab INDEX tabix.
ENDLOOP.

Solution 2

If the internal table is small you may duplicate the internal table, do the changes immediately to the duplicated, and after the loop transfer back the values to the original internal table.

DATA(itab) = VALUE bapirettab( ( type = 'S' ) ( type = 'S' ) ( type = 'E' ) ).
DATA(itab_duplicate) = itab. "<====== add
LOOP AT itab REFERENCE INTO DATA(line)
 GROUP BY line->type.
 IF line->type <> 'E'.
 LOOP AT GROUP line TRANSPORTING NO FIELDS.
 DELETE itab_duplicate INDEX sy-tabix. "<====== add
 ENDLOOP.
 ENDIF.
ENDLOOP.
itab = itab_duplicate. "<====== add
Read only

wridgeu

‎2025 Oct 19 4:11 PM

850

Hi Sandra, one small addition to the first solution could be the use of STEP -1 (reverse LOOP) instead of sorting (finally, a use-case ^^).

AltStyle によって変換されたページ (->オリジナル) /