Internal Tables Part 1: Standard, Sorted and Hashed Tables
Understand internal tables from the ground up: what they are, the line type and the table key, the three table kinds (standard, sorted, hashed), work areas, and filling and reading a table from SFLIGHT in a classic report.
What this complete series covers
Learn Internal Tables in a clear, practical sequence — from the basic idea to real project use, troubleshooting, and interview-ready understanding.
- Who it is for
- Best for SAP consultants, developers, and learners who want a practical understanding of Internal Tables.
- Prerequisites
- Basic SAP navigation and ABAP syntax help. For hands-on practice, use an ABAP system with ADT or the relevant ABAP development tools.
- Final outcome
- By the end, you should be able to explain Internal Tables clearly, follow the main end-to-end flow, apply it in a project scenario, and troubleshoot the most common issues.
- Part 1: Internal Tables Part 1: Standard, Sorted and Hashed Tables
Standard, Sorted, Hashed tables, secondary keys, and how to pick the right one so your reports scale.
- Part 2: Internal Tables Part 2: Choosing the Right Table Type
Choose STANDARD, SORTED or HASHED internal tables from the dominant access pattern, uniqueness and ordering requirements, and use secondary keys when one dataset needs multiple efficient lookup paths.
- Part 3: Internal Tables Part 3: Work Area vs Field Symbol vs Data Reference
Choose work areas, field symbols and data references from ownership and lifetime needs: work areas copy rows, field symbols alias existing memory and references provide explicit ob
- Part 4: Internal Tables Part 4: READ TABLE, sy-subrc and Table Expressions
Choose READ TABLE, lineexists and table expressions according to whether you need existence, row data or exception behavior, and always use a key that matches the internal-table design.
- Part 5: Internal Tables Part 5: SORT, BINARY SEARCH and Secondary Keys
Use BINARY SEARCH only on a correctly sorted compatible key, and prefer SORTED or secondary-key table definitions when the access pattern is repeated enough that the data structure
- Part 6: Internal Tables Part 6: APPEND, INSERT, MODIFY, DELETE and COLLECT
Use internal-table modification statements according to table type and intent, understanding index versus key behavior, in-place field-symbol updates and the special aggregation semantics of COLLECT.
- Part 7: Internal Tables Part 7: Removing Duplicates and Building Unique Datasets
Build unique driver datasets with keyed internal tables or deliberate sort-and-delete logic so downstream SQL and processing do not repeat the same business key unnecessarily.
- Part 8: Internal Tables Part 8: LOOP Patterns — WHERE, Control Levels and Totals
Choose modern ABAP looping and constructor expressions for clarity: use ASSIGNING for in-place row work, WHERE or GROUP BY for focused iteration, and VALUE, FILTER or REDUCE when e
- Part 9: Internal Tables Part 9: Nested LOOP Optimization and Parallel Cursor
Replace expensive nested-loop scans with keyed internal tables, grouped iteration or range-based access; use classic parallel-cursor logic only when it remains clearer than modern
- Part 10: Internal Tables Part 10: Memory Management and Large Internal Tables
Control ABAP memory by reducing data at the database, avoiding duplicate full-table copies, processing large volumes in packages and releasing genuinely large temporary datasets wh
System and release assumptions: Examples follow modern ABAP practices. Exact syntax, available APIs, and tools can vary by SAP release, so release-dependent points are called out where needed.
Explanation
📌 KEY POINTS
✅ An internal table is a temporary, in-memory table in your program — it lives only while the program runs.
✅ It is defined by a line type (structure), a table kind (STANDARD, SORTED, HASHED) and a key.
✅ Classic processing uses a work area: read a row into it, change it, write it back.
⚠️ Never use tables WITH HEADER LINE or OCCURS in new code — they are obsolete and confusing.
━━━━━━━━━━━━━━━━━━━━
▶ WHAT THIS SERIES COVERS
- Part 1 — table kinds and basics (this lesson)
- Part 2 — choosing the right table kind
- Part 3 — work area vs field symbol vs data reference
- Part 4 — READ TABLE and sy-subrc
- Part 5 — SORT, BINARY SEARCH and secondary keys
- Part 6 — APPEND, INSERT, MODIFY, DELETE, COLLECT
- Part 7 — removing duplicates
- Part 8 — LOOP patterns and control levels
- Part 9 — nested loops and parallel cursor
- Part 10 — memory and large tables
━━━━━━━━━━━━━━━━━━━━
▶ 1. WHAT AN INTERNAL TABLE IS
Almost every ABAP program reads data from the database into internal tables, processes it in memory, and outputs or saves the result. Think of it as an array of structures: every row has the same columns (the line type).
━━━━━━━━━━━━━━━━━━━━
▶ 2. THE THREE PARTS OF A DEFINITION
- Line type — usually a dictionary table/structure (SFLIGHT) or a local TYPES structure.
- Table kind — STANDARD, SORTED or HASHED.
- Key — the fields that identify a row (UNIQUE or NON-UNIQUE).
━━━━━━━━━━━━━━━━━━━━
▶ 3. THE THREE TABLE KINDS
- STANDARD TABLE — rows in insertion order, accessed by index or by key with a linear search (slow on large tables unless sorted + BINARY SEARCH). The most common kind in classic code.
- SORTED TABLE — always kept sorted by its key; key access uses a binary search automatically. Key can be UNIQUE or NON-UNIQUE.
- HASHED TABLE — access only by the full unique key via a hash function; constant access time regardless of size; no index access.
━━━━━━━━━━━━━━━━━━━━
▶ 4. CLASSIC DECLARATION WITH A WORK AREA
TYPES: BEGIN OF ty_flight, carrid TYPE s_carr_id, connid TYPE s_conn_id, fldate TYPE s_date, seatsocc TYPE s_seatsocc, END OF ty_flight.
DATA: gt_flights TYPE STANDARD TABLE OF ty_flight,
gs_flight TYPE ty_flight.
The work area gs_flight holds one row at a time.
━━━━━━━━━━━━━━━━━━━━
▶ 5. FILL, READ, LOOP
- Fill from the database: SELECT … INTO TABLE gt_flights.
- Add a row: APPEND gs_flight TO gt_flights.
- Read one row: READ TABLE gt_flights INTO gs_flight WITH KEY connid = '0400'.
- Process all rows: LOOP AT gt_flights INTO gs_flight. … ENDLOOP.
- Count rows: DESCRIBE TABLE gt_flights LINES lv_lines. (💡 Modern: lines( gt_flights ).)
━━━━━━━━━━━━━━━━━━━━
▶ 6. HEADER LINES — WHY NOT
Old code declares DATA itab TYPE … WITH HEADER LINE or OCCURS 0 — the table and a work area with the same name. It is ambiguous (itab vs itab[]) and not allowed in classes. You must read it in legacy code, but never write it.
━━━━━━━━━━━━━━━━━━━━
▶ STEP BY STEP
- Create report ZITAB_BASICS with the code example.
- Run it for airline LH; see the row count and the loop output.
- Change the READ key to a connection that does not exist and check sy-subrc = 4.
💡 Modern syntax (7.40+): SELECT … INTO TABLE @DATA(lt_flights), LOOP AT … INTO DATA(ls_flight), lines( ).
✅ CHECKPOINT: you can declare, fill, read and loop over an internal table with a work area.
Code example
REPORT zitab_basics. * ===== Step 1: line type, table and work area (classic style) =====TYPES: BEGIN OF ty_flight, carrid TYPE s_carr_id, connid TYPE s_conn_id, fldate TYPE s_date, seatsmax TYPE s_seatsmax, seatsocc TYPE s_seatsocc, END OF ty_flight. DATA: gt_flights TYPE STANDARD TABLE OF ty_flight, " standard table gs_flight TYPE ty_flight, " work area gv_lines TYPE i. PARAMETERS p_carr TYPE s_carr_id DEFAULT 'LH'. START-OF-SELECTION.* ===== Step 2: fill the table from the database ===== SELECT carrid connid fldate seatsmax seatsocc FROM sflight INTO TABLE gt_flights WHERE carrid = p_carr. IF sy-subrc <> 0. WRITE: / 'No flights found for', p_carr. STOP. ENDIF. DESCRIBE TABLE gt_flights LINES gv_lines. WRITE: / 'Number of flights:', gv_lines. * ===== Step 3: read one row by key ===== READ TABLE gt_flights INTO gs_flight WITH KEY connid = '0400'. IF sy-subrc = 0. WRITE: / 'First flight of 0400 on', gs_flight-fldate. ELSE. WRITE: / 'Connection 0400 not in table'. ENDIF. * ===== Step 4: add a row manually ===== CLEAR gs_flight. gs_flight-carrid = p_carr. gs_flight-connid = '9999'. gs_flight-fldate = sy-datum. APPEND gs_flight TO gt_flights. * ===== Step 5: process all rows ===== ULINE. LOOP AT gt_flights INTO gs_flight. WRITE: / sy-tabix, gs_flight-carrid, gs_flight-connid, gs_flight-fldate, gs_flight-seatsocc, '/', gs_flight-seatsmax. ENDLOOP. * ===== Other table kinds (declarations) =====DATA: gt_sorted TYPE SORTED TABLE OF ty_flight WITH NON-UNIQUE KEY carrid connid fldate, gt_hashed TYPE HASHED TABLE OF ty_flight WITH UNIQUE KEY carrid connid fldate. * ===== OBSOLETE - only read it in legacy code =====* DATA itab TYPE ty_flight OCCURS 0 WITH HEADER LINE.Real project scenario
A support developer changed a legacy report where an internal table was declared WITH HEADER LINE. He wrote CLEAR itab to empty the table, but that only cleared the header line; the table kept old rows and the next run of the loop produced duplicate records in an output file.
The team fixed it with CLEAR itab[] and, in the next change, replaced the header line with an explicit work area. They added "no header lines in new code" to their review checklist.
Common mistakes
- Declaring new tables WITH HEADER LINE or OCCURS.
- Confusing itab and itab[] in legacy code.
- Not checking sy-subrc after READ TABLE.
- Forgetting CLEAR on the work area before filling a new row.
- Using a standard table for large key lookups without sorting.
Best practices
- Use explicit work areas (or field symbols) and no header lines.
- Base line types on dictionary structures or clear local TYPES.
- Choose the table kind based on access pattern (Part 2).
- Always check sy-subrc after READ.
- Keep tables local to the processing that needs them.
Interview angle
Questions: "What is an internal table?", "Difference between standard, sorted and hashed tables?", "Why avoid header lines?"
Strong answer: an internal table is an in-memory table defined by line type, table kind and key; standard tables keep insertion order with index access and linear key search, sorted tables keep key order with automatic binary search, hashed tables allow only unique-key access with constant time; header lines are obsolete, ambiguous (itab vs itab[]) and not allowed in OO contexts.
Practice this lesson
Quick check
1. Why should header lines (OCCURS 0 WITH HEADER LINE) be avoided?
2. Which statement adds a row to a STANDARD table at the end?
3. If an internal table type is declared simply as "DATA itab TYPE TABLE OF ty_line." without specifying STANDARD, SORTED, or HASHED, which table category is used by default?
Interview questions
1. What are the three types of internal tables in ABAP (Standard, Sorted, Hashed) and how do they differ in terms of key definition and access?
Answer it in your own words first, then compare.
2. What is the difference between STANDARD, SORTED, and HASHED internal tables?
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 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 6: APPEND, INSERT, MODIFY, DELETE and COLLECT
- Internal Tables Part 7: Removing Duplicates and Building Unique Datasets
- Internal Tables Part 8: LOOP Patterns — WHERE, Control Levels and Totals