Update
This commit is contained in:
@@ -153,18 +153,18 @@ ASSIGN num TO FIELD-SYMBOL(<fs_inl>).
|
|||||||
TYPES c_len_3 TYPE c LENGTH 3.
|
TYPES c_len_3 TYPE c LENGTH 3.
|
||||||
DATA(chars) = 'abcdefg'.
|
DATA(chars) = 'abcdefg'.
|
||||||
|
|
||||||
FIELD-SYMBOLS <fs1> TYPE c_len_3.
|
FIELD-SYMBOLS <fs1> TYPE c_len_3.
|
||||||
|
|
||||||
"Implicit casting
|
"Implicit casting
|
||||||
ASSIGN chars TO <fs1> CASTING.
|
ASSIGN chars TO <fs1> CASTING. "abc
|
||||||
|
|
||||||
FIELD-SYMBOLS <fs2> TYPE data.
|
FIELD-SYMBOLS <fs2> TYPE data.
|
||||||
|
|
||||||
"Explicit casting
|
"Explicit casting
|
||||||
ASSIGN chars TO <fs2> CASTING TYPE c_len_3.
|
ASSIGN chars TO <fs2> CASTING TYPE c_len_3. "abc
|
||||||
|
|
||||||
DATA chars_l4 TYPE c LENGTH 4.
|
DATA chars_l4 TYPE c LENGTH 4.
|
||||||
ASSIGN chars TO <fs2> CASTING LIKE chars_l4.
|
ASSIGN chars TO <fs2> CASTING LIKE chars_l4. "abcd
|
||||||
```
|
```
|
||||||
|
|
||||||
> **💡 Note**<br>
|
> **💡 Note**<br>
|
||||||
@@ -210,7 +210,8 @@ LOOP AT itab ASSIGNING <fs1>.
|
|||||||
...
|
...
|
||||||
ENDLOOP.
|
ENDLOOP.
|
||||||
|
|
||||||
"Inline declaration of a field symbol. It receives a suitable
|
"Inline declaration of a field symbol. The field symbol is implcitly typed
|
||||||
|
"with the generic type data.
|
||||||
"type automatically.
|
"type automatically.
|
||||||
LOOP AT itab ASSIGNING FIELD-SYMBOL(<fs2>).
|
LOOP AT itab ASSIGNING FIELD-SYMBOL(<fs2>).
|
||||||
<fs2>-carrid = ...
|
<fs2>-carrid = ...
|
||||||
@@ -686,7 +687,7 @@ ASSIGN ('DOBJ') TO FIELD-SYMBOL(<fs_inline>).
|
|||||||
|
|
||||||
"The statements set the sy-subrc value. No exception occurs in
|
"The statements set the sy-subrc value. No exception occurs in
|
||||||
"case of an unsuccessful assignment.
|
"case of an unsuccessful assignment.
|
||||||
ASSIGN ('DOESNOTEXIST') TO <fs>.
|
ASSIGN ('DOES_NOT_EXIST') TO <fs>.
|
||||||
IF sy-subrc <> 0.
|
IF sy-subrc <> 0.
|
||||||
...
|
...
|
||||||
ENDIF.
|
ENDIF.
|
||||||
@@ -893,8 +894,8 @@ DATA(gen_comp) = CONV string( <gen>-('COL2') ).
|
|||||||
"has a generic type. The components of the structure are accessed dynamically in
|
"has a generic type. The components of the structure are accessed dynamically in
|
||||||
"a DO loop. The sy-index value is interpreted as the position of the component
|
"a DO loop. The sy-index value is interpreted as the position of the component
|
||||||
"in the structure. Plus, using RTTI - as also shown further down - the component
|
"in the structure. Plus, using RTTI - as also shown further down - the component
|
||||||
"name is retrieved. Component names and the values are added to a string. As a
|
"names are retrieved. Component names and the values are added to a string. As a
|
||||||
"prerequisite, all component values can be converted to type string.
|
"prerequisite, all component values must be convertible to type string.
|
||||||
DATA struc2string TYPE string.
|
DATA struc2string TYPE string.
|
||||||
FIELD-SYMBOLS <strco> TYPE data.
|
FIELD-SYMBOLS <strco> TYPE data.
|
||||||
ASSIGN st TO <strco>.
|
ASSIGN st TO <strco>.
|
||||||
@@ -998,7 +999,7 @@ ENDIF.
|
|||||||
"------- Table expressions ------
|
"------- Table expressions ------
|
||||||
"Similar to READ TABLE statements, you can specify table lines with 3 alternatives:
|
"Similar to READ TABLE statements, you can specify table lines with 3 alternatives:
|
||||||
"index read, read using free key, table key
|
"index read, read using free key, table key
|
||||||
"Also there, dynamic specification are possible regarding the key specifications.
|
"Also there, dynamic specifications are possible regarding the key specifications.
|
||||||
|
|
||||||
"Reading based on index with dynamic key specifications
|
"Reading based on index with dynamic key specifications
|
||||||
"Specifying the secondary table index of a sorted secondary key
|
"Specifying the secondary table index of a sorted secondary key
|
||||||
@@ -1137,7 +1138,7 @@ SELECT *
|
|||||||
INTO TABLE @fli_tab.
|
INTO TABLE @fli_tab.
|
||||||
|
|
||||||
"Excursion: Compatible target data objects
|
"Excursion: Compatible target data objects
|
||||||
"In the examples above, the data object/type was created statically.
|
"In the examples above, the data object/type is created statically.
|
||||||
|
|
||||||
"Creating an anonymous data object with a CREATE DATA statement
|
"Creating an anonymous data object with a CREATE DATA statement
|
||||||
"and specifiying the type dynamically.
|
"and specifiying the type dynamically.
|
||||||
@@ -1177,6 +1178,19 @@ SELECT *
|
|||||||
WHERE (where_clause)
|
WHERE (where_clause)
|
||||||
INTO TABLE NEW @DATA(tab_dyn_where).
|
INTO TABLE NEW @DATA(tab_dyn_where).
|
||||||
|
|
||||||
|
"Dynamic ORDER BY clause
|
||||||
|
SELECT *
|
||||||
|
FROM zdemo_abap_fli
|
||||||
|
ORDER BY (`FLDATE`)
|
||||||
|
INTO TABLE NEW @DATA(tab_dyn_order).
|
||||||
|
|
||||||
|
"SELECT statement with miscellaneous dynamic specifications
|
||||||
|
SELECT (`CARRID, CONNID, FLDATE`)
|
||||||
|
FROM (`ZDEMO_ABAP_FLI`)
|
||||||
|
WHERE (`CARRID <> ``AA```)
|
||||||
|
ORDER BY (`FLDATE`)
|
||||||
|
INTO TABLE NEW @DATA(tab_dyn_misc).
|
||||||
|
|
||||||
"Further dynamic specifications in other ABAP SQL statements
|
"Further dynamic specifications in other ABAP SQL statements
|
||||||
"Creating a structure to be inserted into the database table
|
"Creating a structure to be inserted into the database table
|
||||||
SELECT SINGLE *
|
SELECT SINGLE *
|
||||||
@@ -1197,6 +1211,154 @@ DELETE FROM (table) WHERE (`CARRID = 'YZ'`).
|
|||||||
|
|
||||||
<p align="right"><a href="#top">⬆️ back to top</a></p>
|
<p align="right"><a href="#top">⬆️ back to top</a></p>
|
||||||
|
|
||||||
|
**Excursion**: To take up the use case mentioned in the introduction about retrieving the content of a database table, storing it in an internal table, and
|
||||||
|
displaying it when the database table name is specified dynamically at
|
||||||
|
runtime, see the following code snippet. Note the comments.
|
||||||
|
|
||||||
|
|
||||||
|
```abap
|
||||||
|
CLASS zcl_example_class DEFINITION
|
||||||
|
PUBLIC
|
||||||
|
FINAL
|
||||||
|
CREATE PUBLIC .
|
||||||
|
|
||||||
|
PUBLIC SECTION.
|
||||||
|
INTERFACES if_oo_adt_classrun.
|
||||||
|
PROTECTED SECTION.
|
||||||
|
PRIVATE SECTION.
|
||||||
|
ENDCLASS.
|
||||||
|
CLASS zcl_example_class IMPLEMENTATION.
|
||||||
|
METHOD if_oo_adt_classrun~main.
|
||||||
|
"The example retrieves the content of a database table, storing it in an
|
||||||
|
"internal table, and displaying it when the database table name is
|
||||||
|
"specified dynamically at runtime.
|
||||||
|
"Certainly, there are quite some ways to achieve it, and that work out
|
||||||
|
"of the box. For example, in ABAP for Cloud Development, you can implement
|
||||||
|
"the classrun if_oo_adt_classrun and output content using the out->write(...)
|
||||||
|
"method. You can also inherit from cl_demo_classrun in your class. In
|
||||||
|
"classic ABAP, you can, for example and additionally, use cl_demo_output or
|
||||||
|
"ALV.
|
||||||
|
"Notes:
|
||||||
|
"- The following example is just ABAP code tinkering with dynamic programming
|
||||||
|
" aspects. Note the disclaimer in the README of the cheat sheet repository.
|
||||||
|
" It is an example that sets its focus on a dynamic SELECT statement and
|
||||||
|
" processing internal tablecontent by dynamically accessing structure
|
||||||
|
" components.
|
||||||
|
"- The ways mentioned above are way more powerful (e.g. in most cases also
|
||||||
|
" nested and deep data objects can be displayed for demo purposes).
|
||||||
|
"- For simplicity, column contents are converted to string here if necessary,
|
||||||
|
" i.e. all column contents must be convertible to string.
|
||||||
|
"- For display purposes, the snippet uses the classrun methods to display
|
||||||
|
" results sequentially - instead of displaying the internal table
|
||||||
|
" content retrieved by the SELECT statement directly.
|
||||||
|
"- The example uses database tables from the cheat sheet repository. To fill
|
||||||
|
" them, you can use the method call zcl_demo_abap_aux=>fill_dbtabs( )..
|
||||||
|
zcl_demo_abap_aux=>fill_dbtabs( ).
|
||||||
|
|
||||||
|
"Data objects and types relevant for the example (length and offset for
|
||||||
|
"content display)
|
||||||
|
DATA str TYPE string.
|
||||||
|
TYPES: BEGIN OF comp_struc,
|
||||||
|
name TYPE string,
|
||||||
|
len TYPE i,
|
||||||
|
off TYPE i,
|
||||||
|
END OF comp_struc.
|
||||||
|
DATA it_comps TYPE TABLE OF comp_struc WITH EMPTY KEY.
|
||||||
|
|
||||||
|
"Database table of type string containing names of database tables;
|
||||||
|
"table is looped over to output content of all database tables
|
||||||
|
DATA(dbtabs) = VALUE string_table( ( `ZDEMO_ABAP_CARR` )
|
||||||
|
( `ZDEMO_ABAP_FLI` )
|
||||||
|
( `ZDEMO_ABAP_FLSCH` ) ).
|
||||||
|
|
||||||
|
LOOP AT dbtabs INTO DATA(dbtab).
|
||||||
|
"Retrieving database content of a dynamically specified database table
|
||||||
|
TRY.
|
||||||
|
SELECT *
|
||||||
|
FROM (dbtab)
|
||||||
|
INTO TABLE NEW @DATA(itab)
|
||||||
|
UP TO 5 ROWS.
|
||||||
|
CATCH cx_sy_dynamic_osql_semantics INTO DATA(sql_error).
|
||||||
|
CLEAR itab->*.
|
||||||
|
out->write( |Table { dbtab } does not exist.| ).
|
||||||
|
ENDTRY.
|
||||||
|
|
||||||
|
IF sql_error IS INITIAL.
|
||||||
|
"Getting table component names using RTTI methods
|
||||||
|
TRY.
|
||||||
|
DATA(type_descr_obj_tab) = CAST cl_abap_tabledescr(
|
||||||
|
cl_abap_typedescr=>describe_by_data( itab->* ) ).
|
||||||
|
DATA(tab_comps) = CAST cl_abap_structdescr(
|
||||||
|
type_descr_obj_tab->get_table_line_type( ) )->get_components( ).
|
||||||
|
LOOP AT tab_comps ASSIGNING FIELD-SYMBOL(<comp>).
|
||||||
|
APPEND VALUE #( name = <comp>-name len = strlen( <comp>-name ) ) TO it_comps.
|
||||||
|
ENDLOOP.
|
||||||
|
CATCH cx_sy_move_cast_error INTO DATA(error).
|
||||||
|
ENDTRY.
|
||||||
|
|
||||||
|
IF error IS INITIAL.
|
||||||
|
out->write( |\n| ).
|
||||||
|
out->write( |Retrieved content of database table { dbtab }:| ).
|
||||||
|
"Implementation for properly aligning the content
|
||||||
|
"The example is implemented to check the length of the column names as well as the
|
||||||
|
"length of the values in the columns. It determines the length of the longest string
|
||||||
|
"in each column. Depending on the length values, either the length of the column name
|
||||||
|
"or the length of the longest string in a column is stored in an internal table that
|
||||||
|
"contains information for calculating the offset.
|
||||||
|
LOOP AT tab_comps ASSIGNING FIELD-SYMBOL(<len>).
|
||||||
|
ASSIGN it_comps[ name = <len>-name ] TO FIELD-SYMBOL(<co>).
|
||||||
|
DATA(max_content) = REDUCE i( INIT len = <co>-len
|
||||||
|
FOR <line> IN itab->*
|
||||||
|
NEXT len = COND #( WHEN strlen( CONV string( <line>-(<co>-name) ) ) > len
|
||||||
|
THEN strlen( CONV string( <line>-(<co>-name) ) )
|
||||||
|
ELSE len ) ).
|
||||||
|
"Extend the length value to leave some more space
|
||||||
|
IF max_content > <co>-len.
|
||||||
|
<co>-len = max_content + 3.
|
||||||
|
ELSE.
|
||||||
|
<co>-len += 3.
|
||||||
|
ENDIF.
|
||||||
|
ENDLOOP.
|
||||||
|
"Calculating offset values
|
||||||
|
DATA max_str_len TYPE i.
|
||||||
|
LOOP AT it_comps ASSIGNING FIELD-SYMBOL(<off>).
|
||||||
|
DATA(tabix) = sy-tabix.
|
||||||
|
READ TABLE it_comps INDEX tabix - 1 ASSIGNING FIELD-SYMBOL(<prev>).
|
||||||
|
<off>-off = COND #( WHEN tabix = 1 THEN 0 ELSE <prev>-len + <prev>-off ).
|
||||||
|
max_str_len += <off>-len.
|
||||||
|
ENDLOOP.
|
||||||
|
"Providing enough space so that table row content can be inserted based on
|
||||||
|
"the offset specification
|
||||||
|
SHIFT str BY max_str_len PLACES RIGHT.
|
||||||
|
"Adding the column names first
|
||||||
|
LOOP AT it_comps ASSIGNING FIELD-SYMBOL(<header>).
|
||||||
|
str = insert( val = str sub = <header>-name off = <header>-off ).
|
||||||
|
ENDLOOP.
|
||||||
|
out->write( str ).
|
||||||
|
"Processing all lines in the internal table containing the retrieved table rows
|
||||||
|
LOOP AT itab->* ASSIGNING FIELD-SYMBOL(<wa>).
|
||||||
|
CLEAR str.
|
||||||
|
SHIFT str BY max_str_len PLACES RIGHT.
|
||||||
|
DO.
|
||||||
|
TRY.
|
||||||
|
str = insert( val = str sub = <wa>-(sy-index) off = it_comps[ sy-index ]-off ).
|
||||||
|
CATCH cx_sy_assign_illegal_component cx_sy_range_out_of_bounds cx_sy_itab_line_not_found.
|
||||||
|
EXIT.
|
||||||
|
ENDTRY.
|
||||||
|
ENDDO.
|
||||||
|
out->write( str ).
|
||||||
|
ENDLOOP.
|
||||||
|
ENDIF.
|
||||||
|
out->write( |\n| ).
|
||||||
|
CLEAR: str, it_comps.
|
||||||
|
ENDIF.
|
||||||
|
ENDLOOP.
|
||||||
|
ENDMETHOD.
|
||||||
|
ENDCLASS.
|
||||||
|
```
|
||||||
|
|
||||||
|
<p align="right"><a href="#top">⬆️ back to top</a></p>
|
||||||
|
|
||||||
### Dynamic Invoke
|
### 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.
|
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.
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user