ABAP LOOP AT Anweisung: Interne Tabellen durchlaufen und verarbeiten

kategorie
ABAP-Statements
Veröffentlicht
autor
Johannes

Die LOOP AT-Anweisung ist eine der wichtigsten Kontrollstrukturen in ABAP zur Verarbeitung von internen Tabellen. Sie ermöglicht es, alle oder ausgewählte Zeilen einer internen Tabelle sequenziell zu durchlaufen und dabei auf jede einzelne Zeile zuzugreifen, um sie zu lesen, zu ändern oder zu löschen.

Syntax

Die grundlegende Syntax der LOOP AT-Anweisung bietet verschiedene Varianten für den Zugriff auf die Tabellenzeilen:

1. LOOP mit Arbeitsbereich (INTO)

LOOP AT <interne_tabelle> INTO <arbeitsbereich>
[WHERE <bedingung>]
[FROM <index1>] [TO <index2>].
" Anweisungsblock
" <arbeitsbereich> enthält eine Kopie der aktuellen Zeile
ENDLOOP.

2. LOOP mit Feldsymbol (ASSIGNING)

LOOP AT <interne_tabelle> ASSIGNING <feldsymbol>
[WHERE <bedingung>]
[FROM <index1>] [TO <index2>].
" Anweisungsblock
" <feldsymbol> zeigt direkt auf die aktuelle Zeile (kein Kopieren)
ENDLOOP.

3. LOOP mit Datenreferenz (REFERENCE INTO)

LOOP AT <interne_tabelle> REFERENCE INTO <datenreferenz>
[WHERE <bedingung>]
[FROM <index1>] [TO <index2>].
" Anweisungsblock
" <datenreferenz> enthält einen Zeiger auf die aktuelle Zeile
ENDLOOP.

4. LOOP ohne Zeilenzugriff (nur Zählen)

LOOP AT <interne_tabelle> TRANSPORTING NO FIELDS
[WHERE <bedingung>].
" Anweisungsblock (z.B. nur sy-tabix nutzen)
ENDLOOP.

Bestandteile

  • <interne_tabelle>: Die Tabelle, deren Zeilen durchlaufen werden sollen.
  • INTO <arbeitsbereich>: Der Inhalt der aktuellen Zeile wird in den Arbeitsbereich kopiert. Änderungen am Arbeitsbereich wirken sich nicht automatisch auf die Tabelle aus.
  • ASSIGNING <feldsymbol>: Das Feldsymbol zeigt direkt auf die aktuelle Zeile in der Tabelle. Änderungen am Feldsymbol ändern die Tabellenzeile unmittelbar.
  • REFERENCE INTO <datenreferenz>: Eine Datenreferenz, die auf die aktuelle Zeile zeigt. Zugriff über Dereferenzierung (->*).
  • WHERE <bedingung>: Filtert die zu durchlaufenden Zeilen. Nur Zeilen, die die Bedingung erfüllen, werden verarbeitet.
  • FROM <index1>: Startet den Loop ab der angegebenen Indexposition (nur bei Index-Tabellen).
  • TO <index2>: Beendet den Loop bei der angegebenen Indexposition (nur bei Index-Tabellen).
  • TRANSPORTING NO FIELDS: Es werden keine Feldinhalte transportiert. Nützlich zum Zählen oder wenn nur sy-tabix benötigt wird.

Systemfelder während des Loops

Innerhalb eines LOOP AT werden wichtige Systemfelder gesetzt:

  • sy-tabix: Enthält den aktuellen Zeilenindex der gerade verarbeiteten Zeile (bei Standardtabellen und sortierten Tabellen). Bei Hash-Tabellen ist sy-tabix nicht definiert (Wert 0).
  • sy-subrc: Nach dem ENDLOOP ist sy-subrc = 0, wenn mindestens eine Zeile verarbeitet wurde. sy-subrc = 4, wenn keine Zeile die Bedingungen erfüllte (leere Tabelle oder WHERE ohne Treffer).

Funktionsweise

  1. Die LOOP AT-Anweisung beginnt mit der ersten Zeile (oder der ersten passenden Zeile bei WHERE/FROM).
  2. Bei jeder Iteration wird die aktuelle Zeile über den gewählten Zugriffsmechanismus (INTO, ASSIGNING, REFERENCE INTO) bereitgestellt.
  3. Der Anweisungsblock zwischen LOOP AT und ENDLOOP wird für jede passende Zeile einmal ausgeführt.
  4. Nach der letzten Zeile (oder wenn keine Zeile mehr passt) endet der Loop, und das Programm fährt nach ENDLOOP fort.

Varianten und Zusätze

WHERE-Bedingung

Mit WHERE können Zeilen gefiltert werden, sodass nur bestimmte Zeilen durchlaufen werden:

LOOP AT lt_orders INTO ls_order WHERE status = 'OPEN'.
" Nur offene Bestellungen verarbeiten
ENDLOOP.

Die WHERE-Bedingung unterstützt:

  • Vergleichsoperatoren: =, <>, <, >, <=, >=
  • Logische Verknüpfungen: AND, OR, NOT
  • Bereichsprüfungen: BETWEEN, IN (für Ranges)
  • Pattern-Matching: CP, NP (für Zeichenketten)

FROM und TO (Indexbasiert)

Für Standardtabellen und sortierte Tabellen kann der Bereich eingeschränkt werden:

" Nur Zeilen 5 bis 10 verarbeiten
LOOP AT lt_data INTO ls_data FROM 5 TO 10.
" ...
ENDLOOP.
" Ab Zeile 100 bis zum Ende
LOOP AT lt_data INTO ls_data FROM 100.
" ...
ENDLOOP.

GROUP BY (Gruppierung)

Ab ABAP 7.40 können Zeilen während des Loops gruppiert werden:

LOOP AT lt_orders INTO ls_order
GROUP BY ( customer = ls_order-customer_id
size = GROUP SIZE )
INTO DATA(group).
" Gruppenverarbeitung
LOOP AT GROUP group INTO DATA(member).
" Einzelne Mitglieder der Gruppe
ENDLOOP.
ENDLOOP.

INTO vs. ASSIGNING vs. REFERENCE INTO

Die Wahl des Zugriffsmechanismus beeinflusst Performance und Funktionalität:

VarianteKopie?ÄnderungenPerformanceAnwendungsfall
INTOJaErfordert MODIFYLangsamerNur Lesen, keine Änderungen
ASSIGNINGNeinDirektSchnellerLesen und/oder Ändern
REFERENCE INTONeinÜber ->*SchnellerWenn Referenz benötigt wird

Empfehlung

  • Nur Lesen ohne Änderung: ASSIGNING (performanter als INTO)
  • Lesen und Ändern: ASSIGNING (Änderungen wirken sofort)
  • Referenz weitergeben: REFERENCE INTO
  • Kopie explizit gewünscht: INTO

Beispiele

1. Einfacher LOOP mit INTO

TYPES: BEGIN OF ty_material,
matnr TYPE matnr,
maktx TYPE maktx,
menge TYPE i,
END OF ty_material.
DATA: lt_materials TYPE STANDARD TABLE OF ty_material,
ls_material TYPE ty_material.
" Tabelle füllen (Beispieldaten)
lt_materials = VALUE #(
( matnr = 'MAT001' maktx = 'Schraube M6' menge = 100 )
( matnr = 'MAT002' maktx = 'Mutter M6' menge = 200 )
( matnr = 'MAT003' maktx = 'Scheibe M6' menge = 150 )
).
" Alle Materialien ausgeben
LOOP AT lt_materials INTO ls_material.
WRITE: / sy-tabix, ':', ls_material-matnr, ls_material-maktx.
ENDLOOP.

2. LOOP mit ASSIGNING und Wertänderung

FIELD-SYMBOLS: <fs_material> TYPE ty_material.
" Alle Mengen um 10% erhöhen
LOOP AT lt_materials ASSIGNING <fs_material>.
<fs_material>-menge = <fs_material>-menge * '1.1'.
ENDLOOP.
" Änderungen sind sofort in lt_materials wirksam!

3. LOOP mit WHERE-Bedingung

DATA: lv_total TYPE i VALUE 0.
" Nur Materialien mit Menge > 100 summieren
LOOP AT lt_materials INTO ls_material WHERE menge > 100.
lv_total = lv_total + ls_material-menge.
ENDLOOP.
WRITE: / 'Gesamtmenge (>100):', lv_total.
IF sy-subrc <> 0.
WRITE: / 'Keine Materialien mit Menge > 100 gefunden.'.
ENDIF.

4. LOOP mit REFERENCE INTO

DATA: lr_material TYPE REF TO ty_material.
LOOP AT lt_materials REFERENCE INTO lr_material.
" Zugriff über Dereferenzierung
lr_material->menge = lr_material->menge + 50.
ENDLOOP.

5. Zeilen im LOOP löschen

" Zeilen mit Menge = 0 entfernen
LOOP AT lt_materials ASSIGNING <fs_material>.
IF <fs_material>-menge = 0.
DELETE lt_materials.
ENDIF.
ENDLOOP.

Hinweis: Das Löschen von Zeilen innerhalb eines LOOP ist erlaubt. Der Loop setzt korrekt mit der nächsten Zeile fort. Siehe auch DELETE für weitere Varianten.

6. LOOP mit FROM/TO für Paginierung

CONSTANTS: lc_page_size TYPE i VALUE 10.
DATA: lv_page TYPE i VALUE 2,
lv_from TYPE i,
lv_to TYPE i.
lv_from = ( lv_page - 1 ) * lc_page_size + 1.
lv_to = lv_page * lc_page_size.
LOOP AT lt_materials INTO ls_material FROM lv_from TO lv_to.
" Zeilen 11-20 verarbeiten (Seite 2)
WRITE: / ls_material-matnr.
ENDLOOP.

7. TRANSPORTING NO FIELDS zum Zählen

DATA: lv_count TYPE i VALUE 0.
LOOP AT lt_materials TRANSPORTING NO FIELDS WHERE menge > 100.
lv_count = lv_count + 1.
ENDLOOP.
WRITE: / 'Anzahl Materialien mit Menge > 100:', lv_count.

Tipp: Für das reine Zählen ist die Funktion REDUCE oder lines() mit FILTER oft eleganter:

DATA(lv_count) = REDUCE i( INIT count = 0
FOR wa IN lt_materials WHERE ( menge > 100 )
NEXT count = count + 1 ).

Abgrenzung zu anderen Anweisungen

LOOP vs. READ TABLE

  • LOOP AT: Durchläuft mehrere/alle Zeilen sequenziell.
  • READ TABLE: Liest eine einzelne, spezifische Zeile (per Schlüssel oder Index).

Für den Zugriff auf eine einzelne Zeile ist READ TABLE performanter:

" Einzelne Zeile per Schlüssel
READ TABLE lt_materials INTO ls_material WITH KEY matnr = 'MAT001'.
" Einzelne Zeile per Index
READ TABLE lt_materials INTO ls_material INDEX 1.

LOOP vs. FOR-Ausdruck

Ab ABAP 7.40 gibt es den FOR-Ausdruck für Inline-Iterationen:

" Neue Tabelle mit gefilterten Daten erstellen
DATA(lt_filtered) = VALUE ty_materials(
FOR wa IN lt_materials WHERE ( menge > 100 )
( wa )
).

LOOP AT bleibt für komplexe Verarbeitungslogik mit mehreren Anweisungen die bevorzugte Wahl.

Schleifensteuerung

Innerhalb eines LOOP AT können folgende Anweisungen die Schleife steuern:

  • CONTINUE: Springt zur nächsten Iteration (überspringt den Rest des aktuellen Durchlaufs).
  • EXIT: Beendet die Schleife sofort und fährt nach ENDLOOP fort.
  • CHECK: Beendet die aktuelle Iteration, wenn die Bedingung falsch ist (wie IF NOT ... CONTINUE).
LOOP AT lt_materials ASSIGNING <fs_material>.
" Materialien ohne Text überspringen
CHECK <fs_material>-maktx IS NOT INITIAL.
" Bei speziellem Material abbrechen
IF <fs_material>-matnr = 'STOP'.
EXIT.
ENDIF.
" Verarbeitung...
ENDLOOP.

Performance-Tipps

  1. ASSIGNING statt INTO: Vermeidet das Kopieren von Daten und ist bei großen Strukturen deutlich schneller.

  2. WHERE-Bedingung nutzen: Filtert die zu verarbeitenden Zeilen und reduziert die Anzahl der Iterationen.

  3. Sekundärschlüssel: Bei häufigen WHERE-Abfragen auf bestimmte Felder kann ein Sekundärschlüssel die Performance verbessern. Siehe auch SORT für die Vorbereitung von binären Suchen.

  4. PARALLEL CURSOR: Bei der Verarbeitung von zwei sortierten Tabellen mit Beziehung zueinander kann die Parallel-Cursor-Technik die Performance drastisch verbessern:

DATA: lv_tabix TYPE sy-tabix VALUE 1.
LOOP AT lt_header INTO ls_header.
LOOP AT lt_items INTO ls_item FROM lv_tabix.
IF ls_item-header_id <> ls_header-id.
lv_tabix = sy-tabix.
EXIT.
ENDIF.
" Item verarbeiten...
ENDLOOP.
ENDLOOP.
  1. Vermeiden Sie verschachtelte LOOPs ohne Index: Zwei verschachtelte Loops über große Tabellen ohne Optimierung führen zu O(n²)-Komplexität.

Wichtige Hinweise / Best Practice

  • LOOP AT ist fundamental für die Arbeit mit internen Tabellen in ABAP. Laden Sie Daten zuerst mit SELECT aus der Datenbank.
  • Bevorzugen Sie ASSIGNING für bessere Performance und direkten Schreibzugriff.
  • Nutzen Sie WHERE-Bedingungen, um nur relevante Zeilen zu verarbeiten.
  • Vergessen Sie nie das abschließende ENDLOOP.
  • Prüfen Sie sy-subrc nach dem Loop, wenn Sie wissen müssen, ob Zeilen verarbeitet wurden.
  • Bei Hash-Tabellen ist sy-tabix nicht verfügbar – verwenden Sie stattdessen eigene Zähler wenn nötig.
  • Für moderne ABAP-Entwicklung (ab 7.40) prüfen Sie, ob FOR-Ausdrücke oder REDUCE für Ihren Anwendungsfall geeigneter sind.