Field-Symbols sind ein zentrales Konzept in ABAP für den dynamischen Zugriff auf Speicherbereiche. Im Gegensatz zu normalen Variablen, die Daten kopieren, zeigt ein Field-Symbol direkt auf den Speicherbereich einer anderen Variable – ähnlich wie Zeiger (Pointer) in anderen Programmiersprachen.
Grundkonzept
- Ein Field-Symbol ist ein Platzhalter, der auf einen Speicherbereich zeigt
- Es wird mit
ASSIGNauf eine konkrete Variable “zugewiesen” - Änderungen am Field-Symbol ändern direkt die Originalvariable
- Kein Kopieren von Daten = bessere Performance
Syntax
Field-Symbol deklarieren
" Mit konkretem TypFIELD-SYMBOLS: <fs_name> TYPE <typ>.
" Mit generischem TypFIELD-SYMBOLS: <fs_any> TYPE any.FIELD-SYMBOLS: <fs_data> TYPE data.FIELD-SYMBOLS: <fs_table> TYPE ANY TABLE.FIELD-SYMBOLS: <fs_structure> TYPE any.
" Inline-Deklaration (ab 7.40)ASSIGN variable TO FIELD-SYMBOL(<fs_inline>).ASSIGN-Varianten
" Statische ZuweisungASSIGN <variable> TO <fs>.
" Dynamische Zuweisung (Feldname als String)ASSIGN (lv_fieldname) TO <fs>.
" Komponente einer StrukturASSIGN COMPONENT <name_oder_index> OF STRUCTURE <struktur> TO <fs>.
" Mit Typ-CastingASSIGN <variable> TO <fs> CASTING TYPE <typ>.Systemfelder
Nach ASSIGN:
sy-subrc:0: Zuweisung erfolgreich4: Zuweisung fehlgeschlagen (Variable existiert nicht oder Typ inkompatibel)
Beispiele
1. Grundlegende Verwendung
DATA: lv_number TYPE i VALUE 100.FIELD-SYMBOLS: <fs_num> TYPE i.
" Field-Symbol auf Variable zuweisenASSIGN lv_number TO <fs_num>.
IF sy-subrc = 0. " Änderung über Field-Symbol <fs_num> = 200.
WRITE: / 'Original:', lv_number. " Ausgabe: 200ENDIF.2. Field-Symbol prüfen
FIELD-SYMBOLS: <fs> TYPE any.
" Vor Verwendung prüfen!IF <fs> IS ASSIGNED. " Field-Symbol zeigt auf gültige Daten WRITE: / <fs>.ELSE. " Field-Symbol ist nicht zugewiesen WRITE: / 'Field-Symbol nicht zugewiesen!'.ENDIF.
" Zuweisung aufhebenUNASSIGN <fs>.3. Field-Symbols mit internen Tabellen (LOOP)
Der häufigste Anwendungsfall – direkter Zugriff auf Tabellenzeilen:
TYPES: BEGIN OF ty_material, matnr TYPE matnr, menge TYPE i, preis TYPE p DECIMALS 2, END OF ty_material.
DATA: lt_materials TYPE TABLE OF ty_material.
lt_materials = VALUE #( ( matnr = 'MAT001' menge = 100 preis = '10.00' ) ( matnr = 'MAT002' menge = 200 preis = '20.00' ) ( matnr = 'MAT003' menge = 150 preis = '15.00' )).
" Mit Field-Symbol: Direkter Zugriff, keine KopieFIELD-SYMBOLS: <fs_mat> TYPE ty_material.
LOOP AT lt_materials ASSIGNING <fs_mat>. " Änderung wirkt direkt in der Tabelle <fs_mat>-preis = <fs_mat>-preis * '1.1'. " 10% ErhöhungENDLOOP.
" Tabelle ist jetzt geändert!4. Inline Field-Symbol Deklaration
" Modern (ab 7.40): Inline-DeklarationLOOP AT lt_materials ASSIGNING FIELD-SYMBOL(<fs_inline>). <fs_inline>-menge = <fs_inline>-menge + 50.ENDLOOP.
" Auch mit READ TABLEREAD TABLE lt_materials ASSIGNING FIELD-SYMBOL(<fs_read>) WITH KEY matnr = 'MAT001'.
IF sy-subrc = 0. <fs_read>-preis = 99.ENDIF.5. Dynamischer Zugriff auf Strukturkomponenten
TYPES: BEGIN OF ty_person, vorname TYPE string, nachname TYPE string, alter TYPE i, END OF ty_person.
DATA: ls_person TYPE ty_person.FIELD-SYMBOLS: <fs_field> TYPE any.
ls_person = VALUE #( vorname = 'Max' nachname = 'Müller' alter = 30 ).
" Zugriff über KomponentenindexDO 3 TIMES. ASSIGN COMPONENT sy-index OF STRUCTURE ls_person TO <fs_field>. IF sy-subrc = 0. WRITE: / 'Feld', sy-index, ':', <fs_field>. ENDIF.ENDDO.
" Zugriff über Komponentenname (als String)DATA: lv_fieldname TYPE string VALUE 'NACHNAME'.
ASSIGN COMPONENT lv_fieldname OF STRUCTURE ls_person TO <fs_field>.IF sy-subrc = 0. WRITE: / 'Nachname:', <fs_field>.ENDIF.6. Dynamischer Variablenzugriff
DATA: lv_var1 TYPE string VALUE 'Wert 1', lv_var2 TYPE string VALUE 'Wert 2', lv_name TYPE string.
FIELD-SYMBOLS: <fs_dynamic> TYPE any.
" Variablenname dynamisch aus Stringlv_name = 'LV_VAR1'.ASSIGN (lv_name) TO <fs_dynamic>.
IF sy-subrc = 0. WRITE: / 'Dynamisch:', <fs_dynamic>. " Wert 1ENDIF.
" Auch für globale Variablen mit vollem Pfad" ASSIGN ('(PROGRAMNAME)GLOBALVAR') TO <fs>.7. CASTING - Typ-Konvertierung
DATA: lv_hex TYPE x LENGTH 4 VALUE '41424344'.FIELD-SYMBOLS: <fs_char> TYPE c.
" Hex-Daten als Zeichen interpretierenASSIGN lv_hex TO <fs_char> CASTING TYPE c.
WRITE: / <fs_char>. " Ausgabe: ABCD
" Casting mit StrukturenDATA: lv_raw TYPE x LENGTH 8.FIELD-SYMBOLS: <fs_struct> TYPE ty_small_struct.
ASSIGN lv_raw TO <fs_struct> CASTING.8. Generische Field-Symbols
FIELD-SYMBOLS: <fs_any> TYPE any, " Beliebiger Datentyp <fs_data> TYPE data, " Beliebige Daten (nicht Objekte) <fs_table> TYPE ANY TABLE. " Beliebige interne Tabelle
DATA: lt_any TYPE TABLE OF string.
" Generisches Field-Symbol für TabellenASSIGN lt_any TO <fs_table>.
IF <fs_table> IS ASSIGNED. LOOP AT <fs_table> ASSIGNING <fs_any>. WRITE: / <fs_any>. ENDLOOP.ENDIF.9. Field-Symbol auf Tabellenzeile mit Index
DATA: lt_data TYPE TABLE OF string.
lt_data = VALUE #( ( `Eins` ) ( `Zwei` ) ( `Drei` ) ).
FIELD-SYMBOLS: <fs_line> TYPE string.
" Direkter Zugriff auf Zeile 2ASSIGN lt_data[ 2 ] TO <fs_line>.
IF sy-subrc = 0. <fs_line> = 'GEÄNDERT'.ENDIF.
" lt_data enthält jetzt: Eins, GEÄNDERT, Drei10. Verschachtelte Strukturen dynamisch durchlaufen
DATA: lo_struct_descr TYPE REF TO cl_abap_structdescr, lt_components TYPE abap_compdescr_tab.
FIELD-SYMBOLS: <fs_comp> TYPE abap_compdescr, <fs_val> TYPE any.
" Strukturbeschreibung ermittelnlo_struct_descr ?= cl_abap_typedescr=>describe_by_data( ls_person ).lt_components = lo_struct_descr->components.
" Alle Komponenten durchlaufenLOOP AT lt_components ASSIGNING <fs_comp>. ASSIGN COMPONENT <fs_comp>-name OF STRUCTURE ls_person TO <fs_val>. IF sy-subrc = 0. WRITE: / <fs_comp>-name, '=', <fs_val>. ENDIF.ENDLOOP.Field-Symbol vs. INTO (Performance)
| Aspekt | ASSIGNING (Field-Symbol) | INTO (Arbeitsbereich) |
|---|---|---|
| Datenkopie | Nein | Ja |
| Performance | Schneller | Langsamer |
| Änderungen | Direkt in Tabelle | Erfordert MODIFY |
| Speicher | Minimal | Zusätzlicher Speicher |
" LANGSAM: Kopieren und zurückschreibenLOOP AT lt_materials INTO ls_material. ls_material-preis = ls_material-preis * 2. MODIFY lt_materials FROM ls_material.ENDLOOP.
" SCHNELL: Direkter ZugriffLOOP AT lt_materials ASSIGNING <fs_mat>. <fs_mat>-preis = <fs_mat>-preis * 2.ENDLOOP.Häufige Fehler
1. Nicht zugewiesenes Field-Symbol verwenden
FIELD-SYMBOLS: <fs> TYPE any.
" FEHLER: Field-Symbol nicht zugewiesen!" WRITE: / <fs>. " Runtime Error!
" RICHTIG: Immer prüfenIF <fs> IS ASSIGNED. WRITE: / <fs>.ENDIF.2. Field-Symbol nach Tabellenänderung ungültig
LOOP AT lt_data ASSIGNING FIELD-SYMBOL(<fs>). " VORSICHT: DELETE kann das Field-Symbol ungültig machen! IF <fs>-status = 'X'. DELETE lt_data. " <fs> zeigt jetzt ins Nichts! ENDIF.ENDLOOP.3. Typ-Inkompatibilität
DATA: lv_string TYPE string VALUE 'Test'.FIELD-SYMBOLS: <fs_int> TYPE i.
" FEHLER: Inkompatible TypenASSIGN lv_string TO <fs_int>.IF sy-subrc <> 0. WRITE: / 'Zuweisung fehlgeschlagen!'.ENDIF.Wichtige Hinweise / Best Practice
- Prüfen Sie immer
sy-subrcnachASSIGNoderIS ASSIGNEDvor Verwendung. - Verwenden Sie ASSIGNING in
LOOP ATstatt INTO für bessere Performance. - Field-Symbols sind ideal für dynamische Programmierung.
- Nutzen Sie die Inline-Deklaration (
FIELD-SYMBOL(<fs>)) für kürzeren Code. - Bei generischen Typen (
TYPE any) ist CASTING oft erforderlich. - Field-Symbols können ungültig werden, wenn die Originaldaten gelöscht werden.
- Für Objektreferenzen verwenden Sie stattdessen
Datenreferenzen. - Kombinieren Sie mit
READ TABLEfür effizienten Einzelzugriff.