This commit is contained in:
danrega
2023-12-21 15:26:25 +01:00
parent 74d741d698
commit 990647ab77

View File

@@ -8,7 +8,13 @@
- [Field Symbols](#field-symbols) - [Field Symbols](#field-symbols)
- [Data References](#data-references) - [Data References](#data-references)
- [Dynamic ABAP Statements](#dynamic-abap-statements) - [Dynamic ABAP Statements](#dynamic-abap-statements)
- [CL\_ABAP\_DYN\_PRG: Validating Input for Dynamic Specifications](#cl_abap_dyn_prg-validating-input-for-dynamic-specifications) - [Dynamic ASSIGN Statements](#dynamic-assign-statements)
- [Dynamically Specifying Data Types/Creating (Data) Objects](#dynamically-specifying-data-typescreating-data-objects)
- [Accessing Structure Components Dynamically](#accessing-structure-components-dynamically)
- [Dynamic Specifications in Statements for Processing Internal Tables](#dynamic-specifications-in-statements-for-processing-internal-tables)
- [Dynamic ABAP SQL Statements](#dynamic-abap-sql-statements)
- [Dynamic Invoke](#dynamic-invoke)
- [Validating Input for Dynamic Specifications (CL\_ABAP\_DYN\_PRG)](#validating-input-for-dynamic-specifications-cl_abap_dyn_prg)
- [Runtime Type Services (RTTS)](#runtime-type-services-rtts) - [Runtime Type Services (RTTS)](#runtime-type-services-rtts)
- [Getting Type Information at Runtime](#getting-type-information-at-runtime) - [Getting Type Information at Runtime](#getting-type-information-at-runtime)
- [Dynamically Creating Data Types at Runtime](#dynamically-creating-data-types-at-runtime) - [Dynamically Creating Data Types at Runtime](#dynamically-creating-data-types-at-runtime)
@@ -612,7 +618,8 @@ world. Recommended read: [Accessing Data Objects Dynamically (F1 docu for standa
## Dynamic ABAP Statements ## Dynamic ABAP Statements
As already mentioned above, there are ABAP statements that support the dynamic specification of syntax elements. As already mentioned above, there are ABAP statements that support the dynamic specification of syntax elements.
In this context, you can usually use elementary, character-like data objects - the content is usually provided in capital letters - specified within a pair of parentheses. In this context, you can usually use elementary, character-like data objects specified within a pair of parentheses.
For example, `SORT` statements:
``` abap ``` abap
"Named, character-like data object specified within parentheses "Named, character-like data object specified within parentheses
"used by an ABAP statement "used by an ABAP statement
@@ -623,239 +630,599 @@ SORT itab BY (field_name).
SORT itab BY ('CURRCODE'). SORT itab BY ('CURRCODE').
``` ```
In the `SELECT` list of an ABAP SQL `SELECT` statement, for example, you can use a standard table with a character-like row type. The dynamically specified syntax elements can be included as operands in various ABAP statements. The following code snippets are intended to provide a rough overview.
Note that dynamically specifying syntax elements has downsides, too. Consider some erroneous character-like content of such data objects. There is no syntax warning. At runtime, it can lead to runtime errors. Note that dynamically specifying syntax elements has downsides, too. Consider some erroneous character-like content of such data objects. There is no syntax warning. At runtime, it can lead to runtime errors.
Some of the following code snippets use artifacts from the cheat sheet repository. The code snippets demonstrate a selection.
- Dynamic specifications in ... ### Dynamic ASSIGN Statements
- statements for processing internal tables
``` abap ``` abap
"SORT: Dynamically specifying component name to be sorted for "Creating and populating various types/data objects to work with
TYPES: BEGIN OF st_type,
col1 TYPE i,
col2 TYPE string,
col3 TYPE string,
END OF st_type.
DATA st TYPE st_type.
DATA it TYPE TABLE OF st_type WITH EMPTY KEY.
st = VALUE #( col1 = 1 col2 = `aaa` col3 = `Z` ).
APPEND st TO it.
DATA(dref) = NEW st_type( col1 = 2 col2 = `b` col3 = `Y` ).
DATA dobj TYPE string VALUE `hallo`.
"The following examples use a field symbol with generic type
FIELD-SYMBOLS <fs> TYPE data.
"Populating an internal table "------- Specifying the memory area dynamically ------
SELECT * "I.e. the memory area is not specified directly, but as content of a
FROM zdemo_abap_carr "character-like data object in parentheses.
INTO TABLE @DATA(itab). "Note:
"- When specified as unnamed data object, the compiler treats the
" specifications like static assignments. Do not use named data objects
" for ASSIGN statements in ABAP for Cloud Development. It is recommended
" that existing named data objects are put in a structure. Then, the syntax
" for assigning components dynamically can be used so as to avoid a syntax
" warning.
"- Most of the following examples use an unnamed data object.
"- The specification of the name is not case-sensitive.
"Named data object specified within parenteses ASSIGN ('IT') TO <fs>.
DATA(field_name) = 'CARRNAME'. ASSIGN ('ST') TO <fs>.
SORT itab BY (field_name).
"Unnamed data object specified within parenteses "Field symbol declared inline
SORT itab BY ('CURRCODE'). "Note: The typing is performed with the generic type data.
ASSIGN ('DOBJ') TO FIELD-SYMBOL(<fs_inline>).
"READ TABLE: Dynamically specifying keys "The statements set the sy-subrc value. No exception occurs in
READ TABLE itab INTO DATA(wa) WITH KEY (field_name) = ... "case of an unsuccessful assignment.
ASSIGN ('DOESNOTEXIST') TO <fs>.
IF sy-subrc <> 0.
...
ENDIF.
"MODIFY: Dynamically specifying WHERE conditions "The memory area can also be a dereferenced data reference
DATA(condition) = `CARRID = 'LH'`. ASSIGN dref->* TO <fs>.
MODIFY itab FROM ... TRANSPORTING ... WHERE (condition). "------- Assigning components dynamically ------
"You can chain the names with the component selector (-), or, in
"case of reference variables, the object component selector (->).
ASSIGN st-('COL1') TO <fs>.
ASSIGN it[ 1 ]-('COL1') TO <fs>.
ASSIGN dref->('COL1') TO <fs>.
"The following example uses the dereferencing operator explicitly
"followed by the component selector.
ASSIGN dref->*-('COL1') TO <fs>.
"DELETE: Dynamically specifying WHERE conditions "Using a named data object for the component specification
DELETE itab USING KEY ... WHERE (condition). DATA columnname TYPE string VALUE `COL1`.
ASSIGN st-(columnname) TO <fs>.
"LOOP: Dynamically specifying keys "Fully dynamic specification
DATA(k) = `SOME_KEY`. "If the compiler can fully determine the data object in ASSIGN statements
"in ABAP for Cloud Development, a warning is not issued.
ASSIGN ('ST-COL1') TO <fs>.
LOOP AT itab INTO DATA(wa_lo) USING KEY (k). "Numeric expressions are possible. Its value is interpreted
... "as the position of the component in the structure.
ENDLOOP. ASSIGN st-(3) TO <fs>.
```
- `ASSIGN` statements "If the value is 0, the memory area of the entire structure is
"assigned to the field symbol.
ASSIGN st-(0) TO <fs>.
``` abap "The statements above replace the following, older statements.
"Dynamically assigning components of structures ASSIGN COMPONENT 'COL1' OF STRUCTURE st TO <fs>.
ASSIGN COMPONENT 3 OF STRUCTURE st TO <fs>.
"Populating a structure "------- Assigning attributes of classes or interfaces dynamically ------
SELECT SINGLE * "The following syntax pattern shows the possible specifications.
FROM zdemo_abap_carr "clif stands for the name of a class or interface.
INTO @DATA(wa). "... cref->(attr_name) ...
"... iref->(attr_name) ...
"... (clif_name)=>(attr_name) ...
"... (clif_name)=>attr ...
"... clif=>(attr_name) ...
"Declaring a field symbol "Creating an instance of a class
FIELD-SYMBOLS <fs> type any. DATA(oref) = NEW zcl_demo_abap_objects( ).
DATA(comp_name) = 'CARRNAME'. "Assigning instance attributes using an object reference variable
ASSIGN wa-(comp_name) TO <fs>. "named data object "All visible attributes of objects can be assigned.
ASSIGN wa-('CARRID') TO <fs>. "unnamed data object oref->string = `ABAP`. "Assigning a value to the attribute
ASSIGN oref->('STRING') TO <fs>.
"The statements set sy-subrc value. No exception occurs in "Assigning instance attributes using an interface reference variable
"case of an unsuccessful assignment. DATA iref TYPE REF TO zdemo_abap_objects_interface.
ASSIGN wa-('XYZ') TO <fs>. iref = oref.
IF sy-subrc <> 0. ASSIGN iref->('STRING') TO <fs>.
... iref->in_str = `hallo`.
ENDIF. ASSIGN iref->('IN_STR') TO <fs>.
"Numeric expressions are possible. Its value is interpreted "Assigning static attributes
"as the position of the component in the structure. "All visible static attributes in classes and interfaces can be assigned
ASSIGN wa-(4) TO <fs>. "In the following example, a class and an interface is specified statically,
"and the attributes are specified dynamically.
ASSIGN zcl_demo_abap_objects=>('PUBLIC_STRING') TO <fs>.
ASSIGN zdemo_abap_objects_interface=>('CONST_INTF') TO <fs>.
"If the value is 0, the memory area of the entire structure is "Specifying a class or interface dynamically, and attributes dynamically
"assigned to the field symbol. ASSIGN ('zcl_demo_abap_objects')=>public_string TO <fs>.
ASSIGN wa-(0) TO <fs>. ASSIGN ('zdemo_abap_objects_interface')=>const_intf TO <fs>.
"The statements above replace the following, older statements. "Specifying a class or interface as well as attributes dynamically
ASSIGN COMPONENT 'CARRID' OF STRUCTURE wa TO <fs>. ASSIGN ('zcl_demo_abap_objects')=>('PUBLIC_STRING') TO <fs>.
ASSIGN COMPONENT 5 OF STRUCTURE wa TO <fs>. ASSIGN ('zdemo_abap_objects_interface')=>('CONST_INTF') TO <fs>.
"Populating a structure that is referenced by a data reference "Further dynamic syntax options are possible, for example,
"variable "specifying the memory area after ASSIGN with a writable expressions
SELECT SINGLE * "because the operand position after ASSIGN is a result position
FROM zdemo_abap_carr ASSIGN NEW zcl_demo_abap_objects( )->('PUBLIC_STRING') TO <fs>.
INTO NEW @DATA(ref_struc). ```
"Note the object component selector. The field symbol is created <p align="right"><a href="#top">⬆️ back to top</a></p>
"inline here.
ASSIGN ref_struc->('CARRNAME') TO FIELD-SYMBOL(<fs_inl>).
************************************************************* ### Dynamically Specifying Data Types/Creating (Data) Objects
"Dynamically specifying attributes of classes/interfaces - For dynamic syntax elements in `CREATE OBJECT` statements, find more information [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapcreate_object_explicit.htm) (note that parameters can be specified dynamically, too).
DATA(cl_name) = 'CL_SOME_CLASS'. - In addition to character-like data objects for the type name specified in the parentheses, you can also use [absolute type names](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabsolute_typename_glosry.htm) (see the information about RTTI below).
DATA(dobj) = 'SOME_DOBJ'.
ASSIGN cl_some_class=>(dobj) TO <fs>. ``` abap
ASSIGN (cl_name)=>some_dobj TO <fs>. "Anonymous data objects are created using a type determined at
ASSIGN (cl_name)=>(dobj) TO <fs>. "runtime. See more information below. Note that the NEW operator
"cannot be used here.
DATA(some_type) = 'STRING'.
DATA dataref TYPE REF TO data.
CREATE DATA dataref TYPE (some_type).
CREATE DATA dataref TYPE TABLE OF (some_type).
CREATE DATA dataref TYPE REF TO (some_type).
"Using an absolute type name
CREATE DATA dataref TYPE ('\TYPE=STRING').
"Class reference variable pointing to an object that contains "Assigning a data object to a field symbol casting a dynamically
"attributes and that are specified dynamically. "specified type
DATA cl_ref TYPE REF TO cl_some_class. TYPES clen5 TYPE c LENGTH 5.
cl_ref = NEW #( ). DATA: dobj_c10 TYPE c LENGTH 10 VALUE '1234567890',
ASSIGN cl_ref->('SOME_ATTRIBUTE') TO FIELD-SYMBOL(<another_fs>). some_struct TYPE zdemo_abap_fli.
FIELD-SYMBOLS <casttype> TYPE data.
"If ELSE UNASSIGN is specified, no memory area is assigned to ASSIGN dobj_c10 TO <casttype> CASTING TYPE ('CLEN5'). "12345
"the field symbol. It has the state unassigned after the ASSIGN ASSIGN dobj_c10 TO <casttype> CASTING LIKE some_struct-('CARRID'). "123
"statement.
ASSIGN cl_ref->('SOME_ATTRIBUTE') TO FIELD-SYMBOL(<attr>) ELSE UNASSIGN.
```
- Dynamically specifying data types/creating (data) objects "Dynamically creating an object as an instance of a class and
"assigning the reference to the object to an object reference
"variable. oref can be an object or interface reference variable.
"The reference variable is created here with the generic 'object'.
DATA oref_dyn TYPE REF TO object.
CREATE OBJECT oref_dyn TYPE ('ZCL_DEMO_ABAP_OBJECTS').
"Accessing an instance attribute
oref_dyn->('ANOTHER_STRING') = `hi`.
> **💡 Note**<br> "Note: As covered further down and in the executable example,
> - For dynamic syntax elements in `CREATE OBJECT` statements, find more information [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapcreate_object_explicit.htm) (note that parameters can be specified dynamically, too). "CREATE DATA and ASSIGN statements have the HANDLE addition
> - In addition to character-like data objects for the type name specified in the parentheses, you can also use [absolute type names](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabsolute_typename_glosry.htm) (see the information about RTTI below). "after which dynamically created types can be specified. A type
"description object is expected.
``` abap "Getting type description object
"Anonymous data objects are created using a type determined at DATA(tdo_elem) = cl_abap_elemdescr=>get_c( 4 ).
"runtime. See more information below. Note that the NEW operator CREATE DATA dataref TYPE HANDLE tdo_elem.
"cannot be used here. dataref->* = dobj_c10. "1234
CREATE DATA dref TYPE (some_type). ASSIGN dobj_c10 TO <casttype> CASTING TYPE HANDLE tdo_elem. "1234
CREATE DATA dref TYPE TABLE OF (some_type). ```
CREATE DATA dref TYPE REF TO (some_type).
"Assigning a data object to a field symbol casting a dynamically <p align="right"><a href="#top">⬆️ back to top</a></p>
"specified type
ASSIGN dobj TO <fs> CASTING TYPE (some_type).
"Dynamically creating an object as an instance of a class and ### Accessing Structure Components Dynamically
"assigning the reference to the object to an object reference
"variable. oref can be an object or interface reference variable.
"The reference variable is created here with the generic 'object'.
DATA oref TYPE REF TO object.
CREATE OBJECT oref TYPE (some_class).
"Note: As covered further down and in the executable example, ``` abap
"CREATE DATA/OBJECT and ASSIGN statements have the HANDLE addition "Creating and populating various types/data objects to work with
"after which dynamically created types can be specified. A type TYPES: BEGIN OF st_type,
"description object is expected. col1 TYPE i,
CREATE DATA dref TYPE HANDLE type_descr_obj. col2 TYPE string,
CREATE OBJECT oref TYPE HANDLE type_descr_obj. col3 TYPE string,
ASSIGN dobj TO <fs> CASTING TYPE HANDLE type_descr_obj. END OF st_type.
``` DATA st TYPE st_type.
DATA it TYPE TABLE OF st_type WITH EMPTY KEY.
st = VALUE #( col1 = 1 col2 = `aaa` col3 = `Z` ).
APPEND st TO it.
DATA(dref) = NEW st_type( col1 = 2 col2 = `b` col3 = `Y` ).
- Dynamically specifying clauses in ABAP SQL statements "You can achieve the access using ASSIGN statements as shown above, or
"by statically specifying the structure and the (object) component selector
"followed by a character-like data object in parentheses.
"Write position
st-('COL1') = 123.
it[ 1 ]-('COL1') = 456.
dref->('COL1') = 789.
``` abap "Read position
"This snippet demonstrates a selection of possible dynamic "The example shows how you can retrieve the textual content of any component
"specifications in ABAP SQL SELECT statements. "of any structure.
"Dynamic SELECT list DATA(content_col2) = CONV string( st-('COL1') ).
DATA(content_col3) = |{ st-('COL3') }|.
DATA content_col1 LIKE st-col1.
content_col1 = st-('COL1').
DATA(select_list) = `CARRID, CONNID, COUNTRYFR, COUNTRYTO`. DATA dref_comp TYPE REF TO data.
CREATE DATA dref_comp LIKE st-('COL3').
dref_comp->* = st-('COL3').
SELECT (select_list) "If the component is not found, a catchable exception is raised.
FROM zdemo_abap_fli TRY.
INTO TABLE ... DATA(col_not_existent) = |{ st-('COL123') }|.
CATCH cx_sy_assign_illegal_component.
...
ENDTRY.
"Dynamic FROM clause "Accessing components of generic structures dynamically,
"e.g. if you have a method parameter that is typed with the generic type
"data.
"The example uses a field symbol with the generic type data which is assigned
"a structure.
FIELD-SYMBOLS <gen> TYPE data.
ASSIGN st TO <gen>.
DATA(table) = `ZDEMO_ABAP_FLI`. "As in the examples above, specifying components dynamically is possible.
<gen>-('COL2') = `ABAP`.
DATA(gen_comp) = CONV string( <gen>-('COL2') ).
```
SELECT * <p align="right"><a href="#top">⬆️ back to top</a></p>
### Dynamic Specifications in Statements for Processing Internal Tables
```abap
"Creating and populating various types/data objects to work with
TYPES: BEGIN OF demo_struct,
col1 TYPE i,
col2 TYPE string,
col3 TYPE string,
END OF demo_struct.
DATA itab_ek TYPE TABLE OF demo_struct WITH EMPTY KEY.
"Standard table and specification of primary and secondary table key
DATA itab TYPE TABLE OF demo_struct
WITH NON-UNIQUE KEY col1
WITH UNIQUE SORTED KEY sk COMPONENTS col2.
TYPES itab_type LIKE itab.
DATA itab_ref TYPE TABLE OF REF TO demo_struct WITH EMPTY KEY.
itab_ek = VALUE #( ( col1 = 1 col2 = `aaa` col3 = `zzz` )
( col1 = 2 col2 = `bbb` col3 = `yyy` )
( col1 = 3 col2 = `ccc` col3 = `xxx` ) ).
itab = itab_ek.
itab_ref = VALUE #( ( NEW demo_struct( col1 = 1 col2 = `aaa` col3 = `zzz` ) ) ).
"Notes
"- In statements using key specifications, secondary table key names (or alias names)
" are usually specified. Also the primary table key using the predefined name
" primary_key or its alias name can be used.
"- Many of the following statements provide similar additions offering dynamic
" specifications, such as USING KEY and dynamic component name specifications.
"------- SORT ------
"Named data object specified within parenteses
DATA(field_name) = 'COL1'.
SORT itab_ek BY (field_name) DESCENDING.
"Unnamed data object specified within parenteses
SORT itab_ek BY ('COL2') ASCENDING.
"------- READ TABLE ------
"Reading by specifying keys dynamically
"Implicitly specifying the table key values in a work area (USING KEY addition)
DATA(wa_read) = VALUE demo_struct( col2 = `aaa` ).
READ TABLE itab FROM wa_read USING KEY ('SK') REFERENCE INTO DATA(read_ref).
"Explicitly specifying the key and key values (TABLE KEY addition)
"The component names can also be specified dynamically (which is done in most of the
"following examples for demonstration purposes).
READ TABLE itab WITH TABLE KEY ('SK') COMPONENTS ('COL2') = `aaa` REFERENCE INTO read_ref.
"Specifying the predefined name primary_key explicitly
READ TABLE itab WITH TABLE KEY ('PRIMARY_KEY') COMPONENTS ('COL1') = 1 REFERENCE INTO read_ref.
"If the addition COMPONENTS is not specified, the primary table key is used by default.
READ TABLE itab WITH TABLE KEY ('COL1') = 1 REFERENCE INTO read_ref.
"Reading using a free key (WITH KEY addition)
READ TABLE itab WITH KEY ('COL3') = `yyy` REFERENCE INTO read_ref.
"The addition can also be used by specifying a secondary table key name
READ TABLE itab WITH KEY ('SK') COMPONENTS ('COL2') = `ccc` REFERENCE INTO read_ref.
"Reading based on a table index (INDEX addition)
"Not using the addition USING KEY means reading from the primary table index.
READ TABLE itab INDEX 1 USING KEY ('SK') REFERENCE INTO read_ref.
"More dynamic specification options when specifying the target as work area
"(COMPARING/TRANSPORTING additions)
"TRANSPORTING: Specifying which components shall be respected
READ TABLE itab INDEX 1 INTO DATA(workarea) TRANSPORTING ('COL1') ('COL3').
"COMPARING: If the content of the compared components is identical, sy-subrc is set
"to 0, and otherwise to 2. The line found is assigned to the work area independently
"of the result of the comparison.
workarea-('COL3') = `uvw`.
READ TABLE itab INDEX 1 INTO workarea COMPARING ('COL3') TRANSPORTING ('COL1') ('COL3').
IF sy-subrc <> 0.
...
ENDIF.
"------- Table expressions ------
"Similar to READ TABLE statements, you can specify table lines with 3 alternatives:
"index read, read using free key, table key
"Also there, dynamic specification are possible regarding the key specifications.
"Reading based on index with dynamic key specifications
"Specifying the secondary table index of a sorted secondary key
DATA(wa_te1) = itab[ KEY ('SK') INDEX 1 ].
"Reading using a free key, the keys are specified dynamically
DATA(wa_te2) = itab[ ('COL2') = `bbb` ('COL3') = `yyy` ].
"Reading using a table key
"Specyfing the table key explicitly
"Note: Unlike READ TABLE statements, the name of the table key must be specified. The
"addition COMPONENTS can be omitted.
"In the following example, the component names are also specified dynamically.
DATA(wa_te3) = itab[ KEY ('SK') ('COL2') = `ccc` ].
"Specifying the COMPONENTS addition explicitly
DATA(wa_te4) = itab[ KEY ('primary_key') COMPONENTS ('col1') = 1 ].
"Accessing components
"As shown abobe, chaininings with the (object) component selector are possible.
"The examples use index access and write positions.
itab[ 1 ]-('COL2') = `jkl`.
itab_ref[ 1 ]->('COL2') = `mno`.
"------- LOOP AT ------
"USING KEY addition: Overriding the standard order determined by the table category
LOOP AT itab REFERENCE INTO DATA(ref) USING KEY ('SK').
...
ENDLOOP.
"When the primary table key is specified, the loop behaves as if it was not specified.
"So, the following statement corresponds to the one below.
LOOP AT itab REFERENCE INTO ref USING KEY ('PRIMARY_KEY').
...
ENDLOOP.
LOOP AT itab REFERENCE INTO ref.
...
ENDLOOP.
"Dynamic WHERE condition
"You can specify a character-like data object or a standard table with character-like
"line type.
DATA(cond_loop) = `COL1 > 1`.
LOOP AT itab REFERENCE INTO ref WHERE (cond_loop).
...
ENDLOOP.
"------- INSERT ------
"The USING KEY addition (which accepts a dynamic specification) affects the order in which lines are inserted.
"Result of the following example when using the ...
"- secondary table key: order of itab entries 5 ... /4 ... /...
"- primary table key: order of itab entries 4 ... /5 ... /...
INSERT LINES OF VALUE itab_type( ( col1 = 4 col2 = `eee` col3 = `www` )
( col1 = 5 col2 = `ddd` col3 = `vvv` ) )
USING KEY ('SK')
"USING KEY ('PRIMARY_KEY')
INTO itab INDEX 1.
"Excursion: Taking up the LOOP AT statements with the USING KEY addition
"and exploring the table index
"Declaring demo tables to hold the internal table entries
DATA it_seckey_idx TYPE TABLE OF demo_struct WITH EMPTY KEY.
DATA it_primekey_idx LIKE it_seckey_idx.
"Visualizing the secondary table index
LOOP AT itab INTO DATA(wa_sk) USING KEY ('SK').
APPEND wa_sk TO it_seckey_idx.
ENDLOOP.
"Visualizing the primary table index
LOOP AT itab INTO DATA(wa_pk) USING KEY ('PRIMARY_KEY').
APPEND wa_pk TO it_primekey_idx.
ENDLOOP.
"------- MODIFY ------
"specified using a table key or a table index.
"the statement MODIFY assigns the content of
"In the following example, a line is modified based on a work area and a table key.
"The component col1 is left out from the work area intentionally.
"If the primary table key was used, the value of sy-subrc would be 4, and no modification was done.
"The optional addition transporting is specified to denote what should be modified. In this example,
"the component is also specified dynamically.
MODIFY TABLE itab FROM VALUE #( col2 = `bbb` col3 = `uuu` )
USING KEY ('SK')
TRANSPORTING ('COL3').
"In the following example, a line is modified based on a work area, an index specification and a
"table key.
"INDEX can also be positioned after FROM.
MODIFY itab INDEX 2 USING KEY ('SK')
FROM VALUE #( col3 = `ttt` )
TRANSPORTING ('COL3').
"Dynamic WHERE clause (only to be used with the TRANSPORTING addition)
"The USING KEY addition is also possible. Check the ABAP Keyword Documentation
"for special rules that apply.
DATA(cond_mod) = `COL1 < 3`.
MODIFY itab FROM VALUE #( col3 = `sss` )
TRANSPORTING ('COL3')
WHERE (cond_mod).
"------- DELETE ------
"A single line or multipled lines can be deleted.
"Note that DELETE ADJACENT DUPLICATES statements can also be specified using
"dynamic parts.
"Deleting based on a dynamically specified table key
"The values can be declared either implicitly in a work area after FROM or explicitly
"by listing the components of the table key after TABLE KEY.
"If the USING KEY addition is not specified, the primary table key is used by default.
DELETE TABLE itab FROM VALUE #( col2 = `eee` col3 = `www` )
USING KEY ('SK').
"Each component of the table key must be listed.
DELETE TABLE itab WITH TABLE KEY ('SK')
COMPONENTS ('COL2') = `ddd`.
"Deleting based on the table index
DELETE itab INDEX 1 USING KEY ('SK').
"Deleting multiple lines and specifying the WHERE conditions dynamically
"The USING KEY addition is also possible.
DATA(condition_tab) = VALUE string_table( ( `COL1 < 3` )
( `OR` )
( `COL3 = ``www``` ) ).
DELETE itab WHERE (condition_tab).
```
<p align="right"><a href="#top">⬆️ back to top</a></p>
### Dynamic ABAP SQL Statements
```
"Dynamic SELECT list
DATA(select_list) = `CARRID, CONNID, FLDATE`.
DATA fli_tab TYPE TABLE OF zdemo_abap_fli WITH EMPTY KEY.
SELECT (select_list)
FROM zdemo_abap_fli
INTO CORRESPONDING FIELDS OF TABLE @fli_tab.
"Dynamic FROM clause
DATA(table) = 'ZDEMO_ABAP_FLI'.
SELECT *
FROM (table)
INTO TABLE @fli_tab.
"Excursion: Compatible target data objects
"In the examples above, the data object/type was created statically.
"Creating an anonymous data object with a CREATE DATA statement
"and specifiying the type dynamically.
"You can use the dereferenced object reference variable as target.
DATA itab_dyn TYPE REF TO data.
CREATE DATA itab_dyn TYPE TABLE OF (table).
SELECT *
FROM (table)
INTO TABLE @itab_dyn->*.
"In older ABAP code, you may find assignments to a field symbol
"due to the reasons mentioned above.
FIELD-SYMBOLS <tab> TYPE ANY TABLE.
ASSIGN itab_dyn->* TO <tab>.
SELECT *
FROM (table)
INTO TABLE @<tab>.
"Similar to the NEW operator, you can use the addition NEW
"to create an anonymous data object in place. The advantage is
"that the data type is constructed in a suitable way.
SELECT *
FROM (table)
INTO TABLE NEW @DATA(dref_tab).
"Dynamic WHERE clause
"The example includes a WHERE clause that is created as an internal
"table with a character-like row type.
DATA(where_clause) = VALUE string_table( ( `CARRID = 'LH'` )
( `OR` )
( `CARRID = 'AA'` ) ).
SELECT *
FROM zdemo_abap_fli
WHERE (where_clause)
INTO TABLE NEW @DATA(tab_dyn_where).
"Further dynamic specifications in other ABAP SQL statements
"Creating a structure to be inserted into the database table
SELECT SINGLE *
FROM (table) FROM (table)
INTO TABLE ... INTO NEW @DATA(dref_struc).
dref_struc->('CARRID') = 'YZ'.
"Excursion: Dynamic FROM clause and compatible target data object INSERT (table) FROM @dref_struc->*.
DATA(db_table) = `ZDEMO_ABAP_CARR`.
DATA itab TYPE REF TO data. dref_struc->('CURRENCY') = 'EUR'.
CREATE DATA itab TYPE TABLE OF (db_table). UPDATE (table) FROM @dref_struc->*.
SELECT * dref_struc->('SEATSOCC') = 10.
FROM (db_table) MODIFY (table) FROM @dref_struc->*.
INTO TABLE @itab->*.
"Similar to the NEW operator, you can use the addition NEW here DELETE FROM (table) WHERE (`CARRID = 'YZ'`).
"to create an anonymous data object in place. The advantage is ```
"that the data type is constructed in a suitable way.
SELECT *
FROM (db_table)
INTO TABLE NEW @DATA(dref_tab).
"Dynamic WHERE clause <p align="right"><a href="#top">⬆️ back to top</a></p>
"This is an example for using an internal table with a
"character-like row type
DATA(where_clause) = VALUE string_table( ( `CARRID = 'LH'` )
( `OR CARRID = 'AA'` ) ).
SELECT * ### Dynamic Invoke
FROM zdemo_abap_fli The following code snippet shows dynamically specifying [procedure](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenprocedure_glosry.htm "Glossary Entry") calls.
WHERE (where_clause)
INTO TABLE ...
```
- Dynamic invoke: Dynamically specifying [procedure](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenprocedure_glosry.htm "Glossary Entry") calls ``` abap
"Note: Dynamic method calls require a CALL METHOD statement.
"The following examples assume that there are no mandatory
"parameters defined for the method.
"Possible for methods of the same class, works like me->(meth)
CALL METHOD (meth).
"Class specified statically
CALL METHOD class=>(meth).
"Object reference variable specified statically;
"also possible for interface reference variables
CALL METHOD oref->(meth).
``` abap "The following statements are possible for all visible static methods
"Notes: "Class dynamically specified
"- Dynamic method calls require a CALL METHOD statement. CALL METHOD (class)=>meth.
"- The first 3 examples assume that there are no mandatory "Class and method dynamically specified
" parameters defined for the method. CALL METHOD (class)=>(meth).
"- The example covers only static methods. Dynamic method calls
" for instance methods are also possible.
"Method dynamically specified "Assigning actual parameters to the formal parameters statically
CALL METHOD class=>(meth). CALL METHOD class=>(meth) EXPORTING p1 = a1 p2 = a2 ...
IMPORTING p1 = a1 p2 = a2 ...
"Class dynamically specified "Assigning actual parameters to the formal parameters dynamically
CALL METHOD (class)=>meth. DATA ptab TYPE abap_parmbind_tab.
ptab = ...
"Class and method dynamically specified CALL METHOD class=>(meth) PARAMETER-TABLE ptab.
CALL METHOD (class)=>(meth).
"Assigning actual parameters to the formal parameters statically "Notes on PARAMETER-TABLE ptab
CALL METHOD class=>(meth) EXPORTING p1 = a1 p2 = a2 ... "- The table (of type abap_parmbind_tab; line type is abap_parmbind)
IMPORTING p1 = a1 p2 = a2 ... " must be filled and have a line for all non-optional parameters.
"- Components: name -> formal parameter name
" kind -> kind of parameter, e. g. importing
" value -> pointer to appropriate actual parameter,
" is of type REF TO data
"The addition EXCEPTION-TABLE for exceptions is not dealt with here.
"Assigning actual parameters to the formal parameters dynamically "Copyable snippet
DATA ptab TYPE abap_parmbind_tab. "Creating an instance by specifying the type statically
ptab = ... "An example class of the cheat sheet repository is used.
DATA(ob_ref) = NEW zcl_demo_abap_objects( ).
"Calling an instance method
"The method multiplies an integer by 3.
"The calculation result is returned.
DATA(result) = ob_ref->triple( i_op = 2 ). "6
CALL METHOD class=>(meth) PARAMETER-TABLE ptab. "Dynamic equivalent
"Creating an instance of a class by specifying the type
"dynamically
DATA objref TYPE REF TO object.
CREATE OBJECT objref TYPE ('ZCL_DEMO_ABAP_OBJECTS').
"Notes on PARAMETER-TABLE ptab "Creating parameter table
"- The table (of type abap_parmbind_tab; line type is abap_parmbind) DATA(ptab) = VALUE abap_parmbind_tab( ( name = 'I_OP'
" must be filled and have a line for all non-optional parameters. kind = cl_abap_objectdescr=>exporting
"- Components: name -> formal parameter name value = NEW i( 3 ) )
" kind -> kind of parameter, e. g. importing ( name = 'R_TRIPLE'
" value -> pointer to appropriate actual parameter, kind = cl_abap_objectdescr=>returning
" is of type REF TO data value = NEW i( ) ) ).
"The addition EXCEPTION-TABLE for exceptions is not dealt with here.
```
### CL_ABAP_DYN_PRG: Validating Input for Dynamic Specifications "Dynamic method call and specifying a parameter table
CALL METHOD objref->('TRIPLE') PARAMETER-TABLE ptab.
result = ptab[ name = 'R_TRIPLE' ]-('VALUE')->*. "9
```
<p align="right"><a href="#top">⬆️ back to top</a></p>
### Validating Input for Dynamic Specifications (CL_ABAP_DYN_PRG)
You can use the `CL_ABAP_DYN_PRG` class to validate input for dynamic specifications. You can use the `CL_ABAP_DYN_PRG` class to validate input for dynamic specifications.
There are several methods for different use cases. See the class documentation (click F2 on the class name in ADT) for more information. There are several methods for different use cases. See the class documentation (click F2 on the class name in ADT) for more information.