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)
- [Data References](#data-references)
- [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)
- [Getting Type Information at Runtime](#getting-type-information-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
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
"Named, character-like data object specified within parentheses
"used by an ABAP statement
@@ -622,240 +629,600 @@ SORT itab BY (field_name).
"Unnamed, character-like data object specified within parentheses
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.
Some of the following code snippets use artifacts from the cheat sheet repository. The code snippets demonstrate a selection.
- Dynamic specifications in ...
- statements for processing internal tables
### Dynamic ASSIGN Statements
``` abap
"SORT: Dynamically specifying component name to be sorted for
"Populating an internal table
SELECT *
FROM zdemo_abap_carr
INTO TABLE @DATA(itab).
``` abap
"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.
"Named data object specified within parenteses
DATA(field_name) = 'CARRNAME'.
SORT itab BY (field_name).
"------- Specifying the memory area dynamically ------
"I.e. the memory area is not specified directly, but as content of a
"character-like data object in parentheses.
"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.
"Unnamed data object specified within parenteses
SORT itab BY ('CURRCODE').
ASSIGN ('IT') TO <fs>.
ASSIGN ('ST') TO <fs>.
"READ TABLE: Dynamically specifying keys
READ TABLE itab INTO DATA(wa) WITH KEY (field_name) = ...
"Field symbol declared inline
"Note: The typing is performed with the generic type data.
ASSIGN ('DOBJ') TO FIELD-SYMBOL(<fs_inline>).
"MODIFY: Dynamically specifying WHERE conditions
DATA(condition) = `CARRID = 'LH'`.
"The statements set the sy-subrc value. No exception occurs in
"case of an unsuccessful assignment.
ASSIGN ('DOESNOTEXIST') TO <fs>.
IF sy-subrc <> 0.
...
ENDIF.
MODIFY itab FROM ... TRANSPORTING ... WHERE (condition).
"The memory area can also be a dereferenced data reference
ASSIGN dref->* TO <fs>.
"DELETE: Dynamically specifying WHERE conditions
DELETE itab USING KEY ... 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>.
"LOOP: Dynamically specifying keys
DATA(k) = `SOME_KEY`.
"Using a named data object for the component specification
DATA columnname TYPE string VALUE `COL1`.
ASSIGN st-(columnname) TO <fs>.
LOOP AT itab INTO DATA(wa_lo) USING KEY (k).
...
ENDLOOP.
```
"Fully dynamic specification
"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>.
- `ASSIGN` statements
"Numeric expressions are possible. Its value is interpreted
"as the position of the component in the structure.
ASSIGN st-(3) TO <fs>.
``` abap
"Dynamically assigning components of structures
"If the value is 0, the memory area of the entire structure is
"assigned to the field symbol.
ASSIGN st-(0) TO <fs>.
"Populating a structure
SELECT SINGLE *
FROM zdemo_abap_carr
INTO @DATA(wa).
"Declaring a field symbol
FIELD-SYMBOLS <fs> type any.
"The statements above replace the following, older statements.
ASSIGN COMPONENT 'COL1' OF STRUCTURE st TO <fs>.
ASSIGN COMPONENT 3 OF STRUCTURE st TO <fs>.
DATA(comp_name) = 'CARRNAME'.
ASSIGN wa-(comp_name) TO <fs>. "named data object
ASSIGN wa-('CARRID') TO <fs>. "unnamed data object
"The statements set sy-subrc value. No exception occurs in
"case of an unsuccessful assignment.
ASSIGN wa-('XYZ') TO <fs>.
IF sy-subrc <> 0.
...
ENDIF.
"------- Assigning attributes of classes or interfaces dynamically ------
"The following syntax pattern shows the possible specifications.
"clif stands for the name of a class or interface.
"... cref->(attr_name) ...
"... iref->(attr_name) ...
"... (clif_name)=>(attr_name) ...
"... (clif_name)=>attr ...
"... clif=>(attr_name) ...
"Numeric expressions are possible. Its value is interpreted
"as the position of the component in the structure.
ASSIGN wa-(4) TO <fs>.
"Creating an instance of a class
DATA(oref) = NEW zcl_demo_abap_objects( ).
"If the value is 0, the memory area of the entire structure is
"assigned to the field symbol.
ASSIGN wa-(0) TO <fs>.
"Assigning instance attributes using an object reference variable
"All visible attributes of objects can be assigned.
oref->string = `ABAP`. "Assigning a value to the attribute
ASSIGN oref->('STRING') TO <fs>.
"The statements above replace the following, older statements.
ASSIGN COMPONENT 'CARRID' OF STRUCTURE wa TO <fs>.
ASSIGN COMPONENT 5 OF STRUCTURE wa TO <fs>.
"Assigning instance attributes using an interface reference variable
DATA iref TYPE REF TO zdemo_abap_objects_interface.
iref = oref.
ASSIGN iref->('STRING') TO <fs>.
iref->in_str = `hallo`.
ASSIGN iref->('IN_STR') TO <fs>.
"Populating a structure that is referenced by a data reference
"variable
SELECT SINGLE *
FROM zdemo_abap_carr
INTO NEW @DATA(ref_struc).
"Assigning static attributes
"All visible static attributes in classes and interfaces can be assigned
"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>.
"Note the object component selector. The field symbol is created
"inline here.
ASSIGN ref_struc->('CARRNAME') TO FIELD-SYMBOL(<fs_inl>).
"Specifying a class or interface dynamically, and attributes dynamically
ASSIGN ('zcl_demo_abap_objects')=>public_string TO <fs>.
ASSIGN ('zdemo_abap_objects_interface')=>const_intf TO <fs>.
*************************************************************
"Specifying a class or interface as well as attributes dynamically
ASSIGN ('zcl_demo_abap_objects')=>('PUBLIC_STRING') TO <fs>.
ASSIGN ('zdemo_abap_objects_interface')=>('CONST_INTF') TO <fs>.
"Dynamically specifying attributes of classes/interfaces
DATA(cl_name) = 'CL_SOME_CLASS'.
DATA(dobj) = 'SOME_DOBJ'.
"Further dynamic syntax options are possible, for example,
"specifying the memory area after ASSIGN with a writable expressions
"because the operand position after ASSIGN is a result position
ASSIGN NEW zcl_demo_abap_objects( )->('PUBLIC_STRING') TO <fs>.
```
ASSIGN cl_some_class=>(dobj) TO <fs>.
ASSIGN (cl_name)=>some_dobj TO <fs>.
ASSIGN (cl_name)=>(dobj) TO <fs>.
<p align="right"><a href="#top">⬆️ back to top</a></p>
"Class reference variable pointing to an object that contains
"attributes and that are specified dynamically.
DATA cl_ref TYPE REF TO cl_some_class.
cl_ref = NEW #( ).
ASSIGN cl_ref->('SOME_ATTRIBUTE') TO FIELD-SYMBOL(<another_fs>).
### Dynamically Specifying Data Types/Creating (Data) Objects
"If ELSE UNASSIGN is specified, no memory area is assigned to
"the field symbol. It has the state unassigned after the ASSIGN
"statement.
ASSIGN cl_ref->('SOME_ATTRIBUTE') TO FIELD-SYMBOL(<attr>) ELSE UNASSIGN.
```
- 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).
- 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).
- Dynamically specifying data types/creating (data) objects
``` abap
"Anonymous data objects are created using a type determined at
"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').
> **💡 Note**<br>
> - 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).
> - 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).
"Assigning a data object to a field symbol casting a dynamically
"specified type
TYPES clen5 TYPE c LENGTH 5.
DATA: dobj_c10 TYPE c LENGTH 10 VALUE '1234567890',
some_struct TYPE zdemo_abap_fli.
FIELD-SYMBOLS <casttype> TYPE data.
``` abap
"Anonymous data objects are created using a type determined at
"runtime. See more information below. Note that the NEW operator
"cannot be used here.
CREATE DATA dref TYPE (some_type).
CREATE DATA dref TYPE TABLE OF (some_type).
CREATE DATA dref TYPE REF TO (some_type).
ASSIGN dobj_c10 TO <casttype> CASTING TYPE ('CLEN5'). "12345
ASSIGN dobj_c10 TO <casttype> CASTING LIKE some_struct-('CARRID'). "123
"Assigning a data object to a field symbol casting a dynamically
"specified type
ASSIGN dobj TO <fs> CASTING TYPE (some_type).
"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`.
"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 TYPE REF TO object.
CREATE OBJECT oref TYPE (some_class).
"Note: As covered further down and in the executable example,
"CREATE DATA and ASSIGN statements have the HANDLE addition
"after which dynamically created types can be specified. A type
"description object is expected.
"Note: As covered further down and in the executable example,
"CREATE DATA/OBJECT and ASSIGN statements have the HANDLE addition
"after which dynamically created types can be specified. A type
"description object is expected.
CREATE DATA dref TYPE HANDLE type_descr_obj.
CREATE OBJECT oref TYPE HANDLE type_descr_obj.
ASSIGN dobj TO <fs> CASTING TYPE HANDLE type_descr_obj.
```
"Getting type description object
DATA(tdo_elem) = cl_abap_elemdescr=>get_c( 4 ).
CREATE DATA dataref TYPE HANDLE tdo_elem.
dataref->* = dobj_c10. "1234
ASSIGN dobj_c10 TO <casttype> CASTING TYPE HANDLE tdo_elem. "1234
```
- Dynamically specifying clauses in ABAP SQL statements
<p align="right"><a href="#top">⬆️ back to top</a></p>
``` abap
"This snippet demonstrates a selection of possible dynamic
"specifications in ABAP SQL SELECT statements.
"Dynamic SELECT list
### Accessing Structure Components Dynamically
DATA(select_list) = `CARRID, CONNID, COUNTRYFR, COUNTRYTO`.
``` abap
"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` ).
SELECT (select_list)
FROM zdemo_abap_fli
INTO TABLE ...
"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.
"Dynamic FROM clause
"Read position
"The example shows how you can retrieve the textual content of any component
"of any structure.
DATA(content_col2) = CONV string( st-('COL1') ).
DATA(content_col3) = |{ st-('COL3') }|.
DATA content_col1 LIKE st-col1.
content_col1 = st-('COL1').
DATA(table) = `ZDEMO_ABAP_FLI`.
DATA dref_comp TYPE REF TO data.
CREATE DATA dref_comp LIKE st-('COL3').
dref_comp->* = st-('COL3').
SELECT *
"If the component is not found, a catchable exception is raised.
TRY.
DATA(col_not_existent) = |{ st-('COL123') }|.
CATCH cx_sy_assign_illegal_component.
...
ENDTRY.
"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>.
"As in the examples above, specifying components dynamically is possible.
<gen>-('COL2') = `ABAP`.
DATA(gen_comp) = CONV string( <gen>-('COL2') ).
```
<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)
INTO TABLE ...
INTO NEW @DATA(dref_struc).
dref_struc->('CARRID') = 'YZ'.
"Excursion: Dynamic FROM clause and compatible target data object
DATA(db_table) = `ZDEMO_ABAP_CARR`.
INSERT (table) FROM @dref_struc->*.
DATA itab TYPE REF TO data.
CREATE DATA itab TYPE TABLE OF (db_table).
dref_struc->('CURRENCY') = 'EUR'.
UPDATE (table) FROM @dref_struc->*.
SELECT *
FROM (db_table)
INTO TABLE @itab->*.
dref_struc->('SEATSOCC') = 10.
MODIFY (table) FROM @dref_struc->*.
"Similar to the NEW operator, you can use the addition NEW here
"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).
DELETE FROM (table) WHERE (`CARRID = 'YZ'`).
```
"Dynamic WHERE clause
"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'` ) ).
<p align="right"><a href="#top">⬆️ back to top</a></p>
SELECT *
FROM zdemo_abap_fli
WHERE (where_clause)
INTO TABLE ...
```
### Dynamic Invoke
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.
- 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
"Notes:
"- Dynamic method calls require a CALL METHOD statement.
"- The first 3 examples assume that there are no mandatory
" parameters defined for the method.
"- The example covers only static methods. Dynamic method calls
" for instance methods are also possible.
"The following statements are possible for all visible static methods
"Class dynamically specified
CALL METHOD (class)=>meth.
"Class and method dynamically specified
CALL METHOD (class)=>(meth).
"Method dynamically specified
CALL METHOD class=>(meth).
"Assigning actual parameters to the formal parameters statically
CALL METHOD class=>(meth) EXPORTING p1 = a1 p2 = a2 ...
IMPORTING p1 = a1 p2 = a2 ...
"Class dynamically specified
CALL METHOD (class)=>meth.
"Assigning actual parameters to the formal parameters dynamically
DATA ptab TYPE abap_parmbind_tab.
ptab = ...
"Class and method dynamically specified
CALL METHOD (class)=>(meth).
CALL METHOD class=>(meth) PARAMETER-TABLE ptab.
"Assigning actual parameters to the formal parameters statically
CALL METHOD class=>(meth) EXPORTING p1 = a1 p2 = a2 ...
IMPORTING p1 = a1 p2 = a2 ...
"Notes on PARAMETER-TABLE ptab
"- The table (of type abap_parmbind_tab; line type is abap_parmbind)
" 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
DATA ptab TYPE abap_parmbind_tab.
ptab = ...
"Copyable snippet
"Creating an instance by specifying the type statically
"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
"- The table (of type abap_parmbind_tab; line type is abap_parmbind)
" 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.
```
"Creating parameter table
DATA(ptab) = VALUE abap_parmbind_tab( ( name = 'I_OP'
kind = cl_abap_objectdescr=>exporting
value = NEW i( 3 ) )
( name = 'R_TRIPLE'
kind = cl_abap_objectdescr=>returning
value = NEW i( ) ) ).
### 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.
There are several methods for different use cases. See the class documentation (click F2 on the class name in ADT) for more information.