Loop through multiple rows in ABAP CDS by AMDP
If you have worked with ABAP CDS long enough, there is no function to really loop through multiple records and use them for a calculation of a row or certain field. While ABAP CDS syntax still does not offer such functions till today, there are few functions available in ABAP Managed Database Procedures(AMDP) table functions from which ABAP CDS can consume the calculated.
Exercise
We will create a CDS view that returns all the business partners and concatenate their business partner roles(customer, vendor, etc) into one field.
Create table function
Table function must define the fields structure required. The actual data fetching will not be done in the table function object but in the ABAP class that is triggered. So the ABAP class and the method must be defined in table function as well.
@EndUserText.label: 'table function'
define table function ZTBL_FUNCTION
with parameters
@Environment.systemField: #CLIENT
p_clnt :abap.clnt,
@Environment.systemField: #SYSTEM_LANGUAGE
p_lang :abap.lang
returns
{
client : abap.clnt;
salesdoc : vbeln_va;
mergefunctiontext : abap.char( 1000 );
}
implemented by method
ZCL_TableFunction=>Get_Data;
Note that if you are using system fields in the SQL to fetch the data, I suggest to define them as parameters. This is because in the subsequent ABAP class where the SQL Script is performed, certain system fields are not available. If they are defined as parameters in table functions, they can be used in the SQL script. We will demonstrate that with client and system language fields.
Create ABAP class to fetch table function data
Class name and method must match the ones defined in table function. Few key points to mentions:
- INTERFACES if_amdp_marker_hdb is added to the public section
- Get_data method must define what database is used, script language, and the tables used in the script
- Use RETURN statement along with SQL to return the data to table function ztbl_function.
- Most importatntly, the SAP script is client dependent, so it must specify the client in SQL otherwise it will fetch the data from all clients in instance.
Few things to mention on the logic:
- bpfunctionconcat will return the “BP function code ( description ) ” for easier readability
- vbpa.posnr = ‘000000’ excludes all sales document that has BP specifically set for sales item
- As function text is language dependent, tpart.spras must be specified with system language therefore using p_langu defined in the table function.
CLASS zcl_tablefunction DEFINITION
PUBLIC
FINAL
CREATE PUBLIC .
PUBLIC SECTION.
INTERFACES if_amdp_marker_hdb.
CLASS-METHODS:
get_data FOR TABLE FUNCTION ztbl_function.
PROTECTED SECTION.
PRIVATE SECTION.
ENDCLASS.
CLASS zcl_tablefunction IMPLEMENTATION.
METHOD get_data
BY DATABASE FUNCTION
FOR HDB
LANGUAGE SQLSCRIPT
OPTIONS READ-ONLY
USING vbak vbpa tpart.
* Get the sales header BP functions
it_data = select DISTINCT
vbak.mandt as client,
vbak.vbeln as salesdoc,
vbpa.parvw as bpfunction,
tpart.vtext as bpfunctiontext,
concat(concat(concat(cast(vbpa.parvw as "$ABAP.type( parvw )" ), '('), tpart.vtext), ')') as bpfunctionconcat
from vbak
inner join vbpa
on vbak.mandt = vbpa.mandt
and vbpa.vbeln = vbak.vbeln
and vbpa.posnr = '000000'
inner join tpart
on tpart.mandt = vbpa.mandt
and tpart.parvw = vbpa.parvw
and tpart.spras = :p_lang
where vbak.mandt = :p_clnt;
RETURN select client,
salesdoc,
string_agg(bpfunctionconcat, ', ' ORDER BY bpfunctionconcat) as mergefunctiontext
FROM :it_data
GROUP BY client,
salesdoc;
ENDMETHOD.
ENDCLASS.
Consume table function
Create a CDS view to consume the table function. Pass the system fields client and language.
@AbapCatalog.viewEnhancementCategory: [#NONE]
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Consume table function'
@Metadata.ignorePropagatedAnnotations: true
@ObjectModel.usageType:{
serviceQuality: #X,
sizeCategory: #S,
dataClass: #MIXED
}
define view entity ZTBL_FUNCTION_CONSUME
as select from ZTBL_FUNCTION( p_clnt : $session.client, p_lang : $session.system_language )
{
salesdoc,
mergefunctiontext
}
Preview this CDS in SE16n and you can see that mergefunctiontext returns all the business partner and it’s text in one single line.