ABAP MODIFY Statement: Changing Rows in Internal Tables

Category
ABAP-Statements
Published
Author
Johannes

The MODIFY statement is used in ABAP to change existing rows in internal tables. It can update a single row (by index or key) or multiple rows simultaneously (with WHERE condition). If the row doesn’t exist, MODIFY can also insert it depending on the variant.

Syntax

There are several variants of the MODIFY statement:

1. Change Row by Index

MODIFY <internal_table> FROM <work_area> INDEX <index>
[TRANSPORTING <component1> <component2> ...].

2. Change or Insert Row by Table Key

MODIFY TABLE <internal_table> FROM <work_area>
[TRANSPORTING <component1> <component2> ...].

3. Change Multiple Rows with WHERE Condition

MODIFY <internal_table> FROM <work_area>
TRANSPORTING <component1> [<component2> ...]
WHERE <condition>.

4. Change Current Row in LOOP

LOOP AT <internal_table> INTO <work_area>.
" modify <work_area>
MODIFY <internal_table> FROM <work_area>.
ENDLOOP.

Components

  • <internal_table>: The table whose rows should be changed.
  • <work_area>: A structure with the new values. Must be compatible with the table’s row type.
  • INDEX <index>: The position of the row to change (only for standard tables and sorted tables).
  • TABLE: Indicates the variant with key search. The row is found using the primary key.
  • TRANSPORTING <components>: Limits the change to the specified components. Other fields remain unchanged.
  • WHERE <condition>: Changes all rows that meet the condition.

System Fields

After a MODIFY, the following system fields are set:

  • sy-subrc:

    • 0: Row(s) successfully changed (or inserted with MODIFY TABLE).
    • 4: No matching row found (with INDEX or TABLE).
  • sy-tabix: Contains the index of the changed row (for single-row operations on index tables).

Behavior by Variant

MODIFY … INDEX

Changes the row at the specified index position. The entire content of the work area is copied to the row (except with TRANSPORTING).

" Replace row 3 completely
MODIFY lt_data FROM ls_new_data INDEX 3.
" Change only specific fields in row 3
MODIFY lt_data FROM ls_new_data INDEX 3 TRANSPORTING field1 field2.

MODIFY TABLE

Searches for the row using the primary key in the work area:

  • Found: The row is updated.
  • Not found: The row is inserted (like INSERT).
" Search by key and update or insert
MODIFY TABLE lt_customers FROM ls_customer.

MODIFY … WHERE

Changes all rows that meet the WHERE condition. TRANSPORTING is mandatory here.

" Change all rows with status = 'OLD'
MODIFY lt_orders FROM ls_update
TRANSPORTING status
WHERE status = 'OLD'.

MODIFY in LOOP (without INDEX)

Within a LOOP AT ... INTO, MODIFY can be used without INDEX – it then automatically changes the current row.

LOOP AT lt_data INTO ls_data.
ls_data-field = 'New value'.
MODIFY lt_data FROM ls_data.
ENDLOOP.

Better: Use ASSIGNING in the loop to enable direct changes without MODIFY.

Examples

1. Change Row by Index

TYPES: BEGIN OF ty_product,
id TYPE i,
name TYPE string,
price TYPE p DECIMALS 2,
END OF ty_product.
DATA: lt_products TYPE STANDARD TABLE OF ty_product WITH EMPTY KEY,
ls_product TYPE ty_product.
" Fill table
lt_products = VALUE #(
( id = 1 name = 'Laptop' price = '999.00' )
( id = 2 name = 'Mouse' price = '29.99' )
( id = 3 name = 'Keyboard' price = '79.00' )
).
" Replace row 2 completely
ls_product = VALUE #( id = 2 name = 'Gaming Mouse' price = '59.99' ).
MODIFY lt_products FROM ls_product INDEX 2.
IF sy-subrc = 0.
WRITE: / 'Row 2 changed.'.
ENDIF.

2. Change Only Specific Fields (TRANSPORTING)

" Change only the price in row 1
ls_product-price = '899.00'.
MODIFY lt_products FROM ls_product INDEX 1 TRANSPORTING price.
" Name and ID remain unchanged
" See also: /en/read-table-statement/
READ TABLE lt_products INTO ls_product INDEX 1.
WRITE: / 'Product:', ls_product-name, 'Price:', ls_product-price.
" Output: Laptop 899.00

3. MODIFY TABLE (Key-Based)

TYPES: BEGIN OF ty_customer,
id TYPE i,
name TYPE string,
city TYPE string,
END OF ty_customer.
DATA: lt_customers TYPE HASHED TABLE OF ty_customer WITH UNIQUE KEY id,
ls_customer TYPE ty_customer.
" Fill table
lt_customers = VALUE #(
( id = 1 name = 'Miller GmbH' city = 'Berlin' )
( id = 2 name = 'Schmidt AG' city = 'Munich' )
).
" Change existing customer (ID 1 exists)
ls_customer = VALUE #( id = 1 name = 'Miller & Co. GmbH' city = 'Berlin' ).
MODIFY TABLE lt_customers FROM ls_customer.
IF sy-subrc = 0.
WRITE: / 'Customer 1 changed.'.
ENDIF.
" Insert new customer (ID 3 doesn't exist)
ls_customer = VALUE #( id = 3 name = 'Weber KG' city = 'Hamburg' ).
MODIFY TABLE lt_customers FROM ls_customer.
WRITE: / 'Number of customers:', lines( lt_customers ). " Output: 3

4. Change Multiple Rows with WHERE

TYPES: BEGIN OF ty_order,
order_id TYPE i,
status TYPE string,
amount TYPE p DECIMALS 2,
END OF ty_order.
DATA: lt_orders TYPE STANDARD TABLE OF ty_order WITH EMPTY KEY,
ls_update TYPE ty_order.
lt_orders = VALUE #(
( order_id = 1 status = 'NEW' amount = '100.00' )
( order_id = 2 status = 'NEW' amount = '250.00' )
( order_id = 3 status = 'OPEN' amount = '180.00' )
( order_id = 4 status = 'NEW' amount = '320.00' )
).
" Set all orders with status 'NEW' to 'IN_PROGRESS'
ls_update-status = 'IN_PROGRESS'.
MODIFY lt_orders FROM ls_update
TRANSPORTING status
WHERE status = 'NEW'.
" Result: 3 rows changed (order_id 1, 2, 4)
LOOP AT lt_orders INTO DATA(ls_order).
WRITE: / ls_order-order_id, ls_order-status.
ENDLOOP.

5. MODIFY in LOOP with INTO

DATA: ls_prod TYPE ty_product.
" Increase all prices by 10%
LOOP AT lt_products INTO ls_prod.
ls_prod-price = ls_prod-price * '1.1'.
MODIFY lt_products FROM ls_prod.
ENDLOOP.

6. Better Alternative: LOOP with ASSIGNING

FIELD-SYMBOLS: <fs_prod> TYPE ty_product.
" Increase all prices by 10% – without MODIFY
LOOP AT lt_products ASSIGNING <fs_prod>.
<fs_prod>-price = <fs_prod>-price * '1.1'.
ENDLOOP.
" Changes are effective immediately, no MODIFY needed!

7. MODIFY TABLE with TRANSPORTING

" Change only the city of a customer (key search)
ls_customer-id = 2. " Key for search
ls_customer-city = 'Cologne'. " New value
MODIFY TABLE lt_customers FROM ls_customer TRANSPORTING city.
IF sy-subrc = 0.
WRITE: / 'City of customer 2 changed.'.
ENDIF.

Behavior by Table Type

Table TypeINDEXTABLEWHERE
STANDARD TABLEYesYes (linear search)Yes
SORTED TABLEYesYes (binary search)Yes
HASHED TABLENoYes (hash lookup)Yes

Important for sorted tables: If you change key fields, this can violate the sort order and cause a runtime error!

" Dangerous with SORTED TABLE with KEY id:
ls_customer-id = 999. " Changing key field
MODIFY TABLE lt_sorted_customers FROM ls_customer. " Can cause dump!

Comparison with Other Statements

MODIFY vs. ASSIGNING in LOOP

AspectMODIFY in LOOPASSIGNING
SyntaxMore codeMore compact
PerformanceSlower (copying)Faster (direct access)
UsageLegacy codeRecommended
" With MODIFY (outdated)
LOOP AT lt_data INTO ls_data.
ls_data-field = 'X'.
MODIFY lt_data FROM ls_data.
ENDLOOP.
" With ASSIGNING (recommended)
LOOP AT lt_data ASSIGNING FIELD-SYMBOL(<fs>).
<fs>-field = 'X'.
ENDLOOP.

MODIFY vs. INSERT and APPEND

  • MODIFY TABLE: Changes existing row OR inserts new one (Upsert).
  • INSERT: Only inserts, fails if key exists.
  • APPEND: Always appends at the end of a standard table.

MODIFY vs. UPDATE (Database)

  • MODIFY: For internal tables (in memory).
  • UPDATE: For database tables (persistent data).

For finding a row before modifying, see READ TABLE.

Performance Tips

  1. ASSIGNING instead of MODIFY in LOOP: Avoid LOOP ... INTO followed by MODIFY. Use ASSIGNING instead for direct write access.

  2. TRANSPORTING with large structures: When only a few fields need to be changed, limit the data to be copied with TRANSPORTING.

  3. WHERE for mass changes: MODIFY ... WHERE is more efficient than a manual loop with individual changes.

  4. Don’t change key fields: With sorted and hash tables, key fields should not be changed. Instead: delete the row and insert it again (see APPEND or INSERT).

Best Practices

  • Check sy-subrc after MODIFY with INDEX or TABLE to ensure the row was found.
  • Prefer ASSIGNING in LOOP AT for direct changes – it’s more performant and elegant than MODIFY.
  • Use TRANSPORTING when only specific fields should be changed.
  • MODIFY TABLE is an “Upsert” – it inserts if the row doesn’t exist.
  • Never directly change key fields in sorted or hash tables.
  • With MODIFY ... WHERE, TRANSPORTING is mandatory.
  • This MODIFY statement is for internal tables. For database tables, see INSERT, UPDATE, DELETE.