ABAP FIELD-SYMBOLS and ASSIGN: Dynamic Field Access

Category
ABAP-Statements
Published
Author
Johannes

Field-Symbols are a central concept in ABAP for dynamic access to memory areas. Unlike regular variables that copy data, a field symbol points directly to the memory area of another variable – similar to pointers in other programming languages.

Basic Concept

  • A field symbol is a placeholder that points to a memory area
  • It is “assigned” to a concrete variable with ASSIGN
  • Changes to the field symbol directly change the original variable
  • No data copying = better performance

Syntax

Declare Field Symbol

" With concrete type
FIELD-SYMBOLS: <fs_name> TYPE <type>.
" With generic type
FIELD-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 declaration (from 7.40)
ASSIGN variable TO FIELD-SYMBOL(<fs_inline>).

ASSIGN Variants

" Static assignment
ASSIGN <variable> TO <fs>.
" Dynamic assignment (field name as string)
ASSIGN (lv_fieldname) TO <fs>.
" Component of a structure
ASSIGN COMPONENT <name_or_index> OF STRUCTURE <structure> TO <fs>.
" With type casting
ASSIGN <variable> TO <fs> CASTING TYPE <type>.

System Fields

After ASSIGN:

  • sy-subrc:
    • 0: Assignment successful
    • 4: Assignment failed (variable doesn’t exist or type incompatible)

Examples

1. Basic Usage

DATA: lv_number TYPE i VALUE 100.
FIELD-SYMBOLS: <fs_num> TYPE i.
" Assign field symbol to variable
ASSIGN lv_number TO <fs_num>.
IF sy-subrc = 0.
" Change via field symbol
<fs_num> = 200.
WRITE: / 'Original:', lv_number. " Output: 200
ENDIF.

2. Check Field Symbol

FIELD-SYMBOLS: <fs> TYPE any.
" Check before using!
IF <fs> IS ASSIGNED.
" Field symbol points to valid data
WRITE: / <fs>.
ELSE.
" Field symbol is not assigned
WRITE: / 'Field symbol not assigned!'.
ENDIF.
" Remove assignment
UNASSIGN <fs>.

3. Field Symbols with Internal Tables (LOOP)

The most common use case – direct access to table rows:

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' )
).
" With field symbol: Direct access, no copy
FIELD-SYMBOLS: <fs_mat> TYPE ty_material.
LOOP AT lt_materials ASSIGNING <fs_mat>.
" Change takes effect directly in the table
<fs_mat>-preis = <fs_mat>-preis * '1.1'. " 10% increase
ENDLOOP.
" Table is now changed!

4. Inline Field Symbol Declaration

" Modern (from 7.40): Inline declaration
LOOP AT lt_materials ASSIGNING FIELD-SYMBOL(<fs_inline>).
<fs_inline>-menge = <fs_inline>-menge + 50.
ENDLOOP.
" Also with READ TABLE
READ TABLE lt_materials ASSIGNING FIELD-SYMBOL(<fs_read>)
WITH KEY matnr = 'MAT001'.
IF sy-subrc = 0.
<fs_read>-preis = 99.
ENDIF.

5. Dynamic Access to Structure Components

TYPES: BEGIN OF ty_person,
firstname TYPE string,
lastname TYPE string,
age TYPE i,
END OF ty_person.
DATA: ls_person TYPE ty_person.
FIELD-SYMBOLS: <fs_field> TYPE any.
ls_person = VALUE #( firstname = 'Max' lastname = 'Miller' age = 30 ).
" Access via component index
DO 3 TIMES.
ASSIGN COMPONENT sy-index OF STRUCTURE ls_person TO <fs_field>.
IF sy-subrc = 0.
WRITE: / 'Field', sy-index, ':', <fs_field>.
ENDIF.
ENDDO.
" Access via component name (as string)
DATA: lv_fieldname TYPE string VALUE 'LASTNAME'.
ASSIGN COMPONENT lv_fieldname OF STRUCTURE ls_person TO <fs_field>.
IF sy-subrc = 0.
WRITE: / 'Lastname:', <fs_field>.
ENDIF.

6. Dynamic Variable Access

DATA: lv_var1 TYPE string VALUE 'Value 1',
lv_var2 TYPE string VALUE 'Value 2',
lv_name TYPE string.
FIELD-SYMBOLS: <fs_dynamic> TYPE any.
" Variable name dynamically from string
lv_name = 'LV_VAR1'.
ASSIGN (lv_name) TO <fs_dynamic>.
IF sy-subrc = 0.
WRITE: / 'Dynamic:', <fs_dynamic>. " Value 1
ENDIF.
" Also for global variables with full path
" ASSIGN ('(PROGRAMNAME)GLOBALVAR') TO <fs>.

7. CASTING - Type Conversion

DATA: lv_hex TYPE x LENGTH 4 VALUE '41424344'.
FIELD-SYMBOLS: <fs_char> TYPE c.
" Interpret hex data as characters
ASSIGN lv_hex TO <fs_char> CASTING TYPE c.
WRITE: / <fs_char>. " Output: ABCD
" Casting with structures
DATA: lv_raw TYPE x LENGTH 8.
FIELD-SYMBOLS: <fs_struct> TYPE ty_small_struct.
ASSIGN lv_raw TO <fs_struct> CASTING.

8. Generic Field Symbols

FIELD-SYMBOLS: <fs_any> TYPE any, " Any data type
<fs_data> TYPE data, " Any data (not objects)
<fs_table> TYPE ANY TABLE. " Any internal table
DATA: lt_any TYPE TABLE OF string.
" Generic field symbol for tables
ASSIGN 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 on Table Row with Index

DATA: lt_data TYPE TABLE OF string.
lt_data = VALUE #( ( `One` ) ( `Two` ) ( `Three` ) ).
FIELD-SYMBOLS: <fs_line> TYPE string.
" Direct access to row 2
ASSIGN lt_data[ 2 ] TO <fs_line>.
IF sy-subrc = 0.
<fs_line> = 'CHANGED'.
ENDIF.
" lt_data now contains: One, CHANGED, Three

10. Dynamically Iterate Nested Structures

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.
" Get structure description
lo_struct_descr ?= cl_abap_typedescr=>describe_by_data( ls_person ).
lt_components = lo_struct_descr->components.
" Iterate all components
LOOP 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)

AspectASSIGNING (Field Symbol)INTO (Work Area)
Data copyNoYes
PerformanceFasterSlower
ChangesDirectly in tableRequires MODIFY
MemoryMinimalAdditional memory
" SLOW: Copy and write back
LOOP AT lt_materials INTO ls_material.
ls_material-preis = ls_material-preis * 2.
MODIFY lt_materials FROM ls_material.
ENDLOOP.
" FAST: Direct access
LOOP AT lt_materials ASSIGNING <fs_mat>.
<fs_mat>-preis = <fs_mat>-preis * 2.
ENDLOOP.

Common Errors

1. Using Unassigned Field Symbol

FIELD-SYMBOLS: <fs> TYPE any.
" ERROR: Field symbol not assigned!
" WRITE: / <fs>. " Runtime Error!
" CORRECT: Always check
IF <fs> IS ASSIGNED.
WRITE: / <fs>.
ENDIF.

2. Field Symbol Becomes Invalid After Table Change

LOOP AT lt_data ASSIGNING FIELD-SYMBOL(<fs>).
" CAUTION: DELETE can invalidate the field symbol!
IF <fs>-status = 'X'.
DELETE lt_data. " <fs> now points to nothing!
ENDIF.
ENDLOOP.

3. Type Incompatibility

DATA: lv_string TYPE string VALUE 'Test'.
FIELD-SYMBOLS: <fs_int> TYPE i.
" ERROR: Incompatible types
ASSIGN lv_string TO <fs_int>.
IF sy-subrc <> 0.
WRITE: / 'Assignment failed!'.
ENDIF.

Important Notes / Best Practice

  • Always check sy-subrc after ASSIGN or IS ASSIGNED before use.
  • Use ASSIGNING in LOOP AT instead of INTO for better performance.
  • Field symbols are ideal for dynamic programming.
  • Use the inline declaration (FIELD-SYMBOL(<fs>)) for shorter code.
  • With generic types (TYPE any), CASTING is often required.
  • Field symbols can become invalid when the original data is deleted.
  • For object references, use Data References instead.
  • Combine with READ TABLE for efficient single access.