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 ZeileENDLOOP.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 ZeileENDLOOP.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 nursy-tabixbenö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 istsy-tabixnicht definiert (Wert 0).sy-subrc: Nach demENDLOOPistsy-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
- Die
LOOP AT-Anweisung beginnt mit der ersten Zeile (oder der ersten passenden Zeile beiWHERE/FROM). - Bei jeder Iteration wird die aktuelle Zeile über den gewählten Zugriffsmechanismus (
INTO,ASSIGNING,REFERENCE INTO) bereitgestellt. - Der Anweisungsblock zwischen
LOOP ATundENDLOOPwird für jede passende Zeile einmal ausgeführt. - Nach der letzten Zeile (oder wenn keine Zeile mehr passt) endet der Loop, und das Programm fährt nach
ENDLOOPfort.
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 verarbeitenENDLOOP.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 verarbeitenLOOP AT lt_data INTO ls_data FROM 5 TO 10. " ...ENDLOOP.
" Ab Zeile 100 bis zum EndeLOOP 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:
| Variante | Kopie? | Änderungen | Performance | Anwendungsfall |
|---|---|---|---|---|
INTO | Ja | Erfordert MODIFY | Langsamer | Nur Lesen, keine Änderungen |
ASSIGNING | Nein | Direkt | Schneller | Lesen und/oder Ändern |
REFERENCE INTO | Nein | Über ->* | Schneller | Wenn Referenz benötigt wird |
Empfehlung
- Nur Lesen ohne Änderung:
ASSIGNING(performanter alsINTO) - 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 ausgebenLOOP 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öhenLOOP 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 summierenLOOP 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 entfernenLOOP 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üsselREAD TABLE lt_materials INTO ls_material WITH KEY matnr = 'MAT001'.
" Einzelne Zeile per IndexREAD 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 erstellenDATA(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 nachENDLOOPfort.CHECK: Beendet die aktuelle Iteration, wenn die Bedingung falsch ist (wieIF 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
-
ASSIGNINGstattINTO: Vermeidet das Kopieren von Daten und ist bei großen Strukturen deutlich schneller. -
WHERE-Bedingung nutzen: Filtert die zu verarbeitenden Zeilen und reduziert die Anzahl der Iterationen.
-
Sekundärschlüssel: Bei häufigen WHERE-Abfragen auf bestimmte Felder kann ein Sekundärschlüssel die Performance verbessern. Siehe auch
SORTfür die Vorbereitung von binären Suchen. -
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.- 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 ATist fundamental für die Arbeit mit internen Tabellen in ABAP. Laden Sie Daten zuerst mitSELECTaus der Datenbank.- Bevorzugen Sie
ASSIGNINGfü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-subrcnach dem Loop, wenn Sie wissen müssen, ob Zeilen verarbeitet wurden. - Bei Hash-Tabellen ist
sy-tabixnicht 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 oderREDUCEfür Ihren Anwendungsfall geeigneter sind.