Die COLLECT
-Anweisung ist ein spezieller Befehl in ABAP, der zum Verdichten bzw. Aggregieren von Daten in einer *
internen Tabelle* dient. Die Besonderheit von COLLECT
ist:
- Es prüft, ob in der Zieltabelle bereits eine Zeile existiert, deren Schlüssel mit dem der hinzuzufügenden Zeile
übereinstimmt. Der “Schlüssel” für
COLLECT
besteht dabei immer aus allen nicht-numerischen Feldern der Tabellenzeile (also alles außer TypI
,P
,F
,DECFLOAT16/34
). - Wenn eine Zeile mit identischem nicht-numerischen Schlüssel gefunden wird: Die Werte aller numerischen Felder der hinzuzufügenden Zeile werden zu den Werten der entsprechenden numerischen Felder der bereits vorhandenen Zeile hinzuaddiert.
- Wenn keine Zeile mit identischem nicht-numerischen Schlüssel gefunden wird: Die hinzuzufügende Zeile wird als *
neuer Eintrag* in die Tabelle eingefügt (ähnlich wie bei
[APPEND](/append-statement/)
für Standardtabellen oderINSERT
für Hash-Tabellen).
COLLECT
ist also ideal, um Summen oder Zählungen über bestimmte Merkmale zu bilden (z.B. Gesamtmenge pro Material und
Werk).
Syntax
COLLECT <wa> INTO <interne_tabelle> [ASSIGNING <feldsymbol> | REFERENCE INTO <datenreferenz>].
COLLECT
: Das ABAP-Schlüsselwort.<wa>
: Ein Arbeitsbereich (Struktur), der zum Zeilentyp der<interne_tabelle>
kompatibel ist.- Die nicht-numerischen Felder in
<wa>
bilden den Schlüssel für die Suche/Aggregation. - Die numerischen Felder in
<wa>
enthalten die Werte, die ggf. zu einer bestehenden Zeile addiert werden.
- Die nicht-numerischen Felder in
INTO <interne_tabelle>
: Die interne Zieltabelle, in der aggregiert oder eingefügt wird.ASSIGNING <feldsymbol>
/REFERENCE INTO <datenreferenz>
(Optional): Nach der Operation zeigt das Feldsymbol bzw. die Datenreferenz auf die Zeile in der Tabelle, die entweder neu eingefügt oder deren numerische Werte gerade aktualisiert wurden. Dies ist nützlich für den direkten Zugriff auf das Ergebnis.
Funktionsweise und Verhalten nach Tabellentyp (Wichtig!)
Die Eignung und Effizienz von COLLECT
hängt stark vom Typ der Zieltabelle ab:
1. Standardtabellen (STANDARD TABLE
)
COLLECT
ist erlaubt.- Die Suche nach einer Zeile mit passendem nicht-numerischen Schlüssel erfolgt durch sequenzielles Lesen der Tabelle. Dies kann bei großen Tabellen sehr langsam werden!
- Wird kein passender Schlüssel gefunden, wird die Zeile aus
<wa>
am Ende der Tabelle angehängt (wieAPPEND
). sy-tabix
wird auf den Index der modifizierten oder neu angehängten Zeile gesetzt.
2. Hashed-Tabellen (HASHED TABLE
)
COLLECT
ist erlaubt und oft der effizienteste Anwendungsfall, ABER NUR WENN der eindeutige Schlüssel ( UNIQUE KEY) der Hash-Tabelle exakt aus allen nicht-numerischen Feldern der Zeilenstruktur besteht und * keine numerischen Felder* enthält.- Ist diese Bedingung erfüllt, nutzt
COLLECT
den Hash-Algorithmus für eine sehr schnelle Suche nach dem Schlüssel. - Wird kein passender Schlüssel gefunden, wird die Zeile eingefügt (wie
INSERT
). sy-tabix
ist hier undefiniert (meist 0), da der Index bei Hash-Tabellen keine Rolle spielt.- Achtung: Stimmt der definierte Schlüssel der Hash-Tabelle nicht mit dem impliziten
COLLECT
-Schlüssel (alle nicht-numerischen Felder) überein, führt die Verwendung vonCOLLECT
zu einem Laufzeitfehler!
3. Sortierte Tabellen (SORTED TABLE
)
- Die Verwendung von
COLLECT
mit sortierten Tabellen ist dringend abzuraten und führt oft zu Laufzeitfehlern! COLLECT
ignoriert die definierte Sortierreihenfolge der Tabelle und arbeitet nur mit seinem eigenen impliziten Schlüssel (alle nicht-numerischen Felder). Das Einfügen oder Aggregieren kann die Sortierung verletzen und zu inkonsistenten Zuständen oder direkten Abbrüchen führen.- Für Aggregationen in sortierten Tabellen: Verwende stattdessen eine manuelle Logik mit
READ TABLE <tabelle> WITH KEY ... BINARY SEARCH
, gefolgt vonMODIFY <tabelle> ...
(wenn gefunden) oderINSERT <wa> INTO TABLE <tabelle>
(wenn nicht gefunden).
Systemfelder
sy-subrc
: Wird durchCOLLECT
normalerweise immer auf0
gesetzt, egal ob eine Zeile aggregiert oder neu eingefügt wurde. Er ist daher kein guter Indikator dafür, was passiert ist.sy-tabix
: Sinnvoll nur bei Standardtabellen, wo er den Index der bearbeiteten/neu eingefügten Zeile enthält. Bei Hash-Tabellen ist er 0/undefiniert.
Beispiele
1. Aggregation in Standardtabelle (Menge pro Material)
TYPES: BEGIN OF ty_mat_quant, material TYPE string, " Schlüssel (nicht-numerisch) quantity TYPE i, " Wert (numerisch) END OF ty_mat_quant.
DATA: lt_summary TYPE STANDARD TABLE OF ty_mat_quant, ls_data TYPE ty_mat_quant.
ls_data = VALUE #( material = 'M-01' quantity = 10 ).COLLECT ls_data INTO lt_summary.
ls_data = VALUE #( material = 'M-02' quantity = 5 ).COLLECT ls_data INTO lt_summary.
ls_data = VALUE #( material = 'M-01' quantity = 7 ). " Wird zu M-01 addiertCOLLECT ls_data INTO lt_summary.
cl_demo_output=>display( lt_summary )." Ausgabe:" Material | Quantity" ---------|---------" M-01 | 17" M-02 | 5
2. Effiziente Aggregation in Hashed-Tabelle (Menge pro Material/Werk)
TYPES: BEGIN OF ty_stock, matnr TYPE matnr, " Teil des Schlüssels werks TYPE werks_d, " Teil des Schlüssels menge TYPE i, " Wert END OF ty_stock.
" Schlüssel der Hash-Tabelle MUSS den nicht-numerischen Feldern entsprechen!DATA lt_stock_agg TYPE HASHED TABLE OF ty_stock WITH UNIQUE KEY matnr werks.DATA ls_stock TYPE ty_stock.
ls_stock = VALUE #( matnr = 'MAT1' werks = '1000' menge = 100 ).COLLECT ls_stock INTO lt_stock_agg.
ls_stock = VALUE #( matnr = 'MAT2' werks = '1000' menge = 50 ).COLLECT ls_stock INTO lt_stock_agg.
ls_stock = VALUE #( matnr = 'MAT1' werks = '1000' menge = 25 ). " Wird addiertCOLLECT ls_stock INTO lt_stock_agg.
ls_stock = VALUE #( matnr = 'MAT1' werks = '2000' menge = 200 ). " Neuer EintragCOLLECT ls_stock INTO lt_stock_agg.
cl_demo_output=>display( lt_stock_agg )." Ausgabe (Reihenfolge bei Hash nicht definiert):" Matnr | Werks | Menge" ------|-------|------" MAT1 | 1000 | 125" MAT2 | 1000 | 50" MAT1 | 2000 | 200
3. Verwendung von ASSIGNING
FIELD-SYMBOLS: <fs_stock_line> LIKE LINE OF lt_stock_agg.
ls_stock = VALUE #( matnr = 'MAT1' werks = '1000' menge = 5 ).COLLECT ls_stock INTO lt_stock_agg ASSIGNING <fs_stock_line>.
IF <fs_stock_line> IS ASSIGNED. WRITE: / 'Aggregierte/Neue Zeile:', <fs_stock_line>-matnr, <fs_stock_line>-werks, 'Menge:', <fs_stock_line>-menge. " Ausgabe z.B.: Aggregierte/Neue Zeile: MAT1 1000 Menge: 130 (wenn vorher 125 drin war)ENDIF.
Wichtige Hinweise / Best Practice
COLLECT
ist das spezielle Werkzeug für die Aggregation numerischer Werte basierend auf einem nicht-numerischen Schlüssel in internen Tabellen.- Es modifiziert die Zieltabelle direkt.
- Für optimale Performance nutze
COLLECT
mit Hashed-Tabellen, deren Schlüssel korrekt definiert ist (Unique Key = alle nicht-numerischen Felder). - Verwende
COLLECT
nicht mit sortierten Tabellen – nutze stattdessenREAD
/MODIFY
/INSERT
. - Bei Standardtabellen bedenke die potenzielle Performance-Implikation bei großen Datenmengen.