Internal Tables Part 6: APPEND, INSERT, MODIFY, DELETE and COLLECT
Change internal tables correctly: APPEND vs INSERT for each table kind, MODIFY by index or with WHERE, DELETE single rows, ranges and WHERE conditions, COLLECT for totals, and APPEND LINES for whole tables.
Explanation
📌 KEY POINTS
✅ APPEND adds at the end (standard tables); INSERT … INTO TABLE works for all kinds and respects keys.
✅ MODIFY … TRANSPORTING … WHERE changes many rows in one statement.
✅ DELETE … WHERE removes many rows at once — much faster than deleting in a loop.
💡 COLLECT sums numeric fields for rows with the same non-numeric key — perfect for totals.
━━━━━━━━━━━━━━━━━━━━
▶ WHERE WE ARE
Parts 1–5 read tables. Now we change them.
━━━━━━━━━━━━━━━━━━━━
▶ 1. ADDING ROWS
- APPEND gs_flight TO gt_flight. — standard tables (and sorted if the order stays correct).
- INSERT gs_flight INTO TABLE gt_flight. — generic: standard → end, sorted → correct position, hashed → by key. With unique keys, a duplicate is not inserted (sy-subrc = 4).
- INSERT gs_flight INTO gt_flight INDEX 1. — at a position (standard/sorted).
- APPEND LINES OF gt_other TO gt_flight. — whole table.
- Modern: gt_flight = VALUE #( BASE gt_flight ( … ) ).
━━━━━━━━━━━━━━━━━━━━
▶ 2. CHANGING ROWS
- In a loop with field symbols (Part 3) — preferred.
- MODIFY gt_flight FROM gs_flight INDEX lv_tabix. — one row by index.
- MODIFY TABLE gt_flight FROM gs_flight. — by table key (sorted/hashed).
- MODIFY gt_flight FROM gs_upd TRANSPORTING price WHERE carrid = 'LH'. — many rows, only the listed fields.
━━━━━━━━━━━━━━━━━━━━
▶ 3. DELETING ROWS
- DELETE gt_flight INDEX 3.
- DELETE TABLE gt_flight FROM gs_flight. — by table key.
- DELETE gt_flight WHERE seatsocc >= seatsmax. — all matching rows, one statement.
- DELETE ADJACENT DUPLICATES FROM gt_flight COMPARING carrid connid. — after SORT (Part 7).
⚠️ WATCH OUT: deleting rows inside LOOP AT of the same table shifts indexes — prefer DELETE WHERE after the loop.
━━━━━━━━━━━━━━━━━━━━
▶ 4. COLLECT — TOTALS
COLLECT gs_total INTO gt_total.
If a row with the same values in all non-numeric fields exists, numeric fields are added; otherwise the row is inserted. Use it with sorted or hashed tables (efficient) to build totals per airline, per month, etc.
Modern alternatives: LOOP AT … GROUP BY or REDUCE (Part 8), or aggregate directly in SQL (Open SQL topic).
━━━━━━━━━━━━━━━━━━━━
▶ 5. CLEAR, REFRESH, FREE
- CLEAR gt_flight / REFRESH gt_flight — empty the table (memory kept for reuse).
- FREE gt_flight — empty and release memory (Part 10).
━━━━━━━━━━━━━━━━━━━━
▶ STEP BY STEP
Run the code example: insert into a sorted table, mass-update with MODIFY WHERE, delete full flights with DELETE WHERE, and build seat totals per airline with COLLECT.
✅ CHECKPOINT: you change tables with the right statement for each table kind — without loops where one statement suffices.
Code example
REPORT zitab_part6. TYPES: BEGIN OF ty_flight, carrid TYPE s_carr_id, connid TYPE s_conn_id, fldate TYPE s_date, price TYPE s_price, seatsmax TYPE s_seatsmax, seatsocc TYPE s_seatsocc, END OF ty_flight, BEGIN OF ty_total, " non-numeric key + numeric fields carrid TYPE s_carr_id, seatsmax TYPE i, seatsocc TYPE i, END OF ty_total. DATA: gt_flight TYPE SORTED TABLE OF ty_flight WITH UNIQUE KEY carrid connid fldate, gs_flight TYPE ty_flight, gt_std TYPE STANDARD TABLE OF ty_flight, gt_total TYPE HASHED TABLE OF ty_total WITH UNIQUE KEY carrid, gs_total TYPE ty_total, gs_upd TYPE ty_flight. START-OF-SELECTION. SELECT carrid connid fldate price seatsmax seatsocc FROM sflight INTO TABLE gt_std UP TO 50 ROWS. * ===== INSERT INTO TABLE: works for every table kind, respects the key ===== LOOP AT gt_std INTO gs_flight. INSERT gs_flight INTO TABLE gt_flight. IF sy-subrc <> 0. WRITE: / 'duplicate key skipped:', gs_flight-carrid, gs_flight-connid. ENDIF. ENDLOOP. * ===== MODIFY ... TRANSPORTING ... WHERE: mass update, one statement ===== gs_upd-price = 999. MODIFY gt_std FROM gs_upd TRANSPORTING price WHERE carrid = 'LH'. * ===== DELETE ... WHERE: remove full flights, no loop needed ===== DELETE gt_std WHERE seatsocc >= seatsmax. * ===== COLLECT: totals per airline ===== LOOP AT gt_flight INTO gs_flight. CLEAR gs_total. gs_total-carrid = gs_flight-carrid. gs_total-seatsmax = gs_flight-seatsmax. gs_total-seatsocc = gs_flight-seatsocc. COLLECT gs_total INTO gt_total. " adds numeric fields per carrid ENDLOOP. LOOP AT gt_total INTO gs_total. WRITE: / gs_total-carrid, 'seats', gs_total-seatsocc, 'of', gs_total-seatsmax. ENDLOOP. * ===== Whole table ===== APPEND LINES OF gt_std TO gt_std. " duplicates the content (demo) * ===== WRONG: deleting in the loop of the same table =====* LOOP AT gt_std INTO gs_flight.* IF gs_flight-price > 1000. DELETE gt_std. ENDIF. " index shifts, hard to follow* ENDLOOP.* RIGHT: DELETE gt_std WHERE price > 1000.Real project scenario
A data cleansing program deleted invalid records one by one inside a LOOP over a table of 3 million rows and used the loop index for later MODIFY statements. Runtime was over two hours, and after each deletion the stored indexes pointed to the wrong rows, corrupting some records.
Replacing the loop with DELETE … WHERE and MODIFY … TRANSPORTING … WHERE statements reduced the runtime to a few minutes and removed the index errors entirely.
Common mistakes
- APPEND to sorted tables out of order (runtime error).
- Deleting rows inside a loop over the same table.
- Row-by-row MODIFY where MODIFY … WHERE suffices.
- COLLECT with non-numeric fields that should be summed, or on large standard tables.
- Ignoring sy-subrc after INSERT into unique-key tables.
Best practices
- INSERT … INTO TABLE for generic, key-safe inserts.
- Mass statements (MODIFY/DELETE … WHERE) instead of loops.
- COLLECT only with sorted/hashed tables, or aggregate in SQL.
- APPEND LINES OF for whole tables.
- Use FREE when large tables are no longer needed.
Interview angle
Questions: "APPEND vs INSERT?", "How does COLLECT work?", "How do you delete many rows efficiently?"
Strong answer: APPEND adds at the end of standard tables; INSERT INTO TABLE works for all kinds respecting keys (duplicates rejected with sy-subrc 4); COLLECT adds numeric fields of rows with identical non-numeric fields, best with sorted/hashed tables; DELETE … WHERE and MODIFY … TRANSPORTING … WHERE process many rows in one statement instead of loops.
Practice this lesson
Quick check
1. Which statement removes all full flights from an internal table in one step?
2. COLLECT aggregates numeric fields based on:
3. Which statement adds a row to a STANDARD table at the end?
Interview questions
1. A program uses APPEND to add rows into what was declared as a SORTED table, and it throws a runtime error intermittently only for certain input data. What's happening and how would you fix it?
Answer it in your own words first, then compare.
2. What is the difference between APPEND, INSERT, and COLLECT when adding rows to an internal table?
Answer it in your own words first, then compare.
Reference-verified: the steps are checked against official SAP documentation and tutorials, and object and field names in the sample code are checked for consistency. The code has not been compiled or run on an SAP system by ERPClimb. Syntax marked release-dependent varies by SAP release, so check it in your own system.
More lessons in this topic
- Internal Tables Part 1: Standard, Sorted and Hashed Tables
- Internal Tables Part 10: Memory Management and Large Internal Tables
- Internal Tables Part 2: Choosing the Right Table Type
- Internal Tables Part 3: Work Area vs Field Symbol vs Data Reference
- Internal Tables Part 4: READ TABLE, sy-subrc and Table Expressions
- Internal Tables Part 5: SORT, BINARY SEARCH and Secondary Keys
- Internal Tables Part 7: Removing Duplicates and Building Unique Datasets
- Internal Tables Part 8: LOOP Patterns — WHERE, Control Levels and Totals