Querry报表引起的一个AMDP开发
最近接了一个小需求,生产订单报表上加个订单状态。嗯,成熟的解决方案,小case啦~然后一看,是Querry报表。
作为一个成熟的老开发,岂能就此退缩!第一时间想到的,就是写个CDS视图,只要数据字典能看到它,Querry就能用,小case啦~
然后……


是的,虽然S4以后,ABAP也可以使用一些“高端”的SQL写法,比如直接进行字符串操作,计算等,并且大部分ABAP的OPENSQL能干的,CDS都能干,甚至干的更好,但是STRING_AGG,这个聚合函数它没有。
(可能有童鞋不清楚STRING_AGG这个函数,解释一下,它的作用是将数组纵列的字段,按条件拼接在一起。和concat不同,concat是拼接数组当前行的字段)
所以要怎么破呢?
还是我们的老朋友,AMDP来搞定。
看过我《直接SQL你的JSON字符串》的朋友,应该已经了解了AMDP的一个方法,AMDP procedure implementations,过程实现。它是用于实现数据库过程的 AMDP 方法。它是在 AMDP 类中声明的,就像任何可见性部分中的常规静态方法或实例方法一样。在类的声明部分中,无法将 AMDP 过程实现标识为 AMDP 方法。
AMDP 过程实现在类的实现部分中使用语句 METHOD 的添加 BY DATABASE PROCEDURE 表示为 AMDP 方法。同时,还定义了使用该方法的数据库系统以及用于实现该方法的数据库系统的编程语言。必须使用加法 USING 声明在 AMDP 方法中访问的当前数据库模式的数据库对象。如果可能,将根据此信息执行语法检查。当访问 ABAP 字典中定义的数据库表时,并且该访问是静态已知的,AMDP 框架将确保遵循字典中定义的字段的顺序,该顺序可能与数据库上的顺序不同。
现在我们要用AMDP写视图,则是要使用它的另一个方法,Function Implementations,函数实现。
AMDP 函数实现是一种 AMDP 方法,用于将 AMDP 函数实现为数据库函数 。AMDP 函数实现在类的实现部分中使用语句 METHOD 的加法 BY DATABASE FUNCTION 表示为 AMDP 方法。可以实现 AMDP 表函数和 AMDP 标量函数 。
AMDP 表函数有以下几种类型:只能在其他 AMDP 方法中访问的函数;可在 ABAP SQL 中访问的实现 CDS 表函数的函数。
AMDP 标量函数有以下类型:只能在其他 AMDP 方法中访问的函数;实现 CDS 标量函数的函数,可用于 CDS 实体的作数位置。
这一次,我们用表函数来解决问题。
首先,还是创建一个Data Definition。


选择table function的类型

然后写代码:
@EndUserText.label: 'AMDP table function test'definetablefunction ztf_testreturns{key client :abap.clnt;key aufnr :aufnr;status :char255;}implementedbymethod ZCL_TF_TEST=>GET_STATUS;
需要注意,这里status不能使用太长的字符类型,会报错;后面指定的方法和类,不能被其他table function使用。
保存激活一下,再新建类。不然后面会报错。

CLASS zcl_tf_test DEFINITIONPUBLICFINALCREATE PUBLIC .PUBLIC SECTION.INTERFACES if_amdp_marker_hdb.CLASS-METHODS:get_status FOR TABLE FUNCTION ztf_test.PROTECTED SECTION.PRIVATE SECTION.ENDCLASS.CLASS zcl_tf_test IMPLEMENTATION.METHOD get_status BY DATABASE FUNCTIONFOR HDBLANGUAGE SQLSCRIPTOPTIONS READ-ONLYUSING aufkjesttj02t.itab =select DISTINCTjest.mandt as client,aufk.aufnr,tj02t.txt04from aufkinner join jest on jest.objnr = aufk.objnr andjest.mandt = aufk.mandtinner join tj02t on tj02t.istat = jest.statand tj02t.spras = session_context('LOCALE_SAP')WHERE jest.inact = ''AND jest.mandt = session_context('CLIENT');RETURNselect client,aufnr,STRING_AGG(txt04, ', ' order by txt04) as statusFROM :itabGROUP BY client,aufnrORDER BY client,aufnr;ENDMETHOD.ENDCLASS.
讲解下代码:

类要使用AMDP的接口,if_amdp_marker_hdb,这个是必选项,没啥好说的。后面的class-methods,方法就是前面table function指定的方法名,后面的for table function,就是前面我们创建的table function。不要输错,并且创建好的table function要先激活,不然类会报错,说table function不存在。

这一部分很眼熟了吧,指定数据库,语言,和要用到的表。

先取订单的全部状态。这里的语法还是CDS的语法范畴,无法使用ABAP的语法。

Return后面的部分,这里的语法就是ABAP的语法了,我们可以正常的使用STRING_AGG,把txt04拼接成一行。
激活类,这个table function就能正常输出值了。

但是为了能在数据字典中看到它,还是需要再写个普通的CDS View类型的视图封装下。


