ITAB Instructions in ABAP #
Is initial #
Objectives #
- Check if an internal table is empty or not
- Understand the use of brackets
[] - Use
IS INITIALorIS NOT INITIALto test the content of an internal table - Know that
IS INITIALalso 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 INITIALchecks 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 linesitab[] 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 INITIALreturns TRUE.- After the
APPEND, it contains one line →IS NOT INITIALreturns 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 useitab[] IS INITIALwith 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 INITIALallows checking if an internal table or variable is empty.
itab[] IS INITIAL→ empty tableitab[] 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
CLEARcan also be used on simple variables - Differentiate
CLEAR itab[]andREFRESH itab - Check the content of a table before and after clearing
Definition #
CLEAR: itab[],
var1.
The instruction
CLEARallows 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
CLEARon 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.
TheREFRESHis 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
CLEARon 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 #
CLEARis a simple but powerful instruction
CLEAR itab[]: erases all lines of an internal tableCLEAR var: resets a variable to its initial valueCLEAR structure: reinitializes all fields of the structureCLEARcan be combined on multiple objectsCLEARwith[]is the modern equivalent ofREFRESH[!TIP] It’s like pressing “Reset” – we reset everything to zero before starting cleanly again.
Sort #
Objectives #
- Understand the functioning of the
SORTinstruction for internal tables - Know how to sort according to primary key or specific fields
- Identify the options
ASCENDING,DESCENDING,AS TEXTandSTABLE - 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
SORTorganizes an internal table (itab) of typeSTANDARDorHASHEDaccording to:
- its primary key if defined
- or a list of fields
c1tocn[!NOTE]
ASCENDING/DESCENDING: ascending or descending sortAS TEXT: sort character strings according to local language defined bySET LOCALE LANGUAGESTABLE: 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
STABLEoption guarantees that files with the same criterion remain in the same relative order
SORTEDtables cannot be sorted withSORT, because their order is fixed- Sorting is mandatory before certain operations like
DELETE ADJACENT DUPLICATESfor 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
BYis specified and there is no primary key, the sort can be unstable and randomSTABLEguarantees identical result during multiple sorts- Mandatory before
DELETE ADJACENT DUPLICATESforSTANDARD 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 #
SORTorganizes 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
INSERTinstruction 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
INSERTallows 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
INDEXoption allows controlling the final order of lines.- If no
INDEXis 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_employeeswith a structurety_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_employeeswith two lines and insert them intolt_employeesat 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
APPENDinstruction 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
APPENDandINSERTaccording to table type
Definition #
APPEND { ls | {INITIAL LINE} | {LINES OF jtab [FROM idx1] [TO idx2]} }
TO itab.
The instruction
APPENDadds data always at the end of an internal table (itab).
It works likeINSERT, but the destination parameter is alwaysTO 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)
APPENDis simple and fast forSTANDARDandRANGE TABLE.- For
HASHEDorSORTED TABLE, you must useINSERT INTO TABLEto 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 #
APPENDworks only forSTANDARDandRANGE TABLE.- For
HASHEDorSORTED TABLE, you must useINSERT 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_employeeswith structurety_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_employeesand 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_employeesto the end oflt_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
STANDARDandRANGE, forbidden onSORTED/HASHEDexcept 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
INSERTforSORTED/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 INDEXandMODIFY TABLE - Use TRANSPORTING to limit modified fields
Definition #
MODIFY itab FROM ls
TRANSPORTING comp1 comp2 ...
WHERE cond.
MODIFY ... WHEREupdates an internal table (itab) using a condition to select lines to modify.
The structurelsprovides new values andTRANSPORTINGallows 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,SORTEDandHASHED 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
WHEREclause selects the line(s) to modifyTRANSPORTINGrestricts 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 TABLEandMODIFY WHERE.
Explanation
MODIFY TABLE: modifies a line via keyMODIFY 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 ... WHEREupdates 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
WHEREclause, initialize the structure and useTRANSPORTING
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 INDEXandMODIFY 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 structurels_countryis initialized with desired values. Then, the program will modify the internal tablelt_countryatindex 1, from the structurels_country, to modify only theAGEfield.
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 asitab_dest[] = itab_src[]) allows copying all lines from one internal table to another.
Imagine two folders:
itab_src= original folder filled with filesitab_dest= empty folder
Copyingitab_src[]toitab_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_destnow contains exactly the same lines aslt_citizen_src.
If
lt_citizen_destalready 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 usingCLEAR.
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 TABLEandMOVE-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-CORRESPONDINGallows 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-CORRESPONDINGcopies 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_srccontains anagefield absent inlt_citizen_dest.MOVE-CORRESPONDINGcopies onlycountryandnamefields, 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:
eachMOVE-CORRESPONDINGadds 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-CORRESPONDINGallows 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
DELETEinstruction for internal tables - Know how to delete lines based on index, key or
WHEREcondition - 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
DELETEremoves lines from an internal table (itab).
Three main forms:
DELETE itab INDEX idx: deletes the line at specified indexDELETE itab FROM ls: deletes the line corresponding to structure / keyDELETE 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 toSTANDARD TABLEFROM/ key: works forSTANDARDandHASHED 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 TABLEDELETE FROM: deletes line corresponding to key or structureDELETE WHERE: deletes all lines corresponding to criterion, useful for conditional deletions- Use WHERE for multiple deletions and INDEX/FROM for targeted deletions
Summary #
DELETEdeletes 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
COMPARINGcorrectly to select relevant fields
Definition #
DELETE ADJACENT DUPLICATES FROM itab
[COMPARING {comp1 comp2 ...}].
The instruction
DELETE ADJACENT DUPLICATESdeletes 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 adjacentSORTED TABLE: deletion based automatically on keyCOMPARINGallows targeting precise fields to detect duplicates- Fields listed in
COMPARINGmust 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 DUPLICATESdeletes consecutive duplicate lines in an internal table- Without
COMPARING: deletion based on primary key- With
COMPARING: deletion based on specified fieldsSTANDARD TABLE: sort before deletionSORTED 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,INDEXto 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-SUBRCand know index viaSY-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 TABLEallows 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 TABLEallows locating and accessing a line in an internal table.
- Search options:
WITH KEY,INDEX- Retrieval options:
INTO,ASSIGNING,TRANSPORTING NO FIELDS- System variables:
SY-SUBRCandSY-TABIX[!TIP] Search for a file in a folder and point directly to it for modification.
Binary search #
Objectives #
- Understand the
BINARY SEARCHoption withREAD 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 SEARCHoption used withREAD TABLEallows 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 typeSORTED.
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 |
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_citizenbycountrythennameand read the record wherecountry = 'ES'andname = 'Luis'usingBINARY SEARCH. Displayage.
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'andname = 'Renata'exists inlt_citizenwithBINARY 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 SEARCHallows fast search in a sorted internal table.
- Condition: sorted table or SORTED type
- Reduces number of comparisons compared to linear search
- Returns
INDEXviaSY-TABIXand return code viaSY-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>andTRANSPORTING NO FIELDS - Filter with
WHERE,FROMandTO - Dynamically declare structures and FIELD-SYMBOLS for more flexibility
- Modify lines directly via FIELD-SYMBOLS
- Understand system variables
SY-SUBRCandSY-TABIX - Use breaks
AT FIRST,AT NEW,AT END OF,AT LAST - Use complex filters with
WHEREon 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 ATallows 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 fileASSIGNING <lfs_>= point directly to the file to modifyTRANSPORTING 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 ofls_citizenwill not affectlt_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-SYMBOLSconflicts.
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
countryfield = ‘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 NEWwith 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.
ANDandORcan 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_citizenand display citizens wherecountry = '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'andage > 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_countryandage > 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'orcountry = 'IT'andage < 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 ATallows browsing internal tables line by line.
INTO: line copyASSIGNING: direct reference in memoryTRANSPORTING NO FIELDS: verification onlyWHERE: simple or complex filtering (one or more fields, AND/OR, dynamic variables)FROM/TO: filtering by rangeFIELD-SYMBOLS: direct modificationSY-SUBRC/SY-TABIX: return code and indexAT FIRST/AT NEW/AT END OF/AT LAST: break management