Skip to main content
  1. Documentation/

ITAB Instructions in ABAP

··38 mins· loading · loading · · ·
SAP ERP Back-End
Adrien D'acunto
Author
Adrien D’acunto
Table of Contents

ITAB Instructions in ABAP
#

Is initial
#

Objectives
#

  • Check if an internal table is empty or not
  • Understand the use of brackets []
  • Use IS INITIAL or IS NOT INITIAL to test the content of an internal table
  • Know that IS INITIAL also works with simple variables

Definition
#

IF itab[] IS INITIAL.
  " The table is empty
ENDIF.

IF [NOT] itab[] IS [NOT] INITIAL.
  " The table contains at least one line
ENDIF.

The expression IS INITIAL checks if data is empty or uninitialized.
For internal tables, the brackets [] mean we evaluate the complete content of the table.

  • itab[] IS INITIAL → the table contains no lines
  • itab[] IS NOT INITIAL → the table contains at least one line

Analogy
#

Imagine a box:

  • If the box contains no object, it is initial (empty).
  • If it contains at least one object, it is not initial.

Similarly:

  • itab[] IS INITIAL → the box is empty.
  • NOT itab[] IS INITIAL → the box contains something.

Complete example
#

TYPES: BEGIN OF ty_citizen,
         country TYPE char3,
         name    TYPE char20,
         age     TYPE numc2,
       END OF ty_citizen.

DATA: lt_citizen TYPE STANDARD TABLE OF ty_citizen,
      ls_citizen TYPE ty_citizen.

" --- Check before adding ---
IF lt_citizen[] IS INITIAL.
  WRITE: / 'The table is empty at the start.'.
ENDIF.

" --- Adding a record ---
ls_citizen-country = 'FR'.
ls_citizen-name    = 'Thierry'.
ls_citizen-age     = '24'.
APPEND ls_citizen TO lt_citizen.

" --- Check after adding ---
IF NOT lt_citizen[] IS INITIAL.
  WRITE: / 'The table contains at least one record.'.
ENDIF.
  • Before the APPEND, the table is empty → IS INITIAL returns TRUE.
  • After the APPEND, it contains one line → IS NOT INITIAL returns TRUE.

Warning
#

  • If you forget the brackets [], you test the table reference, not its content.
  • A table can be “non-initial” even if it has no more lines if it was initialized elsewhere.
    → Always use itab[] IS INITIAL with brackets.

Best practices
#

Best practice Explanation
Always test before processing Avoids loop errors on empty table
Use IS INITIAL with [] Clearly specifies that the test concerns content
Use ... IS NOT INITIAL Checks that there is at least one line in the table
Apply also to variables Allows controlling data initialization
Prefer IS INITIAL to LINES( itab ) = 0 More readable and faster

Summary examples
#

1 – Empty table
#

DATA lt_data TYPE TABLE OF string.

IF lt_data[] IS INITIAL.
  WRITE: / 'The table is empty.'.
ENDIF.

2 – Non-empty table
#

APPEND 'Hello' TO lt_data.

IF NOT lt_data[] IS INITIAL.
  WRITE: / 'The table contains at least one value.'.
ENDIF.

Summary
#

IS INITIAL allows checking if an internal table or variable is empty.

  • itab[] IS INITIAL → empty table
  • itab[] IS NOT INITIAL → non-empty table
  • Also works for simple variables and structures

Good practice: always check before processing or looping on a table.

Test if a box contains something before trying to take an object from inside.

Clear table
#

Objectives
#

  • Delete all lines of an internal table with CLEAR
  • Understand the syntax with brackets []
  • Know that CLEAR can also be used on simple variables
  • Differentiate CLEAR itab[] and REFRESH itab
  • Check the content of a table before and after clearing

Definition
#

CLEAR: itab[],
       var1.

The instruction CLEAR allows deleting all data from an internal table or resetting variables to zero.

Imagine a whiteboard filled with information.

  • CLEAR itab[] = completely erase the board (all lines).
  • CLEAR var1 = erase the content of a single cell.

The brackets [] are essential: without them, only the structure is erased, not its content.

Examples
#

1 – Clear on internal table
#

TYPES: BEGIN OF ty_citizen,
         country TYPE char3,
         name    TYPE char20,
         age     TYPE numc2,
       END OF ty_citizen.

DATA: lt_citizen TYPE STANDARD TABLE OF ty_citizen,
      ls_citizen TYPE ty_citizen,
      gv_count   TYPE i.

" TABLE FILLING
ls_citizen-country = 'FR'.
ls_citizen-name    = 'Thierry'.
ls_citizen-age     = '24'.
APPEND ls_citizen TO lt_citizen.

ls_citizen-country = 'ES'.
ls_citizen-name    = 'Luis'.
ls_citizen-age     = '32'.
APPEND ls_citizen TO lt_citizen.

gv_count = lines( lt_citizen ). " Number of lines before CLEAR

WRITE:/ 'Lines before deletion:', gv_count.

CLEAR lt_citizen[]. " Deletes all lines from the table

gv_count = lines( lt_citizen ). " Recalculate number of lines
WRITE:/ 'Lines after CLEAR:', gv_count.
  • Before CLEAR, the table contains 2 lines.
  • After CLEAR, the table is completely empty.

The CLEAR lt_citizen (without []) does not erase the lines, it only resets the variable to initial status (empty structure).

2 – Clear on simple variable
#

DATA: gv_total TYPE i VALUE 125.

WRITE:/ 'Before CLEAR:', gv_total.

CLEAR gv_total.

WRITE:/ 'After CLEAR:', gv_total.

The CLEAR on a simple variable resets its value to zero (or initial).
For example:

  • Numeric → 0
  • Character → empty
  • Boolean → ’ ’ (false)

3 – Clear on multiple objects at once
#

DATA: gv_counter TYPE i VALUE 10,
      gv_name    TYPE string VALUE 'Thierry',
      lt_data    TYPE STANDARD TABLE OF ty_citizen.

CLEAR: gv_counter, gv_name, lt_data[].

It is possible to erase multiple elements in a single instruction.
Useful to reset an environment to zero before restarting a process.

4 – Difference between clear and refresh
#

DATA: lt_table TYPE STANDARD TABLE OF ty_citizen.

CLEAR lt_table[].  " Erases the table content
REFRESH lt_table.  " Also erases content (identical behavior since ABAP 7.40)

The CLEAR itab[] is preferred in modern code.
The REFRESH is kept for compatibility with old programs.

5 – Clear on complete structure
#

DATA: ls_person TYPE ty_citizen.

ls_person-country = 'FR'.
ls_person-name    = 'Thierry'.
ls_person-age     = '24'.

WRITE:/ 'Before CLEAR:', ls_person-country, ls_person-name, ls_person-age.

CLEAR ls_person.

WRITE:/ 'After CLEAR:', ls_person-country, ls_person-name, ls_person-age.

The CLEAR on a structure resets each field to its initial value (empty or zero).

6 – Dynamic clear with field-symbol
#

FIELD-SYMBOLS: <lfs_tab> TYPE STANDARD TABLE.

ASSIGN lt_citizen TO <lfs_tab>.

IF <lfs_tab> IS ASSIGNED.
  CLEAR <lfs_tab>[].
ENDIF.

Very useful for writing dynamic programs manipulating multiple internal tables without naming them directly.

Best practices
#

Best practice Explanation
Always check the number of lines LINES( itab ) before/after CLEAR confirms deletion
Use CLEAR with [] Explicitly indicates that the entire table is erased
CLEAR can combine multiple variables Reduces code and keeps logic clear
Prefer CLEAR to REFRESH in code More modern syntax, same effect
Don’t forget brackets [] Without brackets, only the variable is reset to zero, not the content
Avoid CLEAR on untested references Always check IS ASSIGNED before CLEAR on FIELD-SYMBOLS

Summary
#

CLEAR is a simple but powerful instruction

  • CLEAR itab[]: erases all lines of an internal table
  • CLEAR var: resets a variable to its initial value
  • CLEAR structure: reinitializes all fields of the structure
  • CLEAR can be combined on multiple objects
  • CLEAR with [] is the modern equivalent of REFRESH

[!TIP] It’s like pressing “Reset” – we reset everything to zero before starting cleanly again.

Sort
#

Objectives
#

  • Understand the functioning of the SORT instruction for internal tables
  • Know how to sort according to primary key or specific fields
  • Identify the options ASCENDING, DESCENDING, AS TEXT and STABLE
  • Know when to sort before certain operations like DELETE ADJACENT DUPLICATES

Definition
#

SORT itab [ASCENDING|DESCENDING] [AS TEXT] [STABLE]
            BY c1 [ASCENDING|DESCENDING] [AS TEXT]
              ...
                cn [ASCENDING|DESCENDING] [AS TEXT].

The instruction SORT organizes an internal table (itab) of type STANDARD or HASHED according to:

  • its primary key if defined
  • or a list of fields c1 to cn

[!NOTE]

  • ASCENDING / DESCENDING: ascending or descending sort
  • AS TEXT: sort character strings according to local language defined by SET LOCALE LANGUAGE
  • STABLE: maintains relative order for equal values

Imagine a file folder:

  • You can sort by identifier, name or several combined criteria (e.g. name then age)
  • The STABLE option guarantees that files with the same criterion remain in the same relative order
  • SORTED tables cannot be sorted with SORT, because their order is fixed
  • Sorting is mandatory before certain operations like DELETE ADJACENT DUPLICATES for STANDARD TABLE

Examples
#

Simple sort
#

TYPES: BEGIN OF ty_citizen,
         country TYPE char3,
         name    TYPE char20,
         age     TYPE numc2,
       END OF ty_citizen.

DATA: lt_citizen TYPE STANDARD TABLE OF ty_citizen,
      ls_citizen TYPE ty_citizen.

" Adding data
ls_citizen-country = 'FR'.
ls_citizen-name    = 'Thierry'.
ls_citizen-age     = '24'.
APPEND ls_citizen TO lt_citizen.

ls_citizen-country = 'ES'.
ls_citizen-name    = 'Luis'.
ls_citizen-age     = '32'.
APPEND ls_citizen TO lt_citizen.

ls_citizen-country = 'BR'.
ls_citizen-name    = 'Renata'.
ls_citizen-age     = '27'.
APPEND ls_citizen TO lt_citizen.

ls_citizen-country = 'FR'.
ls_citizen-name    = 'Floriane'.
ls_citizen-age     = '32'.
APPEND ls_citizen TO lt_citizen.

Descending sort on entire table
#

SORT lt_citizen DESCENDING.

Sort by specific fields
#

SORT lt_citizen BY country ASCENDING age DESCENDING.
  • If no BY is specified and there is no primary key, the sort can be unstable and random
  • STABLE guarantees identical result during multiple sorts
  • Mandatory before DELETE ADJACENT DUPLICATES for STANDARD TABLE

Best practices
#

Best practice Explanation
Always specify fields for BY Avoids random sort on STANDARD TABLE
Use ASCENDING or DESCENDING Controls sort direction
Use AS TEXT for local strings Respects linguistic order
STABLE for repetitive sorts Maintains relative order of equal values
Sort before DELETE ADJACENT DUPLICATES Ensures correct duplicate removal

Summary
#

SORT organizes lines of an internal table according to a primary key or specific fields.

[!NOTE] The ASCENDING, DESCENDING, AS TEXT, STABLE

[!TIP] Sort a folder according to one or more criteria while keeping the relative order of duplicates if necessary

Insert into itab
#

Objectives
#

  • Understand the functioning of the INSERT instruction for internal tables
  • Know how to insert a structure, an empty line or lines from another table
  • Master insertion at a precise index in the target table
  • Simplify code by avoiding manual loops to add multiple lines

Definition
#

The instruction INSERT allows adding lines to an internal table (itab).
It can come from different sources:

  • A structure (ls)
  • An empty line (INITIAL LINE)
  • Another internal table (LINES OF jtab) with possibility to specify an interval (FROM idx1 TO idx2)

Imagine a file folder:

  • Add a complete file (structure)
  • Slip in a blank page (INITIAL LINE)
  • Copy certain pages from another folder (LINES OF) at a precise position
  • The INDEX option allows controlling the final order of lines.
  • If no INDEX is specified, the line is added at the end of the table.
  • Very practical to insert multiple lines at once, without a loop.

Declaration and example
#

TYPES: BEGIN OF ty_citizen,
         country TYPE char3,
         name    TYPE char20,
         age     TYPE numc2,
       END OF ty_citizen.

DATA: lt_citizen1 TYPE TABLE OF ty_citizen,
      lt_citizen2 TYPE TABLE OF ty_citizen,
      ls_citizen  TYPE ty_citizen.

1️⃣ Insertion of a structure into the table
#

ls_citizen-country = 'FR'.
ls_citizen-name    = 'Thierry'.
ls_citizen-age     = '24'.
INSERT ls_citizen INTO TABLE lt_citizen1.

2️⃣ Creation of multiple records in another table
#

ls_citizen-country = 'ES'.
ls_citizen-name    = 'Luis'.
ls_citizen-age     = '32'.
INSERT ls_citizen INTO TABLE lt_citizen2.

ls_citizen-country = 'BR'.
ls_citizen-name    = 'Renata'.
ls_citizen-age     = '27'.
INSERT ls_citizen INTO TABLE lt_citizen2.

ls_citizen-country = 'FR'.
ls_citizen-name    = 'Floriane'.
ls_citizen-age     = '32'.
INSERT ls_citizen INTO TABLE lt_citizen2.

3️⃣ Insertion of an empty line at a precise index
#

INSERT INITIAL LINE INTO lt_citizen1 INDEX 1.

4️⃣ Insertion of multiple lines from another table
#

INSERT LINES OF lt_citizen2 FROM 2 TO 3 INTO lt_citizen1 INDEX 1.
  • A structure serves as a line model for the internal table.
  • You can insert a single line, an empty line or multiple lines from another table.
  • The order of lines is controlled by INDEX.

Final result of lt_citizen1
#

COUNTRY NAME AGE
BR Renata 27
FR Floriane 32
FR Thierry 24

The final order reflects the position of insertions and use of INDEX.

Best practices
#

Best practice Explanation
Clearly define structures Facilitates reading and maintenance
Specify index if necessary Controls final order of records
Use LINES OF to copy ranges Avoids manual loops and simplifies code
Check presence of target table Prevent insertion errors

Exercises
#

1 – Create and insert records
#

Declare an internal table lt_employees with a structure ty_employee

  • id (CHAR5)
  • name (CHAR20)
  • department (CHAR10)

Insert two employees and display the data.

SOLUTION
TYPES: BEGIN OF ty_employee,
         id         TYPE char5,
         name       TYPE char20,
         department TYPE char10,
       END OF ty_employee.

DATA: lt_employees TYPE TABLE OF ty_employee,
      ls_employee  TYPE ty_employee.

ls_employee-id         = 'E001'.
ls_employee-name       = 'Dupont'.
ls_employee-department = 'HR'.
INSERT ls_employee INTO TABLE lt_employees.

ls_employee-id         = 'E002'.
ls_employee-name       = 'Martin'.
ls_employee-department = 'IT'.
INSERT ls_employee INTO TABLE lt_employees.

LOOP AT lt_employees INTO ls_employee.
  WRITE: / ls_employee-id, ls_employee-name, ls_employee-department.
ENDLOOP.

2 – Insert an empty line
#

Add an empty line at index 2 and display the table.

SOLUTION
INSERT INITIAL LINE INTO lt_employees INDEX 2.

LOOP AT lt_employees INTO ls_employee.
  WRITE: / ls_employee-id, ls_employee-name, ls_employee-department.
ENDLOOP.

3 – Copy lines from another table
#

Create lt_new_employees with two lines and insert them into lt_employees at index 1.

SOLUTION
DATA: lt_new_employees TYPE TABLE OF ty_employee.

ls_employee-id         = 'E003'.
ls_employee-name       = 'Renata'.
ls_employee-department = 'FIN'.
INSERT ls_employee INTO TABLE lt_new_employees.

ls_employee-id         = 'E004'.
ls_employee-name       = 'Luis'.
ls_employee-department = 'LOG'.
INSERT ls_employee INTO TABLE lt_new_employees.

INSERT LINES OF lt_new_employees INTO lt_employees INDEX 1.

LOOP AT lt_employees INTO ls_employee.
  WRITE: / ls_employee-id, ls_employee-name, ls_employee-department.
ENDLOOP.

Summary
#

  • INSERT → add a line, an empty line or multiple lines from another table.
  • INDEX → controls the position of the line(s).

[!TIP] Slip files into a folder at the desired location, by copying or creating new files.

[!IMPORTANT] Clearly define the structure, check the target table and avoid loops to insert multiple lines.

Append to itab
#

Objectives
#

  • Understand the functioning of the APPEND instruction for internal tables
  • Know how to add a structure, an empty line, or lines from another table at the end of a table
  • Identify limitations according to internal table type
  • Compare APPEND and INSERT according to table type

Definition
#

APPEND { ls | {INITIAL LINE} | {LINES OF jtab [FROM idx1] [TO idx2]} }
       TO itab.

The instruction APPEND adds data always at the end of an internal table (itab).
It works like INSERT, but the destination parameter is always TO itab.

Imagine a folder:

  • You always paste new files at the end.
  • You can:
    • Add a complete file (STRUCTURE)
    • Slip in a blank page (INITIAL LINE)
    • Copy pages from another internal table (LINES OF itab)
  • APPEND is simple and fast for STANDARD and RANGE TABLE.
  • For HASHED or SORTED TABLE, you must use INSERT INTO TABLE to respect constraints.

Standard table example
#

ls_citizen-country = 'ES'.
ls_citizen-name    = 'Luiza'.
ls_citizen-age     = '31'.
APPEND ls_citizen TO lt_citizen1.

ls_citizen-country = 'BR'.
ls_citizen-name    = 'Felipe'.
ls_citizen-age     = '25'.
APPEND ls_citizen TO lt_citizen1.

Final content of lt_citizen1:

COUNTRY NAME AGE
BR Renata 27
FR Floriane 32
FR Thierry 24
ES Luiza 31
BR Felipe 25

Limitations for sorted and hashed table
#

  • APPEND works only for STANDARD and RANGE TABLE.
  • For HASHED or SORTED TABLE, you must use INSERT INTO TABLE.
  • On a SORTED TABLE, adding at the end can violate the order defined by the key → DUMP.

Sorted table example – Dump
#

TYPES: BEGIN OF ty_country,
         land TYPE char3,
       END OF ty_country.

DATA: lt_country TYPE SORTED TABLE OF ty_country WITH NON-UNIQUE KEY land,
      ls_country TYPE ty_country.

ls_country-land = 'ES'.
APPEND ls_country TO lt_country.

ls_country-land = 'BR'.
APPEND ls_country TO lt_country.  " DUMP: order not respected

Sorted table example – No dump
#

ls_country-land = 'BR'.
APPEND ls_country TO lt_country.

ls_country-land = 'ES'.
APPEND ls_country TO lt_country.  " Order respected, no DUMP
  • APPEND does not control order on SORTED TABLE.
  • Correct usage depends on key and defined order.
  • HASHED TABLE can never use APPEND because there is no sequential order.

Best practices
#

Best practice Explanation
Check table type before APPEND Avoids DUMP on SORTED or HASHED TABLE
Use APPEND only for STANDARD/RANGE Guarantees insertion at end without key violation
For SORTED/HASHED TABLE, prefer INSERT Maintains order or key uniqueness
Check key order before insertion Prevent errors and DUMP

Exercises
#

1 – Add employees to a standard table
#

Declare lt_employees with structure ty_employee:

  • id (CHAR5)
  • name (CHAR20)
  • department (CHAR10)

Add two employees with APPEND and display the table.

SOLUTION
DATA: lt_employees TYPE TABLE OF ty_employee,
      ls_employee  TYPE ty_employee.

ls_employee-id         = 'E001'.
ls_employee-name       = 'Dupont'.
ls_employee-department = 'HR'.
APPEND ls_employee TO lt_employees.

ls_employee-id         = 'E002'.
ls_employee-name       = 'Martin'.
ls_employee-department = 'IT'.
APPEND ls_employee TO lt_employees.

LOOP AT lt_employees INTO ls_employee.
  WRITE: / ls_employee-id, ls_employee-name, ls_employee-department.
ENDLOOP.

2 – Add an empty line
#

Add an empty line at the end of lt_employees and display the table.

SOLUTION
APPEND INITIAL LINE TO lt_employees.

LOOP AT lt_employees INTO ls_employee.
  WRITE: / ls_employee-id, ls_employee-name, ls_employee-department.
ENDLOOP.

3 – Copy lines from another table
#

Copy all lines from lt_new_employees to the end of lt_employees.

SOLUTION
INSERT LINES OF lt_new_employees INTO TABLE lt_employees.  " or APPEND if STANDARD

Summary
#

  • APPEND → always adds at the end of an internal table.
  • Compatible with STANDARD and RANGE, forbidden on SORTED/HASHED except with caution.

[!CAUTION] DUMP if order is violated on SORTED TABLE.

[!TIP] Paste new files at the end of a folder, respecting order if necessary.

[!IMPORTANT] Check table type and use INSERT for SORTED/HASHED.

Modify where
#

Objectives
#

  • Understand the functioning of MODIFY ... WHERE
  • Know how to modify specific lines of an internal table using a condition
  • Identify the difference with MODIFY INDEX and MODIFY TABLE
  • Use TRANSPORTING to limit modified fields

Definition
#

MODIFY itab FROM ls
            TRANSPORTING comp1 comp2 ...
            WHERE cond.

MODIFY ... WHERE updates an internal table (itab) using a condition to select lines to modify.
The structure ls provides new values and TRANSPORTING allows modifying only certain fields.

Imagine a folder:

  • You search for files matching a precise criterion (WHERE)
  • You modify only necessary information
  • Other files remain unchanged
  • Works for STANDARD, SORTED and HASHED TABLE
  • Useful when key is not known or when a complex condition must be applied
  • Comparable to a WHERE in SQL

Declaration and example
#

TYPES: BEGIN OF ty_country,
         land TYPE char3,
         age  TYPE i,
       END OF ty_country.

DATA: lt_country TYPE HASHED TABLE OF ty_country WITH UNIQUE KEY land,
      ls_country TYPE ty_country.

" Initial filling
ls_country-land = 'FR'.
ls_country-age  = 23.
COLLECT ls_country INTO lt_country.

ls_country-land = 'IT'.
ls_country-age  = 20.
COLLECT ls_country INTO lt_country.

ls_country-land = 'IT'.
ls_country-age  = 55.
COLLECT ls_country INTO lt_country.

ls_country-land = 'FR'.
ls_country-age  = 5.
COLLECT ls_country INTO lt_country.

" CLEAR of key for conditional modification
CLEAR ls_country-land.
ls_country-age  = 10.

" Modification with WHERE
MODIFY lt_country FROM ls_country TRANSPORTING age
                  WHERE land = 'IT'.
  • The WHERE clause selects the line(s) to modify
  • TRANSPORTING restricts modification to listed fields
  • Unlike MODIFY TABLE, search is not done via key but via condition
  • Ideal for complex conditional modifications

Table state
#

Before MODIFY:

LAND AGE
FR 28
IT 75

After MODIFY:

LAND AGE
FR 28
IT 10

Best practices
#

Best practice Explanation
Check WHERE clause Ensures only desired line will be modified
Use TRANSPORTING for targeted fields Limits modification to necessary fields
Initialize structure correctly Avoids rewriting undesirable values
Compare with MODIFY TABLE Know when to use key or condition
Test on table subset Prevent accidental modifications

Exercises
#

1 – Modify by simple condition
#

Modify age of countries 'FR' to 35.

SOLUTION
CLEAR ls_country-land.
ls_country-age = 35.
MODIFY lt_country FROM ls_country TRANSPORTING age
                  WHERE land = 'FR'.

2 – Modify multiple lines with condition
#

Add 5 years to all countries where age is less than 30.

SOLUTION
LOOP AT lt_country INTO ls_country.
  IF ls_country-age < 30.
    ls_country-age = ls_country-age + 5.
    MODIFY lt_country FROM ls_country TRANSPORTING age
                      WHERE land = ls_country-land.
  ENDIF.
ENDLOOP.

3 – Comparison with modify table
#

Explain practical difference between MODIFY TABLE and MODIFY WHERE.

Explanation
  • MODIFY TABLE: modifies a line via key
  • MODIFY WHERE: modifies one or more lines via condition
  • WHERE is necessary when key is not known or multiple lines must be updated
  • TRANSPORTING remains useful to modify only certain fields

Summary
#

  • MODIFY ... WHERE updates lines of an internal table according to a condition
  • Allows modifying all fields or only certain ones via TRANSPORTING
  • Difference with MODIFY INDEX: selection by condition instead of an index
  • Difference with MODIFY TABLE: selection by condition instead of key

[!TIP] Modify certain files in a folder based on a precise criterion

[!IMPORTANT] Check the WHERE clause, initialize the structure and use TRANSPORTING

Modify with index
#

Objectives
#

  • Understand the functioning of MODIFY ... INDEX
  • Know how to modify specific lines of an internal table using a condition
  • Identify the difference with MODIFY INDEX and MODIFY TABLE
  • Use TRANSPORTING to limit modified fields

Definition
#

For the MODIFY instruction, there are three possible syntax forms.

MODIFY itab [INDEX idx] FROM ls
            [TRANSPORTING comp1 comp2 ...].

The instruction MODIFY will modify the internal table itab from the structure ls_. It is possible to indicate the index of the line to modify (INDEX idx) as well as the list of fields to modify (TRANSPORTING comp1 comp2…).

Declaration and example
#

TYPES: BEGIN OF ty_country,
         land   TYPE char3,
         age(3) TYPE i,
       END OF ty_country.

DATA: lt_country TYPE STANDARD TABLE OF ty_country WITH NON-UNIQUE KEY land,
      ls_country TYPE ty_country.

ls_country-land = 'FR'.
ls_country-age  = 23.
COLLECT ls_country INTO lt_country.

ls_country-land = 'IT'.
ls_country-age  = 20.
COLLECT ls_country INTO lt_country.

ls_country-land = 'IT'.
ls_country-age  = 55.
COLLECT ls_country INTO lt_country.

ls_country-land = 'FR'.
ls_country-age  = 5.
COLLECT ls_country INTO lt_country.

ls_country-land = 'FR'.
ls_country-age  = 10.
MODIFY lt_country INDEX 1 FROM ls_country TRANSPORTING age.

Before the MODIFY, the structure ls_country is initialized with desired values. Then, the program will modify the internal table lt_country at index 1, from the structure ls_country, to modify only the AGE field.

lt_country before MODIFY

LAND AGE
FR 28
IT 75

lt_country after MODIFY

LAND AGE
FR 10
IT 75

Copy table
#

Objectives
#

  • Copy all lines from one internal table to another
  • Understand the use of brackets [] to copy complete content
  • Know that this operation duplicates all data and not the reference
  • Know precautions to take before a copy
  • Be able to verify the success of a copy

Definition
#

itab_dest[] = itab_src[]

The instruction COPY TABLE (written in ABAP as itab_dest[] = itab_src[]) allows copying all lines from one internal table to another.

Imagine two folders:

  • itab_src = original folder filled with files
  • itab_dest = empty folder
    Copying itab_src[] to itab_dest[] is like photocopying all files from the first to store them in the second.

Examples
#

1 – Complete copy of an internal table
#

TYPES: BEGIN OF ty_citizen,
         country TYPE char3,
         name    TYPE char20,
         age     TYPE numc2,
       END OF ty_citizen.

DATA: lt_citizen_src  TYPE STANDARD TABLE OF ty_citizen,
      lt_citizen_dest TYPE STANDARD TABLE OF ty_citizen,
      ls_citizen      TYPE ty_citizen.

" FILLING SOURCE TABLE
ls_citizen-country = 'FR'.
ls_citizen-name    = 'Thierry'.
ls_citizen-age     = '24'.
APPEND ls_citizen TO lt_citizen_src.

ls_citizen-country = 'ES'.
ls_citizen-name    = 'Luis'.
ls_citizen-age     = '32'.
APPEND ls_citizen TO lt_citizen_src.

" COPY ALL LINES
lt_citizen_dest[] = lt_citizen_src[].

" DISPLAY DESTINATION TABLE
LOOP AT lt_citizen_dest ASSIGNING FIELD-SYMBOLS(<lfs_citizen>).
  WRITE:/ <lfs_citizen>-country, <lfs_citizen>-name, <lfs_citizen>-age.
ENDLOOP.

The table lt_citizen_dest now contains exactly the same lines as lt_citizen_src.

If lt_citizen_dest already contained data, it will be replaced (not added).

2 – Copy with identical but empty structure
#

DATA: lt_empty_src TYPE STANDARD TABLE OF ty_citizen,
      lt_copy     TYPE STANDARD TABLE OF ty_citizen.

lt_copy[] = lt_empty_src[].

If the source table is empty, the destination table will be empty too.
This can be useful to reset a table without using CLEAR.

3 – Copy with dynamic declaration
#

FIELD-SYMBOLS: <lfs_src>  TYPE STANDARD TABLE,
               <lfs_dest> TYPE STANDARD TABLE.

DATA: lt_people TYPE STANDARD TABLE OF ty_citizen.

ASSIGN lt_people TO <lfs_src>.
ASSIGN lt_citizen_dest TO <lfs_dest>.

IF <lfs_src> IS ASSIGNED AND <lfs_dest> IS ASSIGNED.
  <lfs_dest>[] = <lfs_src>[].
ENDIF.

This method is used in programs where table names vary according to contexts.
It allows copying dynamically without knowing the exact names of tables.

Useful in generic modules, reusable functions, or loops processing several different internal tables.

Best practices
#

Best practice Explanation
Always check content with LINES() Allows confirming that copy was done
Use [] to indicate complete content Without brackets, only table reference would be copied, not its data
Prepare destination table If it already contains data, it will be replaced
Avoid unnecessary copies For large tables, this can slow down the program
Favor FIELD-SYMBOLS to modify If goal is to manipulate directly, no need to duplicate data

Summary
#

itab_dest[] = itab_src[] is the simplest method to completely copy an internal table.

  • Brackets [] mean “copy of all content”
  • Data is duplicated, not just the reference
  • Old lines are replaced
  • Possibility to use FIELD-SYMBOLS for dynamic processing

[!TIP] Copying a table is like scanning an entire folder to make a faithful copy, without touching the original.

Move corresponding
#

Objectives
#

  • Copy only values of corresponding fields between internal tables
  • Understand the difference between COPY TABLE and MOVE-CORRESPONDING
  • Know how to combine multiple source tables to the same target table
  • Learn to manipulate different structures without type error

Definition
#

MOVE-CORRESPONDING itab_src TO itab_dest.

The instruction MOVE-CORRESPONDING allows copying only fields with the same name between a source internal table and a destination internal table.

Imagine two forms with similar sections (for example: Name, Country, Age).
MOVE-CORRESPONDING copies only sections with the same heading, without touching other fields.

  • If source and destination have different fields, only corresponding fields are copied.
  • Fields that don’t exist in the other structure are ignored without error.
  • Operation can be repeated to merge multiple tables into the same target.

Example 1 – Copy between different tables
#

TYPES: BEGIN OF ty_citizen_src,
         country TYPE char3,
         name    TYPE char20,
         age     TYPE numc2,
       END OF ty_citizen_src.

TYPES: BEGIN OF ty_citizen_dest,
         name    TYPE char20,
         country TYPE char3,
       END OF ty_citizen_dest.

DATA: lt_citizen_src  TYPE STANDARD TABLE OF ty_citizen_src,
      lt_citizen_dest TYPE STANDARD TABLE OF ty_citizen_dest,
      ls_src          TYPE ty_citizen_src.

" --- FILLING SOURCE TABLE ---
ls_src-country = 'FR'.
ls_src-name    = 'Thierry'.
ls_src-age     = '24'.
APPEND ls_src TO lt_citizen_src.

ls_src-country = 'ES'.
ls_src-name    = 'Luis'.
ls_src-age     = '32'.
APPEND ls_src TO lt_citizen_src.

" --- TRANSFER CORRESPONDING FIELDS ---
MOVE-CORRESPONDING lt_citizen_src TO lt_citizen_dest.

" --- VERIFICATION ---
LOOP AT lt_citizen_dest ASSIGNING FIELD-SYMBOLS(<llfs_dest>).
  WRITE:/ <llfs_dest>-country, <llfs_dest>-name.
ENDLOOP.
  • lt_citizen_src contains an age field absent in lt_citizen_dest.
  • MOVE-CORRESPONDING copies only country and name fields, because they exist in both structures.

The system automatically handles name correspondence without considering field order.

Example 2 – Merging multiple tables
#

DATA: lt_additional TYPE STANDARD TABLE OF ty_citizen_src.

" Filling another source table
ls_src-country = 'DE'.
ls_src-name    = 'Klaus'.
ls_src-age     = '28'.
APPEND ls_src TO lt_additional.

" Successive copy into target table
MOVE-CORRESPONDING lt_citizen_src TO lt_citizen_dest.
MOVE-CORRESPONDING lt_additional  TO lt_citizen_dest.

Like filling a common register from multiple lists:
each MOVE-CORRESPONDING adds compatible lines without causing errors.

Lines are not merged field by field, but added to the destination table.
This can create duplicates if data is repeated.

Example 3 – With dynamic declarations
#

FIELD-SYMBOLS: <lfs_src>  TYPE STANDARD TABLE,
               <lfs_dest> TYPE STANDARD TABLE.

DATA: lt_source TYPE STANDARD TABLE OF ty_citizen_src,
      lt_target TYPE STANDARD TABLE OF ty_citizen_dest.

ASSIGN lt_source TO <lfs_src>.
ASSIGN lt_target TO <lfs_dest>.

IF <lfs_src> IS ASSIGNED AND <lfs_dest> IS ASSIGNED.
  MOVE-CORRESPONDING <lfs_src> TO <lfs_dest>.
ENDIF.

This type of instruction is very useful in generic programs or reports that manipulate different structures dynamically.

Prefer this approach when the program must process multiple types of internal tables with similar fields.

Difference with copy table
#

Instruction Description Type of correspondence
itab1[] = itab2[] Copies all fields (same structure mandatory) Total correspondence
MOVE-CORRESPONDING itab2 TO itab1 Copies only fields with same name, different structures accepted Partial correspondence
  • COPY TABLE = raw copy (all columns must exist).
  • MOVE-CORRESPONDING = intelligent copy (only common columns are transferred).

Best practices
#

Best practice Explanation
Always check field names Correspondence is based on names, not position
Use MOVE-CORRESPONDING for different structures Avoids type errors
Check duplicates during merges Multiple MOVE-CORRESPONDING can add identical lines
Prefer FIELD-SYMBOLS for generic programs Allows manipulating structures unknown in advance

Summary
#

MOVE-CORRESPONDING allows transferring only common fields between two structures or internal tables.

  • Ideal for different but similar structures
  • Ignores non-existent fields without error

Delete
#

Objectives
#

  • Understand the functioning of the DELETE instruction for internal tables
  • Know how to delete lines based on index, key or WHERE condition
  • Identify limitations according to internal table type
  • Use DELETE safely and efficiently

Definition
#

DELETE { TABLE itab { FROM ls }
        | { WITH TABLE KEY [keyname COMPONENTS]
                {comp_name1|(name1)} = operand1
                {comp_name2|(name2)} = operand2 ...}
        | itab INDEX idx
        | itab WHERE cond }.

The instruction DELETE removes lines from an internal table (itab).
Three main forms:

  • DELETE itab INDEX idx: deletes the line at specified index
  • DELETE itab FROM ls: deletes the line corresponding to structure / key
  • DELETE itab WHERE cond: deletes all lines respecting the condition

Imagine a folder:

  • Remove a file at a precise position
  • Delete the file corresponding to an identifier
  • Remove all files corresponding to a specific criterion
  • Deleted lines disappear permanently
  • Indexes of following lines are adjusted automatically for STANDARD TABLE
  • HASHED TABLE and SORTED TABLE handle deletion via key or condition

Examples
#

Delete by index
#

" Delete first line of lt_country (STANDARD TABLE only)
DELETE lt_country INDEX 1.

Delete by structure / Key
#

ls_country-land = 'FR'.
DELETE lt_country FROM ls_country.  " Deletes line where key LAND = 'FR'

Delete with where
#

DELETE lt_country WHERE age < 30.  " Deletes all lines with age < 30
  • INDEX: applicable only to STANDARD TABLE
  • FROM / key: works for STANDARD and HASHED TABLE (based on key)
  • WHERE: applicable to all tables, allows deleting multiple lines according to criterion
  • Deleted lines are permanently removed and index of following lines is adjusted automatically

Best practices
#

Best practice Explanation
Check table type INDEX only for STANDARD
Initialize structure correctly Ensure targeted deletion with FROM
Use WHERE for multiple lines Deletes all lines matching condition
Avoid DELETE in unnecessary loop Prevent performance impacts
Confirm lines to delete Limit accidental deletions

Exercises
#

1 – Delete by index
#

Delete the first line of lt_country.

SOLUTION
DELETE lt_country INDEX 1.

2 – Delete by structure / Key
#

Delete the line with LAND = ‘IT’.

SOLUTION
CLEAR ls_country-land.
ls_country-land = 'IT'.
DELETE lt_country FROM ls_country.

3 – Delete with where
#

Delete all lines where AGE < 25.

SOLUTION
DELETE lt_country WHERE age < 25.

4 – Comparison of methods
#

Explain when to use INDEX, FROM, WHERE.

Explanation
  • DELETE INDEX: fast, applicable only to STANDARD TABLE
  • DELETE FROM: deletes line corresponding to key or structure
  • DELETE WHERE: deletes all lines corresponding to criterion, useful for conditional deletions
  • Use WHERE for multiple deletions and INDEX/FROM for targeted deletions

Summary
#

  • DELETE deletes one or more lines from an internal table according to index, key or WHERE condition

[!TIP] Remove files from a folder either by position, by identifier, or by specific criterion

[!IMPORTANT] Check table type, initialize structure, use WHERE for multiple lines and avoid unnecessary deletions in loop

Delete adjacent duplicates
#

Objectives
#

  • Understand the functioning of DELETE ADJACENT DUPLICATES
  • Know how to delete duplicates in an internal table according to key or specific fields
  • Identify constraints related to table type and data order
  • Use COMPARING correctly to select relevant fields

Definition
#

DELETE ADJACENT DUPLICATES FROM itab
                          [COMPARING {comp1 comp2 ...}].

The instruction DELETE ADJACENT DUPLICATES deletes consecutive duplicate lines in an internal table (itab).

  • If no field is specified with COMPARING, deletion is based on table’s primary key.
  • If fields are specified via COMPARING, only these fields are used to detect duplicates.

Imagine a sorted folder:

  • Consecutive files with the same identifier or same information are merged into one
  • Unique files remain intact
  • For STANDARD TABLE, prior sorting is mandatory before deletion
  • For SORTED TABLE, sorting is ensured automatically by key
  • Deletion removes only adjacent duplicates, not scattered duplicates

Declaration and examples
#

Sorted table
#

TYPES: BEGIN OF ty_citizen,
         country TYPE char3,
         name    TYPE char20,
         age     TYPE numc2,
       END OF ty_citizen.

DATA: lt_citizen TYPE SORTED TABLE OF ty_citizen WITH NON-UNIQUE KEY country,
      ls_citizen TYPE ty_citizen.

" Data insertion
ls_citizen-country = 'FR'.
ls_citizen-name    = 'Thierry'.
ls_citizen-age     = '24'.
INSERT ls_citizen INTO TABLE lt_citizen.

ls_citizen-country = 'ES'.
ls_citizen-name    = 'Luis'.
ls_citizen-age     = '32'.
INSERT ls_citizen INTO TABLE lt_citizen.

ls_citizen-country = 'BR'.
ls_citizen-name    = 'Renata'.
ls_citizen-age     = '27'.
INSERT ls_citizen INTO TABLE lt_citizen.

ls_citizen-country = 'FR'.
ls_citizen-name    = 'Floriane'.
ls_citizen-age     = '32'.
INSERT ls_citizen INTO TABLE lt_citizen.

" Delete adjacent duplicates (primary key)
DELETE ADJACENT DUPLICATES FROM lt_citizen.

Standard table
#

DATA: lt_citizen_std TYPE TABLE OF ty_citizen.

" Adding data
APPEND ls_citizen TO lt_citizen_std.
" ... (other records)

" Mandatory sorting before deletion
SORT lt_citizen_std BY country.
DELETE ADJACENT DUPLICATES FROM lt_citizen_std COMPARING country.
  • STANDARD TABLE: mandatory sorting for duplicates to be adjacent
  • SORTED TABLE: deletion based automatically on key
  • COMPARING allows targeting precise fields to detect duplicates
  • Fields listed in COMPARING must correspond to those used for sorting

Best practices
#

Best practice Explanation
Always sort table before deletion Necessary for STANDARD TABLE
Use COMPARING if key not relevant Targets only necessary fields
Check duplicates before deletion Prevent loss of important data
Respect field order Aligned with sorting to avoid incorrect deletions
Apply on consequent tables Avoid incomplete deletion if duplicates not adjacent

Exercises
#

1 – Delete duplicates on sorted table
#

Delete consecutive duplicates on country key.

SOLUTION
DELETE ADJACENT DUPLICATES FROM lt_citizen.

2 – Delete duplicates on standard table
#

Delete consecutive duplicates on country field.

SOLUTION
SORT lt_citizen_std BY country.
DELETE ADJACENT DUPLICATES FROM lt_citizen_std COMPARING country.

3 – Delete duplicates on multiple fields
#

Delete duplicates where country and age are identical.

SOLUTION
SORT lt_citizen_std BY country age.
DELETE ADJACENT DUPLICATES FROM lt_citizen_std COMPARING country age.

Summary
#

  • DELETE ADJACENT DUPLICATES deletes consecutive duplicate lines in an internal table
  • Without COMPARING: deletion based on primary key
  • With COMPARING: deletion based on specified fields
  • STANDARD TABLE: sort before deletion
  • SORTED TABLE: deletion based on primary key automatically

[!TIP] Remove identical consecutive files in a sorted folder

Read table
#

Objectives
#

  • Read a line from an internal table with READ TABLE
  • Use options WITH KEY, INDEX to locate the line
  • Understand result storage modes: INTO, ASSIGNING, TRANSPORTING NO FIELDS
  • Master use of FIELD-SYMBOLS to directly manipulate memory
  • Check returns with SY-SUBRC and know index via SY-TABIX

Definition
#

READ TABLE itab
  { INTO ls | ASSIGNING <lfs_> | TRANSPORTING NO FIELDS }
  { FROM ls | WITH KEY { comp1 = obj1 comp2 = obj2 ... } [BINARY SEARCH] | INDEX idx }.

The instruction READ TABLE allows reading a line from an internal table (itab) according to different criteria.

Search for a file in a folder, either by file example, by precise criterion, or by number.

Examples with structure
#

Read with structure and condition
#

Simple version of READ with condition where data from found/read line is stored in a structure declared beforehand.

Conditions are essential to identify desired line. It is therefore imperative to properly fill in condition(s) necessary for its identification.

DATA: ls_struct TYPE ty_struct.

READ TABLE lt_citizen INTO ls_struct WITH KEY country = 'FR'.
IF sy-subrc = 0.
  WRITE:/ 'READ FROM structure:', ls_struct-country, ls_struct-name, ls_struct-age.
ENDIF.

Read with structure and conditions
#

Simple version of READ with multiple conditions where data from found/read line is stored in a structure declared beforehand.

Conditions are essential to identify desired line. It is therefore imperative to properly fill in condition(s) necessary for its identification.

DATA: ls_struct TYPE ty_struct.

READ TABLE lt_citizen INTO ls_struct WITH KEY country = 'FR' name = 'Thierry'.
IF sy-subrc = 0.
  WRITE:/ 'READ FROM structure:', ls_struct-country, ls_struct-name, ls_struct-age.
ENDIF.

Read with structure on 1st line (index 1)
#

Version of READ targeting 1st line where data from this line is pointed to in a field-symbol declared beforehand.

DATA: ls_struct TYPE ty_struct.

READ TABLE lt_citizen INTO ls_struct INDEX 1.
IF sy-subrc = 0.
  WRITE:/ 'READ FROM structure:', ls_struct-country, ls_struct-name, ls_struct-age.
ENDIF.

Read with structure and condition + transporting no fields parameter
#

Simple version of READ with condition where no data is retrieved. Here READ mainly serves to check presence of corresponding entry.

Conditions are essential to identify desired line. It is therefore imperative to properly fill in condition(s) necessary for its identification.

DATA: ls_struct TYPE ty_struct.

READ TABLE lt_citizen WITH KEY country = 'FR' TRANSPORTING NO FIELDS.
IF sy-subrc = 0.
  WRITE:/ 'We found a line!'.
ENDIF.

Read with dynamically declared structure
#

Simple version of READ with multiple conditions where data from found/read line is stored in a dynamically declared structure.

Conditions are essential to identify desired line. It is therefore imperative to properly fill in condition(s) necessary for its identification.

READ TABLE lt_citizen INTO DATA(ls_struct) WITH KEY country = 'FR' name = 'Thierry'.
IF sy-subrc = 0.
  WRITE:/ 'READ FROM structure:', ls_struct-country, ls_struct-name, ls_struct-age.
ENDIF.

Examples with field-symbol
#

Read with field-symbol and condition
#

Version of READ targeting a line via condition and where data from this line is pointed to in a field-symbol declared beforehand.

Conditions are essential to identify desired line. It is therefore imperative to properly fill in condition(s) necessary for its identification.

FIELD-SYMBOLS: <lfs_citizen> TYPE ty_citizen.

READ TABLE lt_citizen ASSIGNING <lfs_citizen> WITH KEY country = 'FR'.
IF sy-subrc = 0.
  WRITE:/ 'READ FROM structure:', <lfs_citizen>-country, <lfs_citizen>-name, <lfs_citizen>-age.
ENDIF.

Read with field-symbol and conditions
#

Version of READ targeting a line via conditions and where data from this line is pointed to in a field-symbol declared beforehand.

Conditions are essential to identify desired line. It is therefore imperative to properly fill in condition(s) necessary for its identification.

FIELD-SYMBOLS: <lfs_citizen> TYPE ty_citizen.

READ TABLE lt_citizen ASSIGNING <lfs_citizen> WITH KEY country = 'FR' name = 'Thierry'.
IF sy-subrc = 0.
  WRITE:/ 'READ FROM structure:', <lfs_citizen>-country, <lfs_citizen>-name, <lfs_citizen>-age.
ENDIF.

Read with field-symbol on 1st line (index 1)
#

Version of READ targeting 1st line where data from this line is pointed to in a field-symbol declared beforehand.

FIELD-SYMBOLS: <lfs_citizen> TYPE ty_citizen.

READ TABLE lt_citizen ASSIGNING <lfs_citizen> INDEX 1.
IF sy-subrc = 0.
  WRITE:/ 'READ FROM structure:', <lfs_citizen>-country, <lfs_citizen>-name, <lfs_citizen>-age.
ENDIF.

Read with field-symbol with condition + transporting no fields parameter
#

Version of READ with condition where no data is retrieved. Here READ mainly serves to check presence of corresponding entry.

Conditions are essential to identify desired line. It is therefore imperative to properly fill in condition(s) necessary for its identification.

FIELD-SYMBOLS: <lfs_citizen> TYPE ty_citizen.

READ TABLE lt_citizen ASSIGNING <lfs_citizen> WITH KEY country = 'FR' TRANSPORTING NO FIELDS.
IF sy-subrc = 0.
  WRITE:/ 'We found a line!'.
ENDIF.

Read with dynamically declared field-symbol
#

Simple version of READ with multiple conditions where data from found/read line is pointed to in a dynamically declared structure.

Conditions are essential to identify desired line. It is therefore imperative to properly fill in condition(s) necessary for its identification.

READ TABLE lt_citizen ASSIGNING FIELD-SYMBOL(<lfs_citizen>) WITH KEY country = 'FR' name = 'Thierry'.
IF sy-subrc = 0.
  WRITE:/ 'READ FROM structure:', <lfs_citizen>-country, <lfs_citizen>-name, <lfs_citizen>-age.
ENDIF.

Best practices
#

Best practice Explanation
Always test SY-SUBRC Ensures line was found before accessing fields
Use ASSIGNING <fs> for performance Avoids line copy, modifies memory directly
TRANSPORTING NO FIELDS for verification Just checks existence without copying or modifying
Compare with READ TABLE INDEX and KEY Know how to choose method adapted to table type and key

Summary
#

READ TABLE allows locating and accessing a line in an internal table.

  • Search options: WITH KEY, INDEX
  • Retrieval options: INTO, ASSIGNING, TRANSPORTING NO FIELDS
  • System variables: SY-SUBRC and SY-TABIX

[!TIP] Search for a file in a folder and point directly to it for modification.

Binary search #

Objectives
#

  • Understand the BINARY SEARCH option with READ TABLE
  • Know how to use it to optimize searches in an internal table
  • Know the necessary condition for binary search to work
  • Identify advantages compared to linear search

Definition
#

The BINARY SEARCH option used with READ TABLE allows performing a binary search in an internal table, thus optimizing program performance.

Binary search principle:

  • Compare searched value to middle value of range
  • If equal → return index, end search
  • If value > middle → search in lower half
  • If value < middle → search in upper half
  • Repeat until finding value or exhausting range

The table must be sorted (SORT) unless it is of type SORTED.

Search for a name in a directory sorted alphabetically by always opening to the middle page to divide searches.

Example
#

TYPES: BEGIN OF ty_citizen,
         country TYPE char3,
         name    TYPE char20,
         age     TYPE numc2,
       END OF ty_citizen.

DATA: lt_citizen TYPE STANDARD TABLE OF ty_citizen,
      ls_citizen TYPE ty_citizen.

FIELD-SYMBOLS: <lfs_citizen> TYPE ty_citizen.

" Table filling
ls_citizen-country = 'FR'. ls_citizen-name = 'Thierry'.  ls_citizen-age = '24'. APPEND ls_citizen TO lt_citizen.
ls_citizen-country = 'ES'. ls_citizen-name = 'Luis'.     ls_citizen-age = '32'. APPEND ls_citizen TO lt_citizen.
ls_citizen-country = 'BR'. ls_citizen-name = 'Renata'.   ls_citizen-age = '27'. APPEND ls_citizen TO lt_citizen.
ls_citizen-country = 'FR'. ls_citizen-name = 'Floriane'. ls_citizen-age = '32'. APPEND ls_citizen TO lt_citizen.

" Mandatory sorting for BINARY SEARCH
SORT lt_citizen BY country name.

" Binary search
READ TABLE lt_citizen WITH KEY country = 'FR' name = 'Floriane' BINARY SEARCH ASSIGNING <lfs_citizen>.
IF sy-subrc = 0.
  WRITE:/ 'Record found at line:', sy-tabix, 'Country:', <lfs_citizen>-country, 'Name:', <lfs_citizen>-name.
ENDIF.

Best practices
#

Best practice Explanation
Sort table before BINARY SEARCH Mandatory for STANDARD tables
Use ASSIGNING for performance Avoids line copy, modifies memory directly
Check SY-SUBRC Ensure record was found
Compare BINARY SEARCH vs linear search Significant reduction in number of comparisons
Use BY with all key fields Allows precise and correct search

Exercises
#

1 – Simple binary search + dynamic field-symbol declaration
#

Sort lt_citizen by country then name and read the record where country = 'ES' and name = 'Luis' using BINARY SEARCH. Display age.

SOLUTION
SORT lt_citizen BY country name.

READ TABLE lt_citizen WITH KEY country = 'ES' name = 'Luis' BINARY SEARCH ASSIGNING FIELD-SYMBOL(<lfs_citizen>).
IF sy-subrc = 0.
  WRITE:/ 'Age of citizen Luis in ES:', <lfs_citizen>-age.
ENDIF.

2 – Check existence without copying
#

Check if a record country = 'BR' and name = 'Renata' exists in lt_citizen with BINARY SEARCH, without copying the line (TRANSPORTING NO FIELDS). Display a message.

SOLUTION
READ TABLE lt_citizen WITH KEY country = 'BR' name = 'Renata' BINARY SEARCH TRANSPORTING NO FIELDS.
IF sy-subrc = 0.
  WRITE:/ 'Record BR-Renata found!'.
ELSE.
  WRITE:/ 'Record BR-Renata not found.'.
ENDIF.

Summary
#

BINARY SEARCH allows fast search in a sorted internal table.

  • Condition: sorted table or SORTED type
  • Reduces number of comparisons compared to linear search
  • Returns INDEX via SY-TABIX and return code via SY-SUBRC

[!TIP] Browse a sorted directory by always opening in the middle to divide searches and find the person faster.

Loop at
#

Objectives
#

  • Browse an internal table line by line with LOOP AT
  • Use options INTO, ASSIGNING <fs> and TRANSPORTING NO FIELDS
  • Filter with WHERE, FROM and TO
  • Dynamically declare structures and FIELD-SYMBOLS for more flexibility
  • Modify lines directly via FIELD-SYMBOLS
  • Understand system variables SY-SUBRC and SY-TABIX
  • Use breaks AT FIRST, AT NEW, AT END OF, AT LAST
  • Use complex filters with WHERE on one or more fields

Definition
#

LOOP AT itab
  { INTO ls | ASSIGNING <lfs_> | TRANSPORTING NO FIELDS }
  [FROM idx1] [TO idx2]
  [WHERE condition]
  ...
  AT ...
    ...
  ENDAT.
  ...
ENDLOOP.

The instruction LOOP AT allows browsing an internal table (itab) line by line.
Data can be copied (INTO), referenced in memory (ASSIGNING <fs>) or simply verified (TRANSPORTING NO FIELDS).

Browse a folder line by line:

  • INTO = photocopy the file
  • ASSIGNING <lfs_> = point directly to the file to modify
  • TRANSPORTING NO FIELDS = just check if file exists

Simple examples
#

Loop with into
#

DATA: ls_citizen TYPE ty_citizen.

LOOP AT lt_citizen INTO ls_citizen WHERE country = 'FR'.
  WRITE:/ 'Country:', ls_citizen-country, 'Name:', ls_citizen-name, 'Age:', ls_citizen-age.
ENDLOOP.

Copy of line into ls_citizen. Modification of ls_citizen will not affect lt_citizen.

Loop with assigning field-symbol
#

FIELD-SYMBOLS: <lfs_citizen> TYPE ty_citizen.

LOOP AT lt_citizen ASSIGNING <lfs_citizen> WHERE country = 'ES'.
  <lfs_citizen>-age = <lfs_citizen>-age + 1.
  WRITE:/ 'Country:', <lfs_citizen>-country, 'Name:', <lfs_citizen>-name, 'New age:', <lfs_citizen>-age.
ENDLOOP.

Direct modification in table without using MODIFY.

Loop with transporting no fields
#

LOOP AT lt_citizen TRANSPORTING NO FIELDS WHERE name = 'Renata'.
  IF sy-subrc = 0.
    WRITE:/ 'Renata is present in the table.'.
  ENDIF.
ENDLOOP.

Simply check existence without copying or modifying line.

Loop with from / to
#

LOOP AT lt_citizen INTO ls_citizen FROM 2 TO 3.
  WRITE:/ 'Country:', ls_citizen-country, 'Name:', ls_citizen-name.
ENDLOOP.

Limits loop to lines 2 and 3 to process a precise range.

Loop with dynamic declaration
#

DATA: lt_dyn TYPE STANDARD TABLE OF ty_citizen.

LOOP AT lt_dyn INTO DATA(ls_dyn).
  ls_dyn-country = 'IT'.
  WRITE:/ 'Updated country:', ls_dyn-country, 'Name:', ls_dyn-name.
ENDLOOP.

LOOP AT lt_dyn ASSIGNING FIELD-SYMBOLS(<lfs_dyn_row>).
  <lfs_dyn_row>-country = 'IT'.
  WRITE:/ 'Updated country:', <lfs_dyn_row>-country, 'Name:', <lfs_dyn_row>-name.
ENDLOOP.

Useful to create or manipulate structures as you go, and to avoid FIELD-SYMBOLS conflicts.

Loop with at first / at new / at end of / at last
#

SORT lt_citizen BY country.

LOOP AT lt_citizen ASSIGNING <lfs_citizen>.
  AT FIRST.
    WRITE: 'Beginning of list'.
    ULINE.
  ENDAT.

  AT NEW country.
    WRITE:/ 'Beginning country:', <lfs_citizen>-country.
  ENDAT.

  WRITE:/ 'Name:', <lfs_citizen>-name, 'Age:', <lfs_citizen>-age.

  AT END OF country.
    WRITE:/ 'End country:', <lfs_citizen>-country.
    ULINE.
  ENDAT.

  AT LAST.
    WRITE: 'End of list'.
  ENDAT.
ENDLOOP.

Allows handling breaks to group or mark sections in the table.

Advanced examples – where
#

1 – Where on one field
#

LOOP AT lt_citizen INTO ls_citizen WHERE country = 'FR'.
  WRITE:/ 'Country:', ls_citizen-country, 'Name:', ls_citizen-name.
ENDLOOP.

Checks all lines where country field = ‘FR’.

2 – Where on two fields (key and non-key)
#

LOOP AT lt_citizen ASSIGNING <lfs_citizen> WHERE country = 'ES' AND age > '30'.
  WRITE:/ 'Country:', <lfs_citizen>-country, 'Name:', <lfs_citizen>-name, 'Age:', <lfs_citizen>-age.
ENDLOOP.

Multiple fields can be combined with AND.

Non-key fields can be used to filter.

3 – Where with multiple comparisons
#

LOOP AT lt_citizen INTO ls_citizen WHERE age >= '25' AND age <= '32'.
  WRITE:/ 'Name:', ls_citizen-name, 'Age:', ls_citizen-age.
ENDLOOP.

Allows selecting value ranges.

Search for all files between 25 and 32 years old.

4 – Where on multiple key and non-key fields
#

LOOP AT lt_citizen ASSIGNING <lfs_citizen> WHERE country = 'FR' AND age = '24' AND name = 'Thierry'.
  WRITE:/ 'Citizen found:', <lfs_citizen>-name, 'Country:', <lfs_citizen>-country.
ENDLOOP.

If table is not sorted correctly for keys, using AT NEW with this filter might not work as expected.

5 – Where with complex conditions
#

LOOP AT lt_citizen INTO ls_citizen WHERE (country = 'BR' OR country = 'IT') AND age < '30'.
  WRITE:/ 'Name:', ls_citizen-name, 'Country:', ls_citizen-country, 'Age:', ls_citizen-age.
ENDLOOP.

AND and OR can be combined respecting parentheses priority.

6 – Dynamic where (with field-symbol)
#

DATA: lv_country TYPE char3 VALUE 'ES'.

LOOP AT lt_citizen ASSIGNING FIELD-SYMBOLS(<dyn_citizen>) WHERE country = lv_country AND age > '30'.
  WRITE:/ 'Name:', <dyn_citizen>-name, 'Country:', <dyn_citizen>-country, 'Age:', <dyn_citizen>-age.
ENDLOOP.

Allows using dynamic variables in conditions.

Best practices
#

Best practice Explanations
Always sort table before AT NEW Necessary for STANDARD tables if using breaks
Prefer ASSIGNING to modify Avoids copy and allows working directly in memory
Use WHERE to filter Reduces number of lines browsed
Check SY-SUBRC Useful if using TRANSPORTING NO FIELDS
Unique FIELD-SYMBOLS per scope Avoids errors and conflicts in nested loops
FROM/TO to limit ranges Optimizes processing if only certain lines are concerned
Parentheses with AND/OR Clarifies complex conditions and avoids errors

Exercises
#

1 – Where on single field
#

Browse lt_citizen and display citizens where country = 'FR'.

SOLUTION
LOOP AT lt_citizen INTO ls_citizen WHERE country = 'FR'.
  WRITE:/ 'Country:', ls_citizen-country, 'Name:', ls_citizen-name.
ENDLOOP.

2 – Where on multiple fields
#

Display citizens where country = 'ES' and age > 30.

SOLUTION
LOOP AT lt_citizen ASSIGNING <lfs_citizen> WHERE country = 'ES' AND age > '30'.
  WRITE:/ 'Name:', <lfs_citizen>-name, 'Country:', <lfs_citizen>-country, 'Age:', <lfs_citizen>-age.
ENDLOOP.

3 – Where with age range
#

Display citizens aged between 25 and 32 years.

SOLUTION
LOOP AT lt_citizen INTO ls_citizen WHERE age >= '25' AND age <= '32'.
  WRITE:/ 'Name:', ls_citizen-name, 'Age:', ls_citizen-age.
ENDLOOP.

4 – Dynamic where
#

Display all citizens where country = lv_country and age > 30.

SOLUTION
DATA: lv_country TYPE char3 VALUE 'ES'.

LOOP AT lt_citizen ASSIGNING FIELD-SYMBOLS(<dyn_citizen>) WHERE country = lv_country AND age > '30'.
  WRITE:/ 'Name:', <dyn_citizen>-name, 'Country:', <dyn_citizen>-country, 'Age:', <dyn_citizen>-age.
ENDLOOP.

5 – Complex where with or and and
#

Display all citizens where country = 'BR' or country = 'IT' and age < 30.

SOLUTION
LOOP AT lt_citizen INTO ls_citizen WHERE (country = 'BR' OR country = 'IT') AND age < '30'.
  WRITE:/ 'Name:', ls_citizen-name, 'Country:', ls_citizen-country, 'Age:', ls_citizen-age.
ENDLOOP.

Summary
#

LOOP AT allows browsing internal tables line by line.

  • INTO: line copy
  • ASSIGNING: direct reference in memory
  • TRANSPORTING NO FIELDS: verification only
  • WHERE: simple or complex filtering (one or more fields, AND/OR, dynamic variables)
  • FROM / TO: filtering by range
  • FIELD-SYMBOLS: direct modification
  • SY-SUBRC / SY-TABIX: return code and index
  • AT FIRST / AT NEW / AT END OF / AT LAST: break management

Related

Coniunctiones in ABAP
··18 mins· loading · loading
SAP ERP Back-End
Instructions in ABAP
··20 mins· loading · loading
SAP ERP Back-End
ITAB Types in ABAP
··14 mins· loading · loading
SAP ERP Back-End
Introduction to ABAP
·14 mins· loading · loading
SAP ERP Back-End
ABAP Program Structure
··12 mins· loading · loading
SAP ERP Back-End
Loops in ABAP
··11 mins· loading · loading
SAP ERP Back-End