Add AMDP cheat sheet
This commit is contained in:
437
12_AMDP.md
Normal file
437
12_AMDP.md
Normal file
@@ -0,0 +1,437 @@
|
||||
<a name="top"></a>
|
||||
|
||||
# A Glimpse on AMDP
|
||||
|
||||
- [A Glimpse on AMDP](#a-glimpse-on-amdp)
|
||||
- [About AMDP](#about-amdp)
|
||||
- [AMDP Classes](#amdp-classes)
|
||||
- [AMDP Methods](#amdp-methods)
|
||||
- [AMDP Procedures](#amdp-procedures)
|
||||
- [AMDP Functions](#amdp-functions)
|
||||
- [CDS Table Functions](#cds-table-functions)
|
||||
- [Further Information](#further-information)
|
||||
- [Executable Example](#executable-example)
|
||||
|
||||
|
||||
This cheat sheet gathers basic information on [ABAP Managed Database
|
||||
Procedures
|
||||
(AMDP)](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_managed_db_proc_glosry.htm "Glossary Entry").
|
||||
Find more details
|
||||
[here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenamdp.htm)
|
||||
in the ABAP Keyword Documentation.
|
||||
|
||||
## About AMDP
|
||||
|
||||
- AMDP are a class-based framework for managing and calling
|
||||
|
||||
- [database
|
||||
procedures](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendatabase_procedure_glosry.htm "Glossary Entry")
|
||||
(which is a synonym for [stored
|
||||
procedures](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenstored_procedure_glosry.htm "Glossary Entry"), i.
|
||||
e. the procedures are stored in the database - the [SAP HANA
|
||||
database](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenhana_database_glosry.htm "Glossary Entry")
|
||||
in this case - and executed there)
|
||||
- [database
|
||||
functions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendatabase_function_glosry.htm "Glossary Entry")
|
||||
(which are [SQLScript
|
||||
functions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensql_script_function_glosry.htm "Glossary Entry")
|
||||
in the SAP HANA database)
|
||||
|
||||
in [AS ABAP](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenas_abap_glosry.htm "Glossary Entry").
|
||||
|
||||
- "ABAP managed" enters the picture in ABAP with the option of
|
||||
implementing special [AMDP
|
||||
procedures](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenamdp_procedure_glosry.htm "Glossary Entry")
|
||||
as database procedures and [AMDP
|
||||
functions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenamdp_function_glosry.htm "Glossary Entry")
|
||||
as database functions.
|
||||
- The implementations are programmed using a database-specific
|
||||
language. Currently, AMDP only supports database procedures and
|
||||
functions from the SAP HANA database. That is,
|
||||
[SQLScript](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensql_script_glosry.htm "Glossary Entry")
|
||||
is the programming language of choice.
|
||||
- AMDP procedures and functions are part of a dedicated [AMDP
|
||||
class](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenamdp_class_glosry.htm "Glossary Entry")
|
||||
and declared and implemented as part of a method. The classes and
|
||||
methods have certain characteristics as outlined further down.
|
||||
- The AMDP framework replicates the procedure or function to the
|
||||
database system, i. e. despite the fact that the programming happens
|
||||
in an AMDP class (which is an [ABAP
|
||||
Repository](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_repository_glosry.htm "Glossary Entry")
|
||||
object as other global classes, too), the (SQLScript) code is
|
||||
executed only on the (SAP HANA) database and not in AS ABAP, i. e.
|
||||
method calls are sent to the database procedure or function.
|
||||
|
||||
> **💡 Note**<br>
|
||||
>- The use of AMDP is not recommended if the same task can be
|
||||
achieved using [ABAP
|
||||
SQL](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_sql_glosry.htm "Glossary Entry").
|
||||
>- AMDP classes can only be edited with the [ABAP Development Tools
|
||||
(ADT)](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenadt_glosry.htm "Glossary Entry").
|
||||
|
||||
## AMDP Classes
|
||||
|
||||
- As mentioned above, an [AMDP
|
||||
class](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenamdp_class_glosry.htm "Glossary Entry")
|
||||
is an [ABAP
|
||||
Repository](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_repository_glosry.htm "Glossary Entry")
|
||||
object like other global classes.
|
||||
- However, an AMDP class includes the specification of the interface
|
||||
`IF_AMDP_MARKER_HDB` for the SAP HANA
|
||||
database (indicated by `HDB`), which is currently the
|
||||
only possible database.
|
||||
- An AMDP class can contain both (one or more) [AMDP
|
||||
methods](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenamdp_method_glosry.htm "Glossary Entry")
|
||||
and non-AMDP methods.
|
||||
|
||||
Example for a [declaration part](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendeclaration_part_glosry.htm "Glossary Entry")
|
||||
of an AMDP class:
|
||||
|
||||
```abap
|
||||
CLASS cl_some_amdp_class DEFINITION
|
||||
PUBLIC
|
||||
FINAL
|
||||
CREATE PUBLIC.
|
||||
|
||||
PUBLIC SECTION.
|
||||
"Specifying the interface is mandatory
|
||||
INTERFACES if_amdp_marker_hdb.
|
||||
...
|
||||
ENDCLASS.
|
||||
```
|
||||
|
||||
|
||||
## AMDP Methods
|
||||
|
||||
- Can be created as [instance
|
||||
methods](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abeninstance_method_glosry.htm "Glossary Entry")
|
||||
using <code>METHODS</code> or [static
|
||||
methods](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenstatic_method_glosry.htm "Glossary Entry")
|
||||
using <code>CLASS-METHODS</code> in any visibility section.
|
||||
- Cannot be identified as AMDP methods in the declaration part of the
|
||||
class since there are no specific additions to the methods.
|
||||
Exceptions: AMDP function implementations that implement any [CDS table functions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencds_table_function_glosry.htm "Glossary Entry")
|
||||
as shown further down and method declarations using [`AMDP
|
||||
OPTIONS`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapmethods_amdp_options.htm)
|
||||
that are not dealt with here.
|
||||
|
||||
AMDP method declarations in any visibility section like non-AMDP
|
||||
methods:
|
||||
|
||||
```abap
|
||||
...
|
||||
PUBLIC SECTION.
|
||||
|
||||
METHODS some_amdp_meth
|
||||
... "Here go the parameters
|
||||
|
||||
PRIVATE SECTION.
|
||||
|
||||
CLASS-METHODS another_amdp_meth
|
||||
... "Here go the parameters
|
||||
|
||||
...
|
||||
```
|
||||
|
||||
|
||||
## AMDP Procedures
|
||||
|
||||
Despite the fact that AMDP methods cannot be identified as such from the
|
||||
[declaration
|
||||
part](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendeclaration_part_glosry.htm "Glossary Entry")
|
||||
(apart from the exceptions mentioned above), the declaration part of
|
||||
[AMDP
|
||||
procedures](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenamdp_procedure_glosry.htm "Glossary Entry")
|
||||
has special characteristics:
|
||||
|
||||
- Parameters must be [passed by
|
||||
value](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenpass_by_value_glosry.htm "Glossary Entry")
|
||||
using <code>VALUE(...)</code>. [Passing by
|
||||
reference](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenpass_by_reference_glosry.htm "Glossary Entry")
|
||||
is not allowed.
|
||||
- Parameter types ...
|
||||
- must not be generic.
|
||||
- can only be [elementary data
|
||||
types](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenelementary_data_type_glosry.htm "Glossary Entry")
|
||||
and [table
|
||||
types](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abentable_type_glosry.htm "Glossary Entry")
|
||||
with a structured row type (and this type can only contain
|
||||
elementary data types as components).
|
||||
- Return values cannot be declared using <code>RETURNING</code>.
|
||||
- Only input parameters can be flagged as optional parameters.
|
||||
|
||||
Example for an AMDP procedure's declaration part:
|
||||
|
||||
```abap
|
||||
...
|
||||
PUBLIC SECTION.
|
||||
|
||||
"Table type with a structured row type
|
||||
TYPES tab_type TYPE STANDARD TABLE OF dbtab WITH EMPTY KEY.
|
||||
|
||||
METHODS amdp_meth
|
||||
IMPORTING VALUE(num) TYPE i,
|
||||
EXPORTING VALUE(tab) TYPE tab_type.
|
||||
|
||||
...
|
||||
```
|
||||
|
||||
In contrast to the declaration part, the [implementation
|
||||
part](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenamdp_procedure_method_glosry.htm "Glossary Entry")
|
||||
of an AMDP method has multiple special additions for AMDP purposes
|
||||
following <code>METHOD</code> and the method name:
|
||||
|
||||
```abap
|
||||
...
|
||||
METHOD amdp_meth
|
||||
BY DATABASE PROCEDURE
|
||||
FOR HDB
|
||||
LANGUAGE SQLSCRIPT
|
||||
OPTIONS READ-ONLY
|
||||
USING db_object. "see comments further down
|
||||
|
||||
"Beginning of the SQLScript code (note that it is not ABAP code although it looks similar)
|
||||
|
||||
... "Here goes SAPScript code
|
||||
"Note that an AMDP method implementation must not be empty.
|
||||
|
||||
"End of the SQLScript code
|
||||
|
||||
ENDMETHOD.
|
||||
...
|
||||
|
||||
"Comments:
|
||||
" BY DATABASE PROCEDURE -> Flags the AMDP method as AMDP procedure
|
||||
" FOR HDB -> Definess the database system where the method is to be used;
|
||||
" currently, only HDB (SAP HANA database) is possible
|
||||
" LANGUAGE SQLSCRIPT -> Defines the programming language of the database system
|
||||
" OPTIONS READ-ONLY -> Specifies database-specific options
|
||||
" USING db_object. -> Optional addition; specifies database objects;
|
||||
" can also be AMDP procedures and functions
|
||||
```
|
||||
|
||||
Note:
|
||||
|
||||
- In the [restricted ABAP language
|
||||
version](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrestricted_version_glosry.htm "Glossary Entry")
|
||||
scope, only reads are allowed. Hence, the addition `OPTIONS READ-ONLY` is mandatory. Furthermore, you must make sure
|
||||
that the database objects that are specified after `USING` are accessible.
|
||||
- Generally, in the [unrestricted ABAP language
|
||||
version](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenunrestricted_version_glosry.htm "Glossary Entry")
|
||||
scope, more syntax options are allowed for AMDP method declaration
|
||||
and implementation parts. Check the ABAP Keyword Documentation for
|
||||
more details as touched on further down.
|
||||
|
||||
|
||||
|
||||
## AMDP Functions
|
||||
|
||||
[Scalar](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenamdp_scalar_function_glosry.htm "Glossary Entry")
|
||||
and [table
|
||||
functions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abentable_function_glosry.htm "Glossary Entry")
|
||||
can be managed as [AMDP
|
||||
functions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenamdp_function_glosry.htm "Glossary Entry").
|
||||
Such [AMDP table
|
||||
functions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenamdp_table_function_glosry.htm "Glossary Entry")
|
||||
have, as the name implies, a tabular [return
|
||||
value](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenreturn_value_glosry.htm "Glossary Entry")
|
||||
whereas AMDP scalar functions have a scalar or elementary return value
|
||||
(more information
|
||||
[here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenamdp_function_methods.htm)).
|
||||
Regarding AMDP table functions, there are two types available:
|
||||
|
||||
- Functions that can only be accessed in other AMDP methods (i. e.
|
||||
other AMDP functions or procedures) and cannot be called directly in
|
||||
ABAP
|
||||
- Functions that implement [CDS table
|
||||
functions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencds_table_function_glosry.htm "Glossary Entry")
|
||||
that can be accessed in ABAP SQL
|
||||
|
||||
Characteristics of method declaration parts of AMDP functions:
|
||||
|
||||
- Similar to AMDP procedures, the methods can be declared as static or
|
||||
instance methods in any visibility section.
|
||||
- The method parameters must include a return value using
|
||||
<code>RETURNING</code> and having a tabular data type.
|
||||
- Additionally, the parameters can include elementary and tabular
|
||||
input parameters.
|
||||
- No class-based exceptions can be declared using <code>RAISING</code>.
|
||||
|
||||
Example for an AMDP function's declaration part:
|
||||
|
||||
```abap
|
||||
...
|
||||
PUBLIC SECTION.
|
||||
|
||||
"Table type with a structured row type
|
||||
TYPES tab_type TYPE STANDARD TABLE OF dbtab WITH EMPTY KEY.
|
||||
|
||||
METHODS amdp_func
|
||||
IMPORTING VALUE(num) TYPE i,
|
||||
VALUE(some_elem) TYPE c LENGTH 3,
|
||||
RETURNING VALUE(tab) TYPE tab_type.
|
||||
|
||||
...
|
||||
```
|
||||
|
||||
The implementation part of an AMDP function is similar to the one of
|
||||
AMDP procedure as shown above. The difference is the use of `BY DATABASE FUNCTION` instead of `BY DATABASE PROCEDURE`:
|
||||
|
||||
```abap
|
||||
...
|
||||
METHOD amdp_func
|
||||
BY DATABASE FUNCTION
|
||||
FOR HDB
|
||||
LANGUAGE SQLSCRIPT
|
||||
OPTIONS READ-ONLY
|
||||
USING db_object.
|
||||
|
||||
"Beginning of the SQLScript code (note that it is not ABAP code although it looks similar)
|
||||
|
||||
... "Here goes SAPScript code;
|
||||
"AMDP table function to be called by other AMDP methods only
|
||||
|
||||
"End of the SQLScript code
|
||||
|
||||
ENDMETHOD.
|
||||
|
||||
"Comment:
|
||||
" BY DATABASE FUNCTION -> Flags the AMDP method as AMDP function
|
||||
...
|
||||
```
|
||||
|
||||
### CDS Table Functions
|
||||
|
||||
- Each [CDS table
|
||||
function](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencds_table_function_glosry.htm "Glossary Entry")
|
||||
is linked with an AMDP function in which it is implemented using
|
||||
SQLScript.
|
||||
- Can be used as data sources of ABAP SQL read statements.
|
||||
- Characteristics for method declaration and implementation parts
|
||||
regarding AMDP functions for CDS table functions:
|
||||
- Method can only be declared as a static method in the public visibility section of
|
||||
an AMDP class using `CLASS-METHODS`.
|
||||
- For the declaration, there is a special form with the addition
|
||||
`FOR TABLE FUNCTION`.
|
||||
- The [parameter
|
||||
interface](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenparameter_interface_glosry.htm "Glossary Entry")
|
||||
is not specified. Instead, the input parameters are determined
|
||||
by the [input
|
||||
parameters](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abeninput_parameter_glosry.htm "Glossary Entry")
|
||||
of the CDS table function (i. e. the names and data types -
|
||||
which are always elementary - specified there are used). As the
|
||||
return value, a standard table with an empty key is generated
|
||||
based on the structured row type including the components as
|
||||
specified in the CDS table function.
|
||||
|
||||
Example for an AMDP functions declaration implementing a CDS table
|
||||
function:
|
||||
|
||||
```abap
|
||||
...
|
||||
PUBLIC SECTION.
|
||||
|
||||
CLASS-METHODS:
|
||||
table_func FOR TABLE FUNCTION some_ddl_source.
|
||||
|
||||
...
|
||||
```
|
||||
|
||||
Notes on the [CDS
|
||||
DDL](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencds_ddl_glosry.htm "Glossary Entry")
|
||||
source of a CDS table function:
|
||||
|
||||
- You have defined (and activated) a CDS DDL source, i. e. a [CDS
|
||||
entity](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencds_entity_glosry.htm "Glossary Entry"),
|
||||
with the notation `DEFINE TABLE FUNCTION`
|
||||
- You can specify optional input parameters using `... WITH PARAMETERS parameter1, parameter2, ...`
|
||||
- You must specify an element list using `... RETURNS { element1; element2; ...; } ...`. The elements determine the
|
||||
components of the structured data type represented by a CDS table
|
||||
function.
|
||||
- You have specified the `IMPLEMENTED BY METHOD` addition
|
||||
followed by a fully qualified method name in the form of
|
||||
`amdp_class=>amdp_method` using the names of the AMDP
|
||||
class and method.
|
||||
- More information
|
||||
[here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencds_table_functions.htm).
|
||||
|
||||
The CDS DDL source might look like this:
|
||||
|
||||
```abap
|
||||
//Here go annotations.
|
||||
define table function some_ddl_source
|
||||
returns
|
||||
{
|
||||
client : abap.clnt;
|
||||
field1 : abap.char(5);
|
||||
field2 : abap.char(5);
|
||||
}
|
||||
implemented by method amdp_class=>amdp_method;
|
||||
```
|
||||
|
||||
You can then use the CDS table function as source for a
|
||||
`SELECT` statement, for example: `SELECT * FROM some_ddl_source INTO ...`.
|
||||
|
||||
|
||||
|
||||
## Further Information
|
||||
|
||||
Notes on using AMDP in environments with restricted language version (in
|
||||
contrast unrestricted language version):
|
||||
|
||||
AMDP methods ...
|
||||
|
||||
- must include the addition <code>OPTIONS READ-ONLY</code> in the
|
||||
declaration part.
|
||||
- must be implemented in SQLScript in any case.
|
||||
- cannot use the additions [`USING SCHEMA` (F1 for docu standard ABAP)](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapmethod_by_db_proc.htm#!ABAP_ADDITION_5@5@)
|
||||
and [`SUPPRESS SYNTAX ERRORS` (F1 docu for standard ABAP)](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapmethod_by_db_proc.htm#!ABAP_ADDITION_3@3@)
|
||||
in the method implementation part
|
||||
- cannot use [AMDP
|
||||
macros](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenamdp_macros.htm)
|
||||
and call hints.
|
||||
- can only use your own entities and entities that are released for
|
||||
the restricted language version after <code>USING</code>.
|
||||
- cannot use
|
||||
[`CONNECTION` (F1 docu for standard ABAP)](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenamdp_db_connections.htm)
|
||||
parameters.
|
||||
- cannot raise the
|
||||
`CX_AMDP_CONNECTION_ERROR` exception since
|
||||
the `CONNECTION` parameter is not allowed.
|
||||
|
||||
As mentioned above and hinted in the bullet points above, AMDP has more
|
||||
options regarding the unrestricted language version. Check the subtopics
|
||||
[here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenamdp.htm).
|
||||
A fundamental question in on-premise ABAP systems with an unrestricted
|
||||
language scope can be whether AMDP is supported at all. The constant
|
||||
`CALL_AMDP_METHOD` of the class
|
||||
`CL_ABAP_DBFEATURES` can be used to query
|
||||
whether the current database supports AMDP methods. See the following
|
||||
snippet:
|
||||
|
||||
```abap
|
||||
IF NOT cl_abap_dbfeatures=>use_features(
|
||||
EXPORTING requested_features =
|
||||
VALUE #( ( cl_abap_dbfeatures=>call_amdp_method ) ) ).
|
||||
|
||||
"Result: Current database system does not support AMDP procedures
|
||||
RETURN.
|
||||
ENDIF.
|
||||
```
|
||||
|
||||
This check is not required (and possible) for the SAP BTP ABAP Environment since those
|
||||
environments are SAP HANA-only anyway and database connections are not
|
||||
possible. Furthermore, another topic that should be noted is that AMDP
|
||||
does not support [implicit client
|
||||
handling](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_sql_client_handling.htm).
|
||||
Therefore, the parameter interface of AMDP methods usually contains an
|
||||
input parameter for the client ID. See more information
|
||||
[here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenamdp_client_handling.htm) (or [here for the F1 docu for standard ABAP](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenamdp_client_handling.htm)).
|
||||
The client handling is not dealt with in this cheat sheet and not
|
||||
relevant in the executable example.
|
||||
|
||||
|
||||
## Executable Example
|
||||
[zcl_demo_abap_amdp](./src/zcl_demo_abap_amdp.clas.abap)
|
||||
|
||||
Note the steps outlined [here](README.md#-getting-started-with-the-examples) about how to import and run the code.
|
||||
@@ -66,7 +66,8 @@ ABAP cheat sheets[^1] ...
|
||||
|[ABAP for RAP: Entity Manipulation Language (ABAP EML)](08_EML_ABAP_for_RAP.md)| Setting EML in the context of RAP, standard (create, read, update, delete) and non-standard operations (actions) | <ul><li>[Demo RAP scenario with a managed RAP BO, external numbering (zcl_demo_abap_rap_ext_num_m)](./src/zcl_demo_abap_rap_ext_num_m.clas.abap)</li><br><li>[Demo RAP scenario with an unmanaged RAP BO, external numbering (zcl_demo_abap_rap_ext_num_u)](./src/zcl_demo_abap_rap_ext_num_u.clas.abap)</li><br><li>[Demo RAP scenario ("RAP calculator") with a managed, draft-enabled RAP BO, late numbering (zcl_demo_abap_rap_draft_ln_m)](./src/zcl_demo_abap_rap_draft_ln_m.clas.abap) <br>Note that this example can also be checked out using the preview version of an SAP Fiori UI. Check the comments in the class for the steps.</li></ul> |
|
||||
|[Excursion Down to Bits and Bytes](09_Bits_and_Bytes.md)|Touches on the technical background of data types and data objects|-|
|
||||
|[ABAP SQL: Working with Hierarchies](10_ABAP_SQL_Hierarchies.md)|Summarizes the functions ABAP SQL offers together with ABAP CDS for working with hierarchical data that is stored in database tables|-|
|
||||
|[ABAP SQL: Grouping Internal Tables](11_ABAP_SQL_Grouping_Internal_Tables.md)|Touches on the `GROUP BY` clause in ABAP SQL|[zcl_demo_abap_sql_group_by](./src/zcl_demo_abap_sql_group_by.clas.abap)
|
||||
|[ABAP SQL: Grouping Internal Tables](11_ABAP_SQL_Grouping_Internal_Tables.md)|Touches on the `GROUP BY` clause in ABAP SQL|[zcl_demo_abap_sql_group_by](./src/zcl_demo_abap_sql_group_by.clas.abap)|
|
||||
|[A Glimpse on AMDP](12_AMDP.md)|Touches ABAP Managed Database Procedures (AMDP): AMDP Procedures and AMDP Functions (including CDS Table Functions)|[zcl_demo_abap_amdp](./src/zcl_demo_abap_amdp.clas.abap)
|
||||
|
||||
## 🎬 Getting Started with the Examples
|
||||
|
||||
|
||||
368
src/zcl_demo_abap_amdp.clas.abap
Normal file
368
src/zcl_demo_abap_amdp.clas.abap
Normal file
@@ -0,0 +1,368 @@
|
||||
***********************************************************************
|
||||
*
|
||||
* ABAP cheat sheet: AMDP
|
||||
*
|
||||
* -------------------------- PURPOSE ----------------------------------
|
||||
* - Example to demonstrate AMDP procedures and functions. It includes
|
||||
* a CDS table function.
|
||||
* - NOTE:
|
||||
* - The example covers basics regarding AMDP method declarations
|
||||
* and implementations.
|
||||
* - The purpose is to give you a rough idea about AMDP. Therefore,
|
||||
* the SQLScript code used in the method implementations is
|
||||
* fairly simple. AMDP is not needed in simple cases like these.
|
||||
* - The example is primarily intended for the SAP BTP ABAP
|
||||
* environment. For example, in SAP BTP ABAP environment only
|
||||
* read-only operations are possible. In general, there are more
|
||||
* syntax options available in the unrestricted ABAP language scope
|
||||
* in on-premise ABAP systems. Check the ABAP Keyword Documentation
|
||||
* for more details and examples.
|
||||
*
|
||||
* ----------------------- GETTING STARTED -----------------------------
|
||||
* - Open the class with the ABAP Development Tools (ADT).
|
||||
* - Choose F9 to run the class.
|
||||
* - Check the console output.
|
||||
* - To understand the context and the ABAP syntax used, check the notes
|
||||
* included in the class as comments or refer to the respective topic
|
||||
* in the ABAP Keyword Documentation.
|
||||
* - Due to the amount of output in the console, the examples include
|
||||
* numbers (e. g. 1) ..., 2) ..., 3) ...) for the individual example
|
||||
* sections. Plus, the variable name is displayed in most cases. Hence,
|
||||
* to easier and faster find the relevant output in the console, just
|
||||
* search in the console for the number/variable name (STRG+F in the
|
||||
* console) or use the debugger.
|
||||
*
|
||||
* ----------------------------- NOTE -----------------------------------
|
||||
* The code presented in this class is only meant for supporting the ABAP
|
||||
* cheat sheets. It is not intended for direct use in a
|
||||
* production system environment. The code examples in the ABAP cheat
|
||||
* sheets are primarily intended to provide a better explanation and
|
||||
* visualization of the syntax and semantics of ABAP statements and not to
|
||||
* solve concrete programming tasks. For production application programs,
|
||||
* a dedicated solution should therefore always be worked out for each
|
||||
* individual case. There is no guarantee for either the correctness or
|
||||
* the completeness of the code. In addition, there is no legal
|
||||
* responsibility or liability for possible errors or their consequences
|
||||
* which occur through the use of the example code.
|
||||
*
|
||||
***********************************************************************
|
||||
"! <p class="shorttext synchronized">ABAP cheat sheet: AMDP</p>
|
||||
"! Example to demonstrate AMDP procedures and functions.<br>Choose F9 in ADT to run the class.
|
||||
CLASS zcl_demo_abap_amdp DEFINITION
|
||||
PUBLIC
|
||||
FINAL
|
||||
CREATE PUBLIC .
|
||||
|
||||
PUBLIC SECTION.
|
||||
INTERFACES:
|
||||
if_oo_adt_classrun, "Interface for displaying output
|
||||
if_amdp_marker_hdb. "This interface specification is mandatory for an AMDP class
|
||||
|
||||
"Various internal table type specifications for the parameters of AMDP methods
|
||||
"Note: Only table and elementary data types are possible for the parameters.
|
||||
TYPES carr_tab TYPE STANDARD TABLE OF zdemo_abap_carr WITH EMPTY KEY.
|
||||
|
||||
TYPES fli_tab TYPE STANDARD TABLE OF zdemo_abap_fli WITH EMPTY KEY.
|
||||
|
||||
TYPES:
|
||||
"Structured data type as basis for the table type below
|
||||
BEGIN OF carr_fli_struc,
|
||||
carrname TYPE zdemo_abap_carr-carrname,
|
||||
connid TYPE zdemo_abap_flsch-connid,
|
||||
cityfrom TYPE zdemo_abap_flsch-cityfrom,
|
||||
cityto TYPE zdemo_abap_flsch-cityto,
|
||||
END OF carr_fli_struc,
|
||||
|
||||
"Internal table type
|
||||
carr_fli_tab TYPE STANDARD TABLE OF carr_fli_struc WITH EMPTY KEY,
|
||||
|
||||
"Structured data type as basis for the table type below
|
||||
BEGIN OF fli_struc,
|
||||
carrid TYPE zdemo_abap_flsch-carrid,
|
||||
connid TYPE zdemo_abap_flsch-connid,
|
||||
cityfrom TYPE zdemo_abap_flsch-cityfrom,
|
||||
cityto TYPE zdemo_abap_flsch-cityto,
|
||||
fltime TYPE zdemo_abap_flsch-fltime,
|
||||
END OF fli_struc,
|
||||
|
||||
"Internal table type
|
||||
flsch_tab TYPE STANDARD TABLE OF zdemo_abap_flsch WITH EMPTY KEY.
|
||||
|
||||
"Various instance method declarations
|
||||
"The selection for instance and static methods is irrelevant for the example.
|
||||
"It is just meant to visualize that AMDP methods can be declared as either of them.
|
||||
|
||||
"AMDP procedure
|
||||
"It's a simple AMDP procedure having only an output parameter with tabular type.
|
||||
"Note the parameter declaration that includes the mandatory passing by value.
|
||||
"This is true for all of the AMDP method declarations.
|
||||
METHODS select_carriers
|
||||
EXPORTING VALUE(carr_tab) TYPE carr_tab.
|
||||
|
||||
"AMDP procedure to call an AMDP table function
|
||||
"As can be seen in the implementation part, this example method calls the
|
||||
"AMDP table function get_carr_fli. AMDP table functions can only be called
|
||||
"by other AMDP methods.
|
||||
METHODS select_get_carr_fli
|
||||
IMPORTING VALUE(carrid) TYPE zdemo_abap_fli-carrid
|
||||
EXPORTING VALUE(carr_fli_tab) TYPE carr_fli_tab.
|
||||
|
||||
"Various static method declarations
|
||||
|
||||
"The purpose of the implementation of the static constructor in this example is to
|
||||
"fill a demo database table to have data to work with in the example.
|
||||
CLASS-METHODS class_constructor.
|
||||
|
||||
"AMDP procedure
|
||||
"This method demonstrates the calling of an AMDP procedure from SQLScript.
|
||||
"In this example, the selection of data is 'delegated' to another AMDP method get_flights_amdp
|
||||
"in the same AMDP class. The method declaration includes the addition RAISING with an
|
||||
"exception class for AMDP-specific exceptions.
|
||||
CLASS-METHODS get_flights
|
||||
IMPORTING VALUE(carrid) TYPE zdemo_abap_fli-carrid
|
||||
EXPORTING VALUE(fli_tab) TYPE fli_tab
|
||||
RAISING cx_amdp_execution_error.
|
||||
|
||||
"AMDP Table Function for CDS Table Function
|
||||
"Note that, in this case, a static method declaration is required along with the special
|
||||
"syntax FOR TABLE FUNCTION. Plus, there are no parameters specified and the declaration
|
||||
"is made in the PUBLIC visibility section.
|
||||
CLASS-METHODS flight_analysis FOR TABLE FUNCTION zdemo_abap_table_function.
|
||||
|
||||
PRIVATE SECTION.
|
||||
|
||||
"AMDP procedure
|
||||
"This method demonstrates the calling of an AMDP procedure from SQLScript as mentioned above.
|
||||
CLASS-METHODS get_flights_amdp
|
||||
IMPORTING VALUE(carrid) TYPE zdemo_abap_fli-carrid
|
||||
EXPORTING VALUE(fli_tab) TYPE fli_tab
|
||||
RAISING cx_amdp_execution_error.
|
||||
|
||||
"AMDP table function
|
||||
"AMDP table functions can only be called by other AMDP methods. In this example,
|
||||
"the AMDP procedure select_get_carr_fli calls this AMDP table function.
|
||||
METHODS get_carr_fli
|
||||
IMPORTING VALUE(carrid) TYPE zdemo_abap_flsch-carrid
|
||||
RETURNING VALUE(carr_fli_tab) TYPE carr_fli_tab.
|
||||
|
||||
ENDCLASS.
|
||||
|
||||
CLASS zcl_demo_abap_amdp IMPLEMENTATION.
|
||||
|
||||
METHOD class_constructor.
|
||||
"Filling demo database tables.
|
||||
zcl_demo_abap_flight_tables=>fill_dbtabs( ).
|
||||
ENDMETHOD.
|
||||
|
||||
|
||||
METHOD if_oo_adt_classrun~main.
|
||||
|
||||
DATA(output) = NEW zcl_demo_abap_display( out ).
|
||||
|
||||
output->display( `Demo: ABAP AMDP` ).
|
||||
|
||||
output->display( `1. AMDP procedure` ).
|
||||
|
||||
"Declaring an internal table to store the data that are
|
||||
"returned by the following method.
|
||||
"You could also choose to create the internal table inline
|
||||
"within the method call,
|
||||
"i. e. like ... IMPORTING carr_tab = DATA(tab) ).
|
||||
DATA amdp_proc_res TYPE zcl_demo_abap_amdp=>carr_tab.
|
||||
|
||||
"Since the method is declared as an instance method, an instance
|
||||
"has to be created. Here, the instance constructor NEW is used
|
||||
"in a standalone method call that includes a chained method call.
|
||||
NEW zcl_demo_abap_amdp( )->select_carriers(
|
||||
IMPORTING carr_tab = amdp_proc_res ).
|
||||
|
||||
output->display( input = amdp_proc_res name = `amdp_proc_res` ).
|
||||
|
||||
**********************************************************************
|
||||
|
||||
output->next_section( `2. Calling an AMDP Procedure from SQLScript` ).
|
||||
|
||||
"As can be seen in the method implementation part, this AMDP procedure
|
||||
"includes an AMDP procedure call from SQLScript.
|
||||
"In this example, the AMDP procedure get_flights_amdp is called by
|
||||
"get_flights which is meant to select data from a database table.
|
||||
"The returned result is displayed.
|
||||
TRY.
|
||||
|
||||
zcl_demo_abap_amdp=>get_flights( EXPORTING carrid = 'LH'
|
||||
IMPORTING fli_tab = DATA(call_amdp_res) ).
|
||||
|
||||
CATCH cx_amdp_execution_error INTO DATA(error1).
|
||||
|
||||
out->write( error1->get_text( ) ).
|
||||
|
||||
ENDTRY.
|
||||
|
||||
output->display( input = call_amdp_res name = `call_amdp_res` ).
|
||||
|
||||
|
||||
**********************************************************************
|
||||
|
||||
output->next_section( `3. AMDP Table Function for AMDP Method` ).
|
||||
|
||||
"The AMDP procedure select_get_carr_fli calls the AMDP table function
|
||||
"get_carr_fli in the implementation part. AMDP table functions can
|
||||
"only be called by other AMDP methods.
|
||||
TRY.
|
||||
|
||||
NEW zcl_demo_abap_amdp( )->select_get_carr_fli(
|
||||
EXPORTING carrid = 'LH'
|
||||
IMPORTING carr_fli_tab = DATA(amdp_tab_func) ).
|
||||
|
||||
CATCH cx_amdp_execution_error INTO DATA(error2).
|
||||
|
||||
out->write( error2->get_text( ) ).
|
||||
|
||||
ENDTRY.
|
||||
|
||||
output->display( input = amdp_tab_func name = `amdp_tab_func` ).
|
||||
|
||||
"Note: When commented in, the following code results in a runtime
|
||||
"error since you cannot call an AMDP function in ABAP directly.
|
||||
* NEW ZCL_demo_ABAP_AMDP( )->get_carr_fli(
|
||||
* EXPORTING carrid = 'LH' ).
|
||||
|
||||
**********************************************************************
|
||||
|
||||
output->next_section( `4. AMDP Table Function for CDS Table Function` ).
|
||||
|
||||
|
||||
"The example demonstrates that a CDS table function can be used as a
|
||||
"data source of ABAP SQL read statements.
|
||||
"You might want to navigate to the DDL source after FROM by holding
|
||||
"CTRL and clicking the DDL source name in ADT to see the details.
|
||||
"Or, just check out the F2 help.
|
||||
"In this example, the CDS table function is implemented in a way to
|
||||
"return accumulated data.
|
||||
"In the method implementation for flight_analysis, first two kinds of
|
||||
"data sets from two database tables are gathered. These data sets are
|
||||
"joined using an inner join. There, some expressions are included
|
||||
"(strings are aggregated, average values are determined).
|
||||
|
||||
SELECT * FROM zdemo_abap_table_function
|
||||
INTO TABLE @DATA(cds_tab_func).
|
||||
|
||||
output->display( input = cds_tab_func name = `cds_tab_func` ).
|
||||
|
||||
ENDMETHOD.
|
||||
|
||||
**********************************************************************
|
||||
|
||||
METHOD select_carriers
|
||||
BY DATABASE PROCEDURE
|
||||
FOR HDB
|
||||
LANGUAGE SQLSCRIPT
|
||||
OPTIONS READ-ONLY
|
||||
USING zdemo_abap_carr.
|
||||
* Simple data selection
|
||||
carr_tab = SELECT *
|
||||
FROM "ZDEMO_ABAP_CARR"
|
||||
ORDER BY carrid;
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD get_flights
|
||||
BY DATABASE PROCEDURE
|
||||
FOR HDB
|
||||
LANGUAGE SQLSCRIPT
|
||||
OPTIONS READ-ONLY
|
||||
USING zcl_demo_abap_amdp=>get_flights_amdp.
|
||||
* Another AMDP procedure is called from SQLScript
|
||||
CALL "ZCL_DEMO_ABAP_AMDP=>GET_FLIGHTS_AMDP"(
|
||||
CARRID => :CARRID,
|
||||
FLI_TAB => :FLI_TAB );
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD get_flights_amdp
|
||||
BY DATABASE PROCEDURE
|
||||
FOR HDB
|
||||
LANGUAGE SQLSCRIPT
|
||||
OPTIONS READ-ONLY
|
||||
USING zdemo_abap_fli.
|
||||
* Simple data selection
|
||||
fli_tab = SELECT *
|
||||
FROM "ZDEMO_ABAP_FLI"
|
||||
WHERE carrid = :carrid
|
||||
ORDER BY carrid;
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD flight_analysis
|
||||
BY DATABASE FUNCTION
|
||||
FOR HDB
|
||||
LANGUAGE SQLSCRIPT
|
||||
OPTIONS READ-ONLY
|
||||
USING zdemo_abap_flsch "Two database tables are used and must both be specified here.
|
||||
zdemo_abap_carr.
|
||||
* Reading data from two database tables
|
||||
itab_cities =
|
||||
SELECT DISTINCT
|
||||
zdemo_abap_flsch.mandt as client,
|
||||
zdemo_abap_flsch.carrid as carrier_id,
|
||||
zdemo_abap_flsch.airpfrom as airport_from,
|
||||
zdemo_abap_flsch.airpto as airport_to,
|
||||
zdemo_abap_flsch.fltime as flight_time,
|
||||
zdemo_abap_flsch.distance as flight_distance,
|
||||
zdemo_abap_flsch.distid as unit
|
||||
FROM zdemo_abap_flsch;
|
||||
|
||||
itab_carrier_names =
|
||||
SELECT DISTINCT
|
||||
zdemo_abap_carr.mandt as client,
|
||||
zdemo_abap_carr.carrid as carrier_id,
|
||||
zdemo_abap_carr.carrname as carrier_name
|
||||
FROM zdemo_abap_carr;
|
||||
|
||||
* Returning joined data using an inner join
|
||||
RETURN
|
||||
SELECT fl.client, fl.carrier_id, ca.carrier_name,
|
||||
* Departure and destination airports are concatenated; then all results are joined by string aggregation
|
||||
STRING_AGG( CONCAT(CONCAT(fl.airport_from,' -> '),fl.airport_to), ', ' ORDER BY fl.airport_from) AS connections,
|
||||
* Retrieving the average flight time of all flights by carrier
|
||||
AVG( fl.flight_time ) as avg_flight_time,
|
||||
* Retrieving the average flight distance of all flights by carrier; miles are converted to kilometers
|
||||
AVG( CASE 'MI'
|
||||
WHEN fl.unit THEN fl.flight_distance * 1.609
|
||||
ELSE fl.flight_distance
|
||||
END ) AS avg_distance
|
||||
FROM :itab_cities AS fl
|
||||
INNER JOIN :itab_carrier_names AS ca
|
||||
ON ca.client = fl.client
|
||||
AND ca.carrier_id = fl.carrier_id
|
||||
WHERE fl.client = ca.client AND fl.carrier_id = ca.carrier_id
|
||||
GROUP BY fl.client, ca.carrier_name, fl.carrier_id;
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD get_carr_fli
|
||||
BY DATABASE FUNCTION
|
||||
FOR HDB
|
||||
LANGUAGE SQLSCRIPT
|
||||
OPTIONS READ-ONLY
|
||||
USING zdemo_abap_carr zdemo_abap_flsch.
|
||||
* AMDP table function to be called by other AMDP methods only.
|
||||
* In the example, joined data from two database table are returned.
|
||||
RETURN
|
||||
SELECT ca.carrname, fl.connid, fl.cityfrom, fl.cityto
|
||||
FROM zdemo_abap_carr as ca
|
||||
INNER JOIN zdemo_abap_flsch as fl
|
||||
ON ca.carrid = fl.carrid
|
||||
WHERE fl.carrid = :carrid
|
||||
ORDER BY ca.mandt, ca.carrname, fl.connid;
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD select_get_carr_fli
|
||||
BY DATABASE PROCEDURE
|
||||
FOR HDB
|
||||
LANGUAGE SQLSCRIPT
|
||||
OPTIONS READ-ONLY
|
||||
USING zcl_demo_abap_amdp=>get_carr_fli.
|
||||
* AMDP procedure to call an AMDP table function as specified after USING
|
||||
carr_fli_tab = SELECT *
|
||||
FROM "ZCL_DEMO_ABAP_AMDP=>GET_CARR_FLI"(
|
||||
carrid => :carrid );
|
||||
ENDMETHOD.
|
||||
|
||||
ENDCLASS.
|
||||
16
src/zcl_demo_abap_amdp.clas.xml
Normal file
16
src/zcl_demo_abap_amdp.clas.xml
Normal file
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<abapGit version="v1.0.0" serializer="LCL_OBJECT_CLAS" serializer_version="v1.0.0">
|
||||
<asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
|
||||
<asx:values>
|
||||
<VSEOCLASS>
|
||||
<CLSNAME>ZCL_DEMO_ABAP_AMDP</CLSNAME>
|
||||
<LANGU>E</LANGU>
|
||||
<DESCRIPT>ABAP cheat sheet: AMDP</DESCRIPT>
|
||||
<STATE>1</STATE>
|
||||
<CLSCCINCL>X</CLSCCINCL>
|
||||
<FIXPT>X</FIXPT>
|
||||
<UNICODE>5</UNICODE>
|
||||
</VSEOCLASS>
|
||||
</asx:values>
|
||||
</asx:abap>
|
||||
</abapGit>
|
||||
13
src/zdemo_abap_table_function.ddls.asddls
Normal file
13
src/zdemo_abap_table_function.ddls.asddls
Normal file
@@ -0,0 +1,13 @@
|
||||
@AccessControl.authorizationCheck: #NOT_REQUIRED
|
||||
define table function ZDEMO_ABAP_TABLE_FUNCTION
|
||||
returns
|
||||
{
|
||||
client : abap.clnt;
|
||||
carrier_id : abap.char(3);
|
||||
carrier_name : abap.char(20);
|
||||
connections : abap.string;
|
||||
avg_flight_time : abap.dec( 10, 2 );
|
||||
avg_distance : abap.dec( 10, 2 );
|
||||
}
|
||||
implemented by method
|
||||
zcl_demo_abap_amdp=>flight_analysis;
|
||||
0
src/zdemo_abap_table_function.ddls.baseinfo
Normal file
0
src/zdemo_abap_table_function.ddls.baseinfo
Normal file
13
src/zdemo_abap_table_function.ddls.xml
Normal file
13
src/zdemo_abap_table_function.ddls.xml
Normal file
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<abapGit version="v1.0.0" serializer="LCL_OBJECT_DDLS" serializer_version="v1.0.0">
|
||||
<asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
|
||||
<asx:values>
|
||||
<DDLS>
|
||||
<DDLNAME>ZDEMO_ABAP_TABLE_FUNCTION</DDLNAME>
|
||||
<DDLANGUAGE>E</DDLANGUAGE>
|
||||
<DDTEXT>ABAP Demo: Table function</DDTEXT>
|
||||
<SOURCE_TYPE>F</SOURCE_TYPE>
|
||||
</DDLS>
|
||||
</asx:values>
|
||||
</asx:abap>
|
||||
</abapGit>
|
||||
Reference in New Issue
Block a user