| Creating internal tables with ... | Details/Code Snippet |
| Standard table keys | ``` abap "Standard table without explicit primary table key specification. "Note that STANDARD is not explicitly specified. "Implicitly, the standard key is used; all non-numeric table fields "make up the primary table key. DATA it1 TYPE TABLE OF zdemo_abap_flsch. "Explicitly specifying STANDARD for a standard table. "Explicitly specifying the standard table key. The declaration "corresponds to it1. DATA it2 TYPE STANDARD TABLE OF zdemo_abap_flsch WITH DEFAULT KEY. "Hashed table with unique standard table key DATA it3 TYPE HASHED TABLE OF zdemo_abap_flsch WITH UNIQUE DEFAULT KEY. "Sorted table with non-unique standard table key DATA it4 TYPE SORTED TABLE OF zdemo_abap_flsch WITH NON-UNIQUE DEFAULT KEY. ``` |
| Primary table keys | ``` abap "Specifying the primary table key "In standard tables, only a non-unique key is possible. "The following two examples are the same. NON-UNIQUE can be ommitted but "is implicitly added. DATA it5 TYPE TABLE OF zdemo_abap_flsch WITH NON-UNIQUE KEY carrid. DATA it6 TYPE TABLE OF zdemo_abap_flsch WITH KEY carrid. "Sorted tables: both UNIQUE and NON-UNIQUE possible DATA it7 TYPE SORTED TABLE OF zdemo_abap_flsch WITH UNIQUE KEY carrid connid. DATA it8 TYPE SORTED TABLE OF zdemo_abap_flsch WITH NON-UNIQUE KEY carrid connid cityfrom. "Hashed tables: UNIQUE KEY must be specified DATA it9 TYPE HASHED TABLE OF zdemo_abap_flsch WITH UNIQUE KEY carrid. "Explicitly specifying the predefined name primary_key and listing the components. "The example is the same as it5 and it6. DATA it10 TYPE TABLE OF zdemo_abap_flsch WITH KEY primary_key COMPONENTS carrid. "The following example is the same as it8. DATA it11 TYPE SORTED TABLE OF zdemo_abap_flsch WITH NON-UNIQUE KEY primary_key COMPONENTS carrid connid cityfrom. "Specifying an alias name for a primary table key. "Only possible for sorted/hashed tables. DATA it12 TYPE SORTED TABLE OF zdemo_abap_flsch WITH NON-UNIQUE KEY primary_key ALIAS p1 COMPONENTS carrid connid cityfrom. "Specifying a key that is composed of the entire line using the "predefined table_line. "In the example, an alias name is defined for a primary table key. DATA it13 TYPE HASHED TABLE OF zdemo_abap_flsch WITH UNIQUE KEY primary_key ALIAS p2 COMPONENTS table_line. ``` |
| Empty keys | ``` abap "Empty keys are only possible for standard tables DATA it14 TYPE TABLE OF zdemo_abap_flsch WITH EMPTY KEY. "Empty primary table key, secondary table key specified DATA it15 TYPE TABLE OF zdemo_abap_flsch WITH EMPTY KEY WITH UNIQUE SORTED KEY cities COMPONENTS cityfrom cityto. "Excursion: The inline declaration in a SELECT statement "produces a standard table with empty key. SELECT * FROM zdemo_abap_flsch INTO TABLE @DATA(it16). ``` |
| Secondary table keys | ``` abap "The following examples demonstrate secondary table keys that are "possible for all table categories. DATA it17 TYPE TABLE OF zdemo_abap_flsch "standard table WITH NON-UNIQUE KEY carrid connid "primary table key WITH UNIQUE SORTED KEY cities COMPONENTS cityfrom cityto. "secondary table key DATA it18 TYPE HASHED TABLE OF zdemo_abap_flsch "hashed table WITH UNIQUE KEY carrid connid WITH NON-UNIQUE SORTED KEY airports COMPONENTS airpfrom airpto. DATA it19 TYPE SORTED TABLE OF zdemo_abap_flsch "sorted table WITH UNIQUE KEY carrid connid WITH UNIQUE HASHED KEY countries COMPONENTS countryfr countryto. "Multiple secondary keys are possible DATA it20 TYPE TABLE OF zdemo_abap_flsch WITH NON-UNIQUE KEY primary_key COMPONENTS carrid connid WITH NON-UNIQUE SORTED KEY cities COMPONENTS cityfrom cityto WITH UNIQUE HASHED KEY airports COMPONENTS airpfrom airpto. "Alias names for secondary table keys (and also for the primary "table key in the example) DATA it21 TYPE SORTED TABLE OF zdemo_abap_flsch WITH NON-UNIQUE KEY primary_key ALIAS k1 COMPONENTS carrid connid WITH NON-UNIQUE SORTED KEY cities ALIAS s1 COMPONENTS cityfrom cityto WITH UNIQUE HASHED KEY airports ALIAS s2 COMPONENTS airpfrom airpto. "Excursion: Example of using table keys and alias names using a LOOP AT statement. "All of the statements below are possible. "Note that if the secondary table key is not specified (and if the USING KEY addition is not "used in the example), the primary table key is respected by default. So, the first statement "specifying the primary table key explicitly is the same as not specifying it. "Further ABAP statements, such as READ or MODIFY, are available in which the key can be "explicitly specified to process internal tables. LOOP AT it21 INTO DATA(wa) USING KEY primary_key. "LOOP AT it21 INTO DATA(wa) USING KEY k1. "LOOP AT it21 INTO DATA(wa) USING KEY cities. "LOOP AT it21 INTO DATA(wa) USING KEY s1. "LOOP AT it21 INTO DATA(wa) USING KEY airports. "LOOP AT it21 INTO DATA(wa) USING KEY s2. ... ENDLOOP. ``` |
| Subject | Details/Code Snippet |
| Elementary line types | ``` abap *&---------------------------------------------------------------------* *& Internal tables declared using elementary line types *&---------------------------------------------------------------------* "Note: In this case, the whole table line is the standard table key. "Elementary built-in ABAP types DATA it_elem_1 TYPE TABLE OF i. DATA it_elem_2 TYPE TABLE OF string WITH EMPTY KEY. DATA it_elem_3 TYPE TABLE OF xstring WITH EMPTY KEY. DATA it_elem_4 TYPE TABLE OF utclong WITH EMPTY KEY. "Note: As described above, the table key can consist of components of the "line type or of the entire line using the pseudo component table_line. In "case of elementary line types, table_line is the only option to refer to the "component/entire line. DATA it_elem_5 TYPE SORTED TABLE OF string WITH NON-UNIQUE KEY table_line. "Locally declared elementary types TYPES ty_c3 TYPE c LENGTH 3. DATA it_elem_6 TYPE TABLE OF ty_c3 WITH EMPTY KEY. "Apart from the globally available elementary built-in ABAP types, you can "also use elementary types from the DDIC such as data elements that are "visible anywhere. You can also refer to CDS simple types that "constitute elementary data types. DATA it_elem_7 TYPE TABLE OF timestamp WITH EMPTY KEY. DATA it_elem_8 TYPE TABLE OF timestampl WITH EMPTY KEY. "Globally available elementary types in the public visibility section of "classes/interfaces "Elementary type declared in an interface DATA it_elem_9 TYPE TABLE OF zdemo_abap_get_data_itf=>occ_rate WITH EMPTY KEY. "Note the syntax options when referring to components. In the following "example, a database table field is referred to using the database table name, "the component selector and the name of a field having an elementary data type. DATA it_elem_10 TYPE TABLE OF zdemo_abap_fli-carrid WITH EMPTY KEY. "CDS view entity component DATA it_elem_11 TYPE TABLE OF zdemo_abap_carr_ve-url WITH EMPTY KEY. ``` |
| Structured types | ``` abap *&---------------------------------------------------------------------* *& Internal tables declared using structured types *&---------------------------------------------------------------------* "Locally declared structured type TYPES: BEGIN OF local_struct, comp1 TYPE i, comp2 TYPE string, comp3 TYPE c LENGTH 3, END OF local_struct. DATA it_struc_1 TYPE SORTED TABLE OF local_struct WITH UNIQUE KEY comp1. "Globally available structured types "E.g. DDIC database tables DATA it_struc_2 TYPE TABLE OF zdemo_abap_fli WITH EMPTY KEY. "CDS objects such as ... "CDS view entity DATA it_struc_3 TYPE TABLE OF zdemo_abap_carr_ve WITH EMPTY KEY. "CDS abstract entity DATA it_struc_4 TYPE TABLE OF zdemo_abap_abstract_ent WITH EMPTY KEY. "CDS table function DATA it_struc_5 TYPE TABLE OF zdemo_abap_table_function WITH EMPTY KEY. "Globally available structured types in the public visibility section of "classes/interfaces DATA it_struc_6 TYPE TABLE OF zcl_demo_abap_amdp=>fli_struc WITH EMPTY KEY. "Many of the previous examples demonstrate flat line types. "Deep line types are also possible, that is, the line type "can include components such as strings, references, and internal "tables. TYPES: BEGIN OF loc_deep_struct, key_field TYPE i, char TYPE c LENGTH 10, str TYPE string, dref TYPE REF TO i, struct TYPE zdemo_abap_flsch, str_tab TYPE string_table, tab TYPE TABLE OF zdemo_abap_flsch WITH EMPTY KEY, END OF loc_deep_struct. DATA it_struc_7 TYPE TABLE OF loc_deep_struct WITH EMPTY KEY. ``` |
| Table types | ``` abap *&---------------------------------------------------------------------* *& Internal tables declared using table types *&---------------------------------------------------------------------* "Locally declared table type (based on a locally declared structured type) TYPES: BEGIN OF loc_struct, comp1 TYPE i, comp2 TYPE string, comp3 TYPE c LENGTH 3, END OF loc_struct, ty_tab_1 TYPE TABLE OF loc_struct WITH EMPTY KEY. DATA it_tab_1 TYPE ty_tab_1. "Locally declared table type (based on a globally available structured type) TYPES ty_tab_2 TYPE TABLE OF zdemo_abap_fli WITH EMPTY KEY. DATA it_tab_2 TYPE ty_tab_2. "Globally available table types "The following examples show released table types. They have an "elementary line type. DATA it_tab_3 TYPE string_table. DATA it_tab_4 TYPE string_hashed_table. DATA it_tab_5 TYPE xstring_table. "Globally available table types in the public visibility section of "classes/interfaces DATA it_tab_6 TYPE zdemo_abap_get_data_itf=>carr_tab. DATA it_tab_7 TYPE zcl_demo_abap_amdp=>flsch_tab. "Creating an internal table based on the table type of an existing "internal table DATA it_tab_8 LIKE it_tab_7. ``` |
| References as line types | ``` abap DATA it_ref_1 TYPE TABLE OF REF TO i. DATA it_ref_2 TYPE TABLE OF REF TO string. DATA it_ref_3 TYPE TABLE OF REF TO zdemo_abap_carr. DATA it_ref_4 TYPE TABLE OF REF TO data. "Such a table can hold any data type it_ref_4 = VALUE #( ( NEW i( 3 ) ) "Elementary type ( NEW string( `hello` ) ) "Elementary type ( NEW zdemo_abap_flsch( carrid = 'XY' connid = '1234' ) ) "Structured type ( NEW string_table( ( `a` ) ( `b` ) ( `c` ) ) ) "Table type ). ``` |
APPEND and INSERT| Subject | Details/Code Snippet |
| Adding a line to an internal table |
The example shows both a structure that is created using the `VALUE` operator as well as an existing structure that is added.
``` abap APPEND VALUE #( comp1 = a comp2 = b ... ) TO itab. APPEND struc TO itab. INSERT VALUE #( comp1 = a comp2 = b ... ) INTO TABLE itab. INSERT struc INTO TABLE itab. ``` |
| Adding an initial line |
... to an internal table without providing any field values.
``` abap APPEND INITIAL LINE TO itab. INSERT INITIAL LINE INTO TABLE itab. ``` |
| Adding a line and assigning the added line to a field symbol or data reference variable |
```abap
"When inserting single lines, you can specify the optional additions
"ASSIGNING and REFERENCE INTO. If the insertion is successful, the
"line is assigned to a field symbol or a data reference variable.
"The targets can also be created inline.
APPEND VALUE #( comp1 = a comp2 = b ... ) TO itab ASSIGNING FIELD-SYMBOL( |
| Adding all lines from another internal table | ``` abap APPEND LINES OF itab2 TO itab. INSERT LINES OF itab2 INTO TABLE itab. ``` |
| Adding multiple lines from another internal table with a specified index range |
- Both `FROM` and `TO` are not mandatory in one statement. it is possible to use only one of them.
- If you use only ...
- `FROM`, all lines up to the last table entry are respected.
- `TO`, all lines starting with the first table entry are respected.
``` abap APPEND LINES OF itab2 FROM 3 TO 5 TO itab. APPEND LINES OF itab2 FROM 3 TO itab. APPEND LINES OF itab2 TO 7 TO itab. INSERT LINES OF itab2 FROM 5 TO 9 INTO TABLE itab. ``` |
| Inserting one line represented by a structure or multiple lines from another internal table at a specific position |
`FROM` and `TO` can be used here, too.
``` abap INSERT struc INTO itab2 INDEX i. INSERT LINES OF itab2 INTO itab INDEX i. ``` |
| Subject | Details/Code Snippet |
| Populating an existing internal table by assigning an internal table that is constructed inline |
In the example below, the internal table is populated by assigning an
internal table that is constructed inline with the `VALUE`
operator. The inline constructed table has two lines. `line`
represents an existing structure with a compatible line type. The
other line is constructed inline.
> [!NOTE]
> - The extra pair of parentheses represents a table line. The `#` character indicates that the line type can be derived from the context. The assignment deletes the existing content of the internal table on the left side.
> - The existing content of the internal table is deleted, and the new content, which is created in place, is added.
``` abap itab = VALUE #( ( line ) ( comp1 = a comp2 = b ... ) ). ``` |
| Creating an internal table by inline declaration and adding lines with a constructor expression | ``` abap "Internal table type TYPES it_type LIKE itab. "Inline declaration "The # character would not be possible here since the line type "cannot be derived from the context. DATA(it_in) = VALUE it_type( ( comp1 = a comp2 = b ... ) ( comp1 = c comp2 = d ... ) ). "Creating string tables DATA(str_tab_a) = VALUE string_table( ( `Hallo` ) ( `World` ) ). DATA(str_tab_b) = VALUE string_table( ). "In the previous statement, the internal table is declared "inline, however, no content, no table lines are provided. "This means that an initial string table was created. This "way, the statement has the same effect as the following "statement. DATA str_tab_c TYPE string_table. ``` |
BASE addition: Adding new lines without deleting existing content |
When you use the above assignments to an existing internal table (`itab = ...`), the internal table is initialized and the existing content is deleted. To add new lines without deleting existing content, use the [`BASE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenvalue_constructor_params_itab.htm) addition.
``` abap itab = VALUE #( BASE itab ( comp1 = a comp2 = b ... ) ( comp1 = c comp2 = d ... ) ). ``` |
LINES OF addition: Adding lines of other tables |
... using the `LINES OF` addition to the `VALUE` operator.
Without the `BASE` addition, the existing content is deleted. It is assumed that the line type of the source table is compatible with that of the target table. You have multiple syntax options following the `LINES OF` addition, e.g. you can further determine and restrict the lines to be added using `FROM` and `TO`.
``` abap itab = VALUE #( ( comp1 = a comp2 = b ...) ( comp1 = a comp2 = b ...) "All lines ( LINES OF itab2 ) "More syntax options ( LINES OF itab3 FROM 2 TO 5 ) ( LINES OF itab4 FROM 3 ) ( LINES OF itab5 TO 7 ) ( LINES OF itab6 STEP 2 ) ( LINES OF itab7 USING KEY primary_key FROM 3 TO 6 ) ... ). ``` |
Iteration expressions with FOR |
Using the `VALUE` operator and iteration expressions with [`FOR`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenfor.htm), you can create content of an internal table by evaluating one or more source tables. The expressions are covered in the [Constructor Expressions](05_Constructor_Expressions.md) cheat sheet.
```abap TYPES ty_int_tab TYPE TABLE OF i WITH EMPTY KEY. DATA(int_table_a) = VALUE ty_int_tab( ( 1 ) ( 2 ) ( 3 ) ( 4 ) ( 5 ) ). DATA int_table_b TYPE ty_int_tab. int_table_b = VALUE #( FOR wa_b IN int_table_a ( wa_b * 2 ) ). "Table Content: 2 / 4 / 6 / 8 / 10 ``` |
| Subject | Details/Code Snippet |
| Copying the content of another (incompatible) internal table |
... using the
[`CORRESPONDING`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenconstructor_expr_corresponding.htm) operator.
- Note that the existing content is deleted.
- As an alternative to the `CORRESPONDING` operator, you can use [`MOVE-CORRESPONDING`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapmove-corresponding.htm) statements.
- The operator is particularly useful for incompatible source and target types. Value assignments are made based on identical components in the source and target. As shown further down, you can also specify mapping rules using the `MAPPING` addition.
- The example assumes that the line types of the source and target table are not compatible. However, if the line types are compatible, the syntax will also work.
- Several additions are possible. They can also be combined. Check the ABAP Keyword Documentation.
``` abap itab = CORRESPONDING #( itab3 ). MOVE-CORRESPONDING itab3 TO itab. ``` |
BASE/KEEPING TARGET LINES additions: Copying content and retaining existing content |
... using the `CORRESPONDING` operator.
The `KEEPING TARGET LINES` addition of the `MOVE-CORRESPONDING` statement preserves the table content.
``` abap itab = CORRESPONDING #( BASE ( itab ) itab3 ). MOVE-CORRESPONDING itab3 TO itab KEEPING TARGET LINES. ``` |
MAPPING addition: Assigning components using mapping relationships |
- You can use the `MAPPING` addition of the `CORRESPONDING` operator to specify components of a source table that are assigned to the components of a target table in mapping relationships.
- For elementary components, the assignment is made according to the associated assignment rules.
``` abap itab = CORRESPONDING #( itab3 MAPPING a = c b = d ). ``` |
EXCEPT addition: Excluding components from the assignment |
... using the `EXCEPT` addition to the `CORRESPONDING` operator.
- This is particularly useful if there are identically named components in the source and target tables that are not compatible or convertible. You can avoid syntax errors or runtime errors.
- Instead of a component list, `EXCEPT` can also be followed by `*` to exclude all components that are not mentioned in a previous mapping of components.
- If `EXCEPT *` is used without the `MAPPING` addition, all components remain initial.
``` abap itab = CORRESPONDING #( itab3 EXCEPT e ). itab = CORRESPONDING #( itab3 EXCEPT * ). ``` |
DISCARDING DUPLICATES addition: Preventing runtime errors when duplicate lines are assigned |
... to the target table that is defined to accept only unique keys using the `DISCARDING DUPLICATES` addition of the `CORRESPONDING` operator.
- In this case, the duplicate line is ignored in the source table.
- The addition can also be specified with `MAPPING ...`.
``` abap itab = CORRESPONDING #( itab2 DISCARDING DUPLICATES ). ``` |
DEEP/EXPANDING NESTED TABLES additions: Copying data from deep internal tables |
- A deep internal table is a table with [deep](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendeep_glosry.htm) line type, which means the table can itself contain internal tables as components, among others.
- The `BASE` addition does not delete the existing content.
- See also the alternative `MOVE-CORRESPONDING` statements that use the `EXPANDING NESTED TABLES` addition.
``` abap itab_nested2 = CORRESPONDING #( DEEP itab_nested1 ). itab_nested2 = CORRESPONDING #( DEEP BASE ( itab_nested2 ) itab_nested1 ). MOVE-CORRESPONDING itab_nested1 TO itab_nested2 EXPANDING NESTED TABLES. MOVE-CORRESPONDING itab_nested1 TO itab_nested2 EXPANDING NESTED TABLES KEEPING TARGET LINES. ``` |
CORRESPONDING with lookup table |
- You can construct an internal table by joining an internal table and a lookup table and comparing their components. - Syntax pattern of the variant: ```abap ... CORRESPONDING type|#( itab FROM lookup_tab USING [KEY key_name] a1 = b1 a2 = b2 ... [MAPPING ...] ) ... ``` - Find more information and code snippets in the [Constructor Expressions](05_Constructor_Expressions.md#corresponding-with-lookup-table) cheat sheet. |
| Target Area | Notes |
| Data object |
- Used to copy a line to a data object using the addition `INTO`.
- After the copying, the line found exists separately in the internal table and in the data object.
- If you change the data object or the table line, the change does not affect the other.
- However, you can modify the copied table line and use a `MODIFY` statement to modify the table based on the modified table line (see below).
- The `TRANSPORTING` addition specifies which components to copy. If it is not specified, all components are respected.
``` abap "dobj must have the table's structure type READ TABLE itab INTO dobj ... READ TABLE itab INTO DATA(dobj_inl) ... READ TABLE itab INTO ... TRANSPORTING comp1 [comp2 ... ]. ``` |
| Field symbol |
- Assigning a line to a [field symbol](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenfield_symbol_glosry.htm "Glossary Entry"),
for example, using an inline declaration (`... ASSIGNING FIELD-SYMBOL( ``` abap "The field symbol must have an appropriate type. READ TABLE itab ASSIGNING |
| Data reference variable |
- Reading a line into a [data reference variable](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendata_reference_variable_glosry.htm "Glossary Entry") using `REFERENCE INTO`.
- In this case, no copying takes place.
- If you want to address the line, you must first [dereference](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendereferencing_operat_glosry.htm) the data reference.
- You cannot use the addition `TRANSPORTING`.
``` abap "The data reference variable must have an appropriate type. READ TABLE itab REFERENCE INTO dref ... "Inline declaration READ TABLE itab REFERENCE INTO DATA(dref_inl) ... ``` |
| Statement | Details/Code Snippet |
READ TABLE |
The following example shows `READ TABLE` statements to read a single line from an internal table by specifying the index. You can use the addition `USING KEY` to specify a table key and thus explicitly determine the table index to use. If the table has a sorted secondary
key, the addition can be specified and the line to be read is then determined from its secondary table index. If the primary table key is
specified by its name `primary_key`, the table must be an index table, and the behavior is the same as if `USING KEY` was
not specified.
Note that the examples only show reading into a work area. Other targets are possible as shown above.
``` abap "Primary table index is used by default READ TABLE itab INTO wa INDEX i. "Primary table index is used, primary key's default name specified explicitly READ TABLE itab INTO wa INDEX i USING KEY primary_key. "Secondary table index is used (assuming a secondary table key sec_key exists) READ TABLE itab INTO wa INDEX i USING KEY sec_key. "Note: You can also use alias names for the keys if specified. ``` |
| Table expressions |
Using [table
expressions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abentable_expressions.htm),
the read result is stored in a variable that can be declared inline.
The number in the square brackets represents the index. A line that is
not found results in an runtime error. To avoid an error, you can
use a [`TRY ... CATCH ... ENDTRY.`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abaptry.htm) block.
Find more information about syntax related to table expressions [further down](#table-expressions).
``` abap "In the examples, integer values are specified for the index. DATA(lv1) = itab[ 1 ]. TRY. DATA(lv2) = itab[ 2 ]. CATCH cx_sy_itab_line_not_found. ... ENDTRY. DATA(lv3) = itab[ KEY primary_key INDEX 3 ]. "Copying a table line via table expression and embedding in constructor expression DATA(lv4) = VALUE #( itab[ 4 ] ). "Reading into data reference variable using the REF operator DATA(lv5_ref) = REF #( itab[ 5 ] ). ``` |
| Avoiding an exception when using table expressions |
When you read a non-existent line using a table expression, you may not want to throw an exception. You can also embed the table expression
in a constructor expression using the `OPTIONAL` addition. This way, an unsuccessful read will not trigger the
exception. The result returned is a line with initial values.
Alternatively, you can use the `DEFAULT` addition to return a
default line in case of an unsuccessful read operation, which can also be another table expression or constructor expression.
``` abap DATA(line1) = VALUE #( itab[ 6 ] OPTIONAL ). DATA(line2) = VALUE #( itab[ 7 ] DEFAULT itab[ 1 ] ). DATA(line3) = VALUE #( itab[ 8 ] DEFAULT VALUE #( ) ). ``` |
| Statement | Details/Code Snippet |
READ TABLE |
``` abap "Example internal table with primary and secondary table key and alias names "Assumption: All components are of type i DATA it TYPE SORTED TABLE OF struc WITH NON-UNIQUE KEY primary_key ALIAS pk COMPONENTS a b WITH NON-UNIQUE SORTED KEY sec_key ALIAS sk COMPONENTS c d. "Primary table key READ TABLE it INTO wa WITH TABLE KEY primary_key COMPONENTS a = 1 b = 2. "Alias READ TABLE it INTO wa WITH TABLE KEY pk COMPONENTS a = 1 b = 2. "Secondary table key READ TABLE it INTO wa WITH TABLE KEY sec_key COMPONENTS c = 3 d = 4. "Alias READ TABLE it INTO wa WITH TABLE KEY sk COMPONENTS c = 3 d = 4. "Reading a line based on keys specified in a work area "Work area containing primary and secondary table key values; the line type "must be compatible to the internal table DATA(pr_keys) = VALUE struc( a = 1 b = 2 ). DATA(sec_keys) = VALUE struc( c = 3 d = 4 ). READ TABLE it FROM pr_keys INTO wa. "If USING KEY is not specified, the primary table key is used. "If it is used, the specified table key is used. READ TABLE it FROM pr_keys USING KEY primary_key INTO wa. READ TABLE it FROM sec_keys USING KEY sec_key INTO wa. "Alias READ TABLE it FROM sec_keys USING KEY sk INTO wa. ``` |
| Table expressions | Find more information about syntax related to table expressions [further down](#table-expressions). ``` abap line = it[ TABLE KEY primary_key COMPONENTS a = 1 b = 2 ]. "The addition COMPONENTS is optional; same as above line = it[ TABLE KEY primary_key a = 1 b = 2 ]. "Primary key alias line = it[ TABLE KEY pk a = 1 b = 2 ]. "Secondary table key line = it[ TABLE KEY sec_key c = 3 d = 4 ]. "Secondary table key alias line = it[ TABLE KEY sk c = 3 d = 4 ]. "Note the section further down about just using KEY (instead of TABLE KEY). ``` |
| Statement | Details/Code Snippet |
READ TABLE |
``` abap "Note: Table keys are specified with the ... WITH TABLE KEY ... addition, "free keys with ... WITH KEY .... READ TABLE it INTO wa WITH KEY b = 2. ``` |
| Table expressions | ``` abap line = it[ b = 2 ]. ``` |
| Subject | Details/Code Snippet |
| Reading table lines by index |
- When only specifying the index number in the square brackets, it means referring to the primary table index.
- In this case, the internal table must be an index table.
- Using the `KEY ... INDEX ...` addition, you can specify the table index explicitly. Either use the predefined name `primary_key` for the primary key explicitly (or an alias name, if specified), or the secondary key name (or an alias name, if specified).
- The `KEY` addition here works like `USING KEY` in `READ TABLE` statements.
- Note that the demo internal tables in the snippet are used in the following examples of the section.
``` abap "Creating and populating demo internal tables "Note: These demo tables are relevant for most of the code snippets "in this section. TYPES: BEGIN OF s_demo, comp1 TYPE i, comp2 TYPE i, comp3 TYPE i, comp4 TYPE c LENGTH 3, END OF s_demo, ttyp TYPE SORTED TABLE OF s_demo WITH UNIQUE KEY comp1 WITH NON-UNIQUE SORTED KEY sk COMPONENTS comp2 comp3, ttyp_hashed TYPE HASHED TABLE OF s_demo WITH UNIQUE KEY comp1 WITH NON-UNIQUE SORTED KEY sk COMPONENTS comp2 comp3, ttyp2 TYPE SORTED TABLE OF s_demo WITH UNIQUE KEY comp1 comp2 WITH NON-UNIQUE SORTED KEY sk COMPONENTS comp3. DATA(itab) = VALUE ttyp( ( comp1 = 1 comp2 = 30 comp3 = 31 comp4 = 'aaa' ) ( comp1 = 2 comp2 = 20 comp3 = 21 comp4 = 'bbb' ) ( comp1 = 3 comp2 = 10 comp3 = 11 comp4 = 'ccc' ) ). DATA itab_hashed TYPE ttyp_hashed. itab_hashed = itab. DATA itab_so TYPE ttyp2. itab_so = itab. DATA line TYPE s_demo. "Reading table line by index "Just specifying the index number means referring to the primary table index. "In this case, the internal table must be an index table. "In the example, the entire table line is assigned to a variable line = itab[ 2 ]. "KEY ... INDEX ... additions "For reading a line according to a table index. "The following example has the same effect as above. Here, the default "name of the primary key is specified explicitly. line = itab[ KEY primary_key INDEX 2 ]. "Secondary table key specified, using secondary table index line = itab[ KEY sk INDEX 1 ]. "This syntax is not possible for hashed tables. "DATA(line_hashed_tab1) = itab_hashed[ 2 ]. "DATA(line_hashed_tab2) = itab_hashed[ KEY primary_key INDEX 2 ]. "Secondary table index access is possible for hashed tables DATA(line_hashed_tab3) = itab_hashed[ KEY sk INDEX 2 ]. ``` |
| Reading table lines by table key |
- `TABLE KEY` addition
- Requires the table key to be fully specified, i.e. all components of the key (primary table key or secondary table key) must be specified, and no other components can be specified.
- Works like the `WITH TABLE KEY` addition in `READ TABLE` statements. However, in table expressions, the `COMPONENTS` addition is optional and the key name must be specified.
- Usually, specifying the primary table key explicitly (using predefined name `primary_key` or an alias, if available) is not required. You can instead also just specify a free key search (i.e. not using any `TABLE KEY`/`KEY` addition) and specify all primary table key components. Then, an optimized search is also performed for sorted and hashed tables.
- `KEY` addition without `TABLE`:
- This syntax option reads a line in accordance with a specified free key.
- It is not mandatory to specify all components of a sorted table key (the initial left part at least is required). The search is then partly optimized (unlike fully optimized when all key components are specified).
- Example purposes of such a specification: Determining the existence of a line, or determining a line number for the starting point for a loop starting at that position.
- Additionally, in case of sorted and secondary table keys, other components not being part of the key can be specified.
- Same as above, specifying the addition `COMPONENTS` is optional.
- Just using `KEY` and specifying all key components following the key name works like specifying `TABLE KEY`. The `TABLE KEY` addition just ensures that indeed all key components are specified.
- Not using any `TABLE KEY`/`KEY` additions:
- In case of sorted and hashed tables and without using any `TABLE KEY`/`KEY` additions, an optimized search is performed when some or all components of the primary table key are specified as free keys.
- Notes:
- Binary searches cannot be enforced with table expressions (unlike `READ TABLE` statements).
- Key names can also be specified dynamically using parentheses `(...)`.
``` abap *&---------------------------------------------------------------------* *& TABLE KEY addition *&---------------------------------------------------------------------* "Explicitly specifying the primary table key line = itab[ TABLE KEY primary_key COMPONENTS comp1 = 1 ]. "The following statement is not possible as no other components can be specified. "line = itab[ TABLE KEY primary_key COMPONENTS comp1 = 1 comp2 = 30 ]. "The addition COMPONENTS is optional; the following example is the same as above line = itab[ TABLE KEY primary_key comp1 = 1 ]. "Specifying a secondary table key line = itab[ TABLE KEY sk COMPONENTS comp2 = 20 comp3 = 21 ]. "Optional COMPONENTS addition line = itab[ TABLE KEY sk comp2 = 20 comp3 = 21 ]. "Fully specifying the table key components is required with TABLE KEY. So, the "following statement is not possible. "line = itab[ TABLE KEY sk comp2 = 20 ]. *&---------------------------------------------------------------------* *& KEY addition *&---------------------------------------------------------------------* "Using KEY and specifying all key components work like specifying TABLE KEY line = itab[ KEY primary_key COMPONENTS comp1 = 1 ]. line = itab[ KEY primary_key comp1 = 1 ]. line = itab[ KEY sk COMPONENTS comp2 = 20 comp3 = 21 ]. line = itab[ KEY sk comp2 = 20 comp3 = 21 ]. "Unlike TABLE KEY, KEY does not enforce all key components to be specified line = itab[ KEY sk comp2 = 20 ]. "In case of sorted and secondary table keys, other components not being part "of the key can be specified line = itab[ KEY primary_key comp1 = 1 comp4 = 'aaa' ]. line = itab[ KEY sk comp2 = 20 comp4 = 'bbb' ]. "The following statements are not possible. The initial, left part of "the key must be specified. In the example case, it is comp2. "line = itab[ KEY sk comp3 = 21 comp4 = 'bbb' ]. "line = itab[ KEY sk comp4 = 'bbb' ]. "The following statement triggers a syntax warning because the initial "part of a table key is specified, but the key name is not specified. "In this case, the search is not optimized as the component is not "part of the primary table key of the sorted table. You may optimize "it by specifying the key. "line = itab[ comp2 = 10 ]. "The syntax warning can be suppressed by a pragma. line = itab[ comp2 = 10 ] ##primkey[sk]. "Specifying the key name line = itab[ KEY sk comp2 = 10 ]. *&---------------------------------------------------------------------* *& No TABLE KEY/KEY additions *&---------------------------------------------------------------------* "Specifying a free key search, but including all components of the primary "table key "For a sorted table as in the example, the search is fully optimized. line = itab[ comp1 = 1 ]. "Partly optimized (only a part of the primary table key of the sorted "example table is specified) line = itab_so[ comp1 = 1 ]. ``` |
| Reading table lines using free keys |
- Free keys are specified without any `... KEY ...` addition. This corresponds to `WITH KEY` specifications in `READ TABLE` statements.
- However, in case of sorted and hashed tables, an optimized search is performed when some or all of the key components are specified as free keys (without any `... KEY ...` addition).
- Note that binary searches cannot be enforced with table expressions (unlike `READ TABLE` statements).
``` abap "The search is and cannot be optimized as the component is not part of "the primary table key of the table. Plus, no appropriate "secondary table key can be applied. line = itab[ comp4 = 'ccc' ]. ``` |
| Using the read result in various positions |
This is to emphasize that table expressions can be used in various read positions. The snippet shows a few examples. Check the notes in the ABAP Keyword Documentation topics about the use.
``` abap DATA(first_line) = itab[ 1 ]. "Using table expressions as arguments of built-in functions IF line_exists( itab[ 1 ] ). ... ELSE. ... ENDIF. ASSERT line_index( itab[ comp4 = 'ccc' ] ) = 3. ``` |
| Assigning table lines to a field symbol |
``` abap
"Works like READ TABLE ... ASSIGNING ...
ASSIGN itab[ 2 ] TO FIELD-SYMBOL( |
| Data reference variables pointing to a table line | ``` abap DATA ref TYPE REF TO data. ref = NEW s_demo( ). ref->* = itab[ 1 ]. ``` |
Specifying table expressions as operands in constructor expressions with VALUE and REF |
``` abap line = VALUE #( itab[ 2 ] ). "Works like READ TABLE ... REFERENCE INTO ... DATA(line_ref) = REF #( itab[ 3 ] ). ``` |
| Specifying a default value for lines that are not found or marking as optional to avoid an exception |
- You can specify default values for lines that are not found to avoid an exception.
- The first example shows catching the execption with a `TRY` control structure.
- The `OPTIONAL` and `DEFAULT` additions can be used in the context of statements using table expressions and constructor expressions (`VALUE` and `REF` are possible).
- When using `OPTIONAL`, the type-specific initial value is set. After the `DEFAULT` addition, a value is expected that is convertible to the target type. You may also specify another table expression for an alternative table line to be searched.
``` abap "Accessing a non-existent table line raises a catchable exception TRY. line = itab[ 4 ]. CATCH cx_sy_itab_line_not_found. ENDTRY. line = VALUE #( itab[ 4 ] OPTIONAL ). line = VALUE #( itab[ 5 ] DEFAULT itab[ 1 ] ). line = VALUE #( itab[ 6 ] DEFAULT VALUE #( ) ). ``` |
| Field symbols and dereferenced data references specified before the square brackets |
The previous examples use concrete internal table names specified before the square brackets. Field symbols and dereferenced data references are also possible.
``` abap ASSIGN itab TO FIELD-SYMBOL( |
| Reading multiple lines |
Using table expressions, you can read entire lines individually. This is just to emphasize that when reading multiple lines sequentially, `LOOP` statements and `FOR` loops are recommended.
``` abap "Instead of something like this ... DO. ASSIGN itab[ sy-index ] TO FIELD-SYMBOL( |
| Reading individual components of table lines | ``` abap "Reading individual components of table lines using chainings after the "closing square bracket "Read component via line read using ... "... index DATA(compa) = itab[ 1 ]-comp1. "... table key DATA(compb) = itab[ TABLE KEY primary_key comp1 = 1 ]-comp2. DATA(compc) = itab[ TABLE KEY sk comp2 = 30 comp3 = 31 ]-comp1. "... free key DATA(compd) = itab[ comp4 = 'ccc' ]-comp1. ``` |
| Chaining table expressions in the context of nested internal tables |
- Table expressions can be chained if the table expression result is a table itself.
- Note the pitfall remarks further down.
``` abap "Creating deep internal table TYPES: BEGIN OF s_sub, comp1 TYPE i, comp2 TYPE i, END OF s_sub, tab_type_sub TYPE TABLE OF s_sub WITH EMPTY KEY, BEGIN OF s, compa TYPE i, compb TYPE TABLE OF tab_type_sub WITH EMPTY KEY, END OF s, tab_type TYPE TABLE OF s WITH EMPTY KEY. "Expressions helpful when populating DATA(deep_tab) = VALUE tab_type( ( compa = 1 compb = VALUE #( ( VALUE #( ( comp1 = 3 comp2 = 4 ) ( comp1 = 5 comp2 = 6 ) ) ) ( VALUE #( ( comp1 = 7 comp2 = 8 ) ( comp1 = 9 comp2 = 10 ) ) ) ) ) ( compa = 2 compb = VALUE #( ( VALUE #( ( comp1 = 11 comp2 = 12 ) ( comp1 = 13 comp2 = 14 ) ) ) ( VALUE #( ( comp1 = 15 comp2 = 16 ) ( comp1 = 17 comp2 = 18 ) ) ) ) ) ). DATA(num1) = deep_tab[ 2 ]-compb[ 1 ][ 2 ]-comp2. ASSERT num1 = 14. "A statement such as the previous one instead of, for example, multiple statements as follows. READ TABLE deep_tab INDEX 2 INTO DATA(wa1). READ TABLE wa1-compb INDEX 1 INTO DATA(wa2). READ TABLE wa2 INTO DATA(wa3) INDEX 2. DATA(num2) = wa3-comp2. ASSERT num2 = num1. ``` |
| Table expression result having a reference type enabling chainings with the object component selector | ``` abap DATA itab_ref TYPE TABLE OF REF TO s_demo WITH EMPTY KEY. itab_ref = VALUE #( ( NEW s_demo( comp1 = 1 comp2 = 30 comp3 = 31 comp4 = 'aaa' ) ) ). "Reading entire line by dereferencing DATA(deref_line) = itab_ref[ 1 ]->*. "Reading component by dereferencing DATA(dref_compa) = itab_ref[ 1 ]->comp3. "The following syntax is also possible (dereferencing operator followed "by the component selector). DATA(dref_compb) = itab_ref[ 1 ]->*-comp4. ``` |
| Table expressions in write positions: Writes on the entire line |
Note that you cannot perform writes on entire lines in the context of key tables as key values cannot be changed.
``` abap "The demo table is a key table. Therefore, writes on entire lines produce runtime errors. "itab[ 3 ] = VALUE #( ). "Creating a standard table DATA itab_std TYPE TABLE OF s_demo WITH NON-UNIQUE KEY comp1 WITH NON-UNIQUE SORTED KEY sk COMPONENTS comp2 comp3. itab_std = itab. "Here, writes on entire lines are allowed. itab_std[ 3 ] = VALUE #( comp1 = 123 comp4 = 'zzz' ). CLEAR itab_std[ 3 ]. ``` |
| Table expressions in write positions: Writes on individual components | ``` abap itab[ 3 ]-comp4 = 'yyy'. itab_ref[ 1 ]->comp3 = 123. "No key value change allowed in key tables "The following statement causes a runtime error. "itab[ 1 ]-comp1 = 987. "Key value change allowed for standard tables. itab_std[ 3 ]-comp1 = 456. ``` |
| Dynamic key and component name specifications |
For more information about dynamic programming, refer to the [Dynamic Programming](06_Dynamic_Programming.md) cheat sheet.
``` abap "Dynamic key and component specifications line = itab[ KEY ('PRIMARY_KEY') COMPONENTS comp1 = 1 ]. line = itab[ KEY ('PRIMARY_KEY') comp1 = 1 ]. line = itab[ KEY ('SK') COMPONENTS comp2 = 20 comp3 = 21 ]. line = itab[ KEY ('SK') comp2 = 20 comp3 = 21 ]. line = itab[ KEY ('PRIMARY_KEY') ('COMP1') = 1 ]. line = itab[ KEY ('SK') ('COMP2') = 20 ('COMP3') = 21 ]. DATA(key_name) = 'PRIMARY_KEY'. DATA(comp_name) = 'COMP1'. line = itab[ KEY (key_name) (comp_name) = 1 ]. line = itab[ KEY primary_key (comp_name) = 1 ]. ``` |
| Pitfalls regarding table expressions |
- The following example emphasizes that table expressions - expression enabling in modern ABAP as such - comes in very handy.
- However, also take the maintainability, debuggability and readbility of your code into consideration.
- The example includes the table expression chaining example from above (that may be fairly hard to understand) and a nonsensical, bad example overusing table expressions (affecting performance).
- Expand the following collapsible section for example code. To try it out, create a demo class named `zcl_demo_abap` and paste the code into it. After activation, choose *F9* in ADT to execute the class. The example is set up to display output in the console.
🟢 Click to expand for example code``` abap CLASS zcl_demo_abap DEFINITION PUBLIC FINAL CREATE PUBLIC . PUBLIC SECTION. INTERFACES if_oo_adt_classrun. PROTECTED SECTION. PRIVATE SECTION. ENDCLASS. CLASS zcl_demo_abap IMPLEMENTATION. METHOD if_oo_adt_classrun~main. "-------------- Chaining table expressions ------------- "Creating a deep internal table TYPES: BEGIN OF s_sub, comp1 TYPE i, comp2 TYPE i, END OF s_sub, tab_type_sub TYPE TABLE OF s_sub WITH EMPTY KEY, BEGIN OF s, compa TYPE i, compb TYPE TABLE OF tab_type_sub WITH EMPTY KEY, END OF s, tab_type TYPE TABLE OF s WITH EMPTY KEY. "Expressions helpful when populating DATA(deep_tab) = VALUE tab_type( ( compa = 1 compb = VALUE #( ( VALUE #( ( comp1 = 3 comp2 = 4 ) ( comp1 = 5 comp2 = 6 ) ) ) ( VALUE #( ( comp1 = 7 comp2 = 8 ) ( comp1 = 9 comp2 = 10 ) ) ) ) ) ( compa = 2 compb = VALUE #( ( VALUE #( ( comp1 = 11 comp2 = 12 ) ( comp1 = 13 comp2 = 14 ) ) ) ( VALUE #( ( comp1 = 15 comp2 = 16 ) ( comp1 = 17 comp2 = 18 ) ) ) ) ) ). "Chained table expressions in the context of reading a value from a "nested internal table "Such a chaining works if the table expression result is a table itself. "Such statements are fairly short, using few lines of code, however, "they may be hard to understand and debug. DATA(num1) = deep_tab[ 2 ]-compb[ 1 ][ 2 ]-comp2. out->write( num1 ). "A statement as above instead of multiple statements, for example, as follows. READ TABLE deep_tab INDEX 2 INTO DATA(wa1). READ TABLE wa1-compb INDEX 1 INTO DATA(wa2). READ TABLE wa2 INTO DATA(wa3) INDEX 2. DATA(num2) = wa3-comp2. out->write( num2 ). "-------------- Overusing table expression ------------- "The following examples performes many reads and writes "using table expressions. The first example includes multiple "table expressions, while the second one is differently designed, "without many table expressions. The runtimes of the loops are "stored, demonstrating that the second example has a significantly "reduced runtime compared to the first example. CONSTANTS: num_of_repetitions TYPE i VALUE 10, num_of_assignment_runs TYPE i VALUE 1000. TYPES: BEGIN OF struct, a TYPE i, b TYPE i, c TYPE i, d TYPE i, e TYPE i, f TYPE i, END OF struct. DATA it TYPE TABLE OF struct WITH EMPTY KEY. it = VALUE #( ( a = 0 b = 0 c = 0 d = 0 e = 0 f = 0 ) ( a = 1 b = 1 c = 1 d = 1 e = 1 f = 1 ) ). DATA(it_original) = it. DATA runtime_tab TYPE TABLE OF decfloat34 WITH EMPTY KEY. DO num_of_repetitions TIMES. DATA(ts1) = utclong_current( ). DO num_of_assignment_runs TIMES. it[ 1 ]-a = sy-index. it[ 1 ]-b = sy-index. it[ 1 ]-c = sy-index. it[ 2 ]-d = sy-index. it[ 2 ]-e = sy-index. it[ 2 ]-f = sy-index. it[ 1 ]-d = it[ 2 ]-d. it[ 1 ]-e = it[ 2 ]-e. it[ 1 ]-f = it[ 2 ]-f. INSERT it[ 1 ] INTO TABLE it. INSERT it[ 2 ] INTO TABLE it. ENDDO. DATA(ts2) = utclong_current( ). cl_abap_utclong=>diff( EXPORTING high = ts2 low = ts1 IMPORTING seconds = DATA(seconds) ). APPEND seconds TO runtime_tab. ENDDO. SORT runtime_tab BY table_line ASCENDING. out->write( `Multiple table expressions, fastest run:` ). out->write( runtime_tab[ 1 ] ). CLEAR runtime_tab. it = it_original. DO num_of_repetitions TIMES. ts1 = utclong_current( ). DO num_of_assignment_runs TIMES. ASSIGN it[ 1 ] TO FIELD-SYMBOL( |
| Subject | Details/Code Snippet |
| Sorting by primary table key | ``` abap "Implicit sorting by primary table key and in ascending order by default SORT itab. "Optional additions to determine the sort order "As mentioned above, ASCENDING is used implicitly. Here, specifying it explicitly. SORT itab ASCENDING. SORT itab DESCENDING. ``` The effect of sorting can have an unexpected result if you use the simple form of the statement and do not explicitly specify the keys. If an internal table has a structured line type and (perhaps inadvertently) the standard key as the primary table key, that is, all character-like and byte-like components make up the primary table key, all these components are taken into account when the table is sorted. ``` abap "Is basically the same as it2 DATA it1 TYPE TABLE OF zdemo_abap_fli. DATA it2 TYPE STANDARD TABLE OF zdemo_abap_fli WITH DEFAULT KEY. "Respecting the standard key when sorting SORT it1. ``` Plus: Suppose there are only elementary numeric components in an internal table with a structured line type. In this case, sorting has no effect because the primary table key is considered empty. This is also applies to tables declared with `EMPTY KEY`. |
| Sorting by explicitly specifying components |
You can sort by any component of the internal table. It is also possible to specify the sort order
(even component-wise). Explicitly specifying the components has the advantage that your code is easier to understand and you can avoid unexpected results if you accidentally use `SORT` without the `BY` addition on empty and standard table keys.
``` abap DATA it3 TYPE TABLE OF struc WITH NON-UNIQUE KEY a. "Sorting by primary table key a SORT itab. "Specifying the component to sort for; here, it is the same as the key; "this way, the sorting is easier to understand SORT itab BY a. "Syntax showing multiple component sorting with component-wise sort order SORT itab BY a b ASCENDING c DESCENDING. "Sorting respecting the entire line (e. g. in the context of tables with "empty or standard keys) SORT itab BY table_line. ``` |
| Stable sorting |
By default, the sorting is unstable concerning preserving the order of table lines with identical sort keys. To ensure a stable sorting with preserving the order of table lines with identical
sort keys, you can use the `STABLE` addition. This code example explores the difference in sorting results when using `STABLE` versus not using it with the `SORT` statement. A `SELECT` statement retrieves data from an internal table, specifying an `ORDER BY` clause for two columns. `SORT` statements sort the internal table. Using `STABLE` demonstrates that the relative order of the columns specified in the `ORDER BY` clause is preserved. Without `STABLE`, this relative order is not necessarily maintained. The `CL_ABAP_DIFF` class is used to compare the internal table content. ``` abap CLASS zcl_demo_abap DEFINITION PUBLIC FINAL CREATE PUBLIC . PUBLIC SECTION. INTERFACES if_oo_adt_classrun. PROTECTED SECTION. PRIVATE SECTION. ENDCLASS. CLASS zcl_demo_abap IMPLEMENTATION. METHOD if_oo_adt_classrun~main. TYPES: BEGIN OF demo_flights, carrid TYPE c LENGTH 3, connid TYPE n LENGTH 4, cityfrom TYPE c LENGTH 20, cityto TYPE c LENGTH 20, END OF demo_flights, ty_flights TYPE TABLE OF demo_flights WITH EMPTY KEY. DATA(itab) = VALUE ty_flights( ( carrid = 'AA' connid = '0017' cityfrom = 'NEW YORK' cityto = 'SAN FRANCISCO' ) ( carrid = 'AA' connid = '0064' cityfrom = 'SAN FRANCISCO' cityto = 'NEW YORK' ) ( carrid = 'AZ' connid = '0555' cityfrom = 'ROME' cityto = 'FRANKFURT' ) ( carrid = 'AZ' connid = '0788' cityfrom = 'ROME' cityto = 'TOKYO' ) ( carrid = 'AZ' connid = '0789' cityfrom = 'TOKYO' cityto = 'ROME' ) ( carrid = 'AZ' connid = '0790' cityfrom = 'ROME' cityto = 'OSAKA' ) ( carrid = 'DL' connid = '0106' cityfrom = 'NEW YORK' cityto = 'FRANKFURT' ) ( carrid = 'DL' connid = '1699' cityfrom = 'NEW YORK' cityto = 'SAN FRANCISCO' ) ( carrid = 'DL' connid = '1984' cityfrom = 'SAN FRANCISCO' cityto = 'NEW YORK' ) ( carrid = 'JL' connid = '0407' cityfrom = 'TOKYO' cityto = 'FRANKFURT' ) ( carrid = 'JL' connid = '0408' cityfrom = 'FRANKFURT' cityto = 'TOKYO' ) ( carrid = 'LH' connid = '0400' cityfrom = 'FRANKFURT' cityto = 'NEW YORK' ) ( carrid = 'LH' connid = '0401' cityfrom = 'NEW YORK' cityto = 'FRANKFURT' ) ( carrid = 'LH' connid = '0402' cityfrom = 'FRANKFURT' cityto = 'NEW YORK' ) ( carrid = 'LH' connid = '2402' cityfrom = 'FRANKFURT' cityto = 'BERLIN' ) ( carrid = 'LH' connid = '2407' cityfrom = 'BERLIN' cityto = 'FRANKFURT' ) ( carrid = 'QF' connid = '0005' cityfrom = 'SINGAPORE' cityto = 'FRANKFURT' ) ( carrid = 'QF' connid = '0006' cityfrom = 'FRANKFURT' cityto = 'SINGAPORE' ) ( carrid = 'SQ' connid = '0988' cityfrom = 'SINGAPORE' cityto = 'TOKYO' ) ( carrid = 'UA' connid = '0941' cityfrom = 'FRANKFURT' cityto = 'SAN FRANCISCO' ) ( carrid = 'UA' connid = '3504' cityfrom = 'SAN FRANCISCO' cityto = 'FRANKFURT' ) ( carrid = 'UA' connid = '3516' cityfrom = 'NEW YORK' cityto = 'FRANKFURT' ) ( carrid = 'UA' connid = '3517' cityfrom = 'FRANKFURT' cityto = 'NEW YORK' ) ). SELECT carrid, connid, cityfrom, cityto FROM @itab AS tab ORDER BY carrid, connid INTO TABLE @DATA(flights). DATA(fl_stable) = flights. DATA(fl_non_stable) = flights. SORT fl_stable STABLE BY cityfrom cityto. SORT fl_non_stable BY cityfrom cityto. DATA is_identical TYPE abap_boolean. DATA(comparison) = cl_abap_diff=>create( ). TRY. DATA(comp_result) = comparison->diff( EXPORTING target = fl_stable source = fl_non_stable IMPORTING flag_identical = is_identical ). IF is_identical = abap_true. out->write( `Comparison result: Identical` ). ELSE. out->write( `Comparison result: Not identical` ). ENDIF. CATCH cx_abap_diff INTO DATA(error). out->write( error->get_text( ) ). ENDTRY. out->write( comp_result ). ENDMETHOD. ENDCLASS. ``` |
Improving Read Performance with Secondary Table Keys
"! ABAP cheat sheet example class
The example class includes several methods that explore both inefficient and potentially more "! efficient code examples affecting performance.
"!In ADT, choose F9 in ADT to run the class.
"! "!Exploring Read Access Performance with Internal Tables
"! ABAP cheat sheet example class
The example class includes several methods that explore both inefficient and potentially more "! efficient code examples affecting performance.
"!In ADT, choose F9 in ADT to run the class.
"! "!