开始使用CDS View

2022-09-27 11:19发布

转自:https://mp.weixin.qq.com/s/iIVfB6yXxS2JK2r0HWYycw


     技术随着HANA近些年在国内的普及,很多已经在使用SAP产品的企业都将传统的SAP产品(比如ECC)做了升级,底层替换为HANA。也有很多新的企业,在采购SAP产品时,直接选择On   Hana的版本。传统的ABAP开发方式,表面看来虽然没有太大改变,但随着产品不断的升级,SAP也提供了更多的开发方式和功能。掌握这些新的功能,势在必行。


对比ABAP数据字典,CDS  (Core Data Services)  作为一种数据建模的新技术/概念,已经在很多项目中采用。关于CDS的学习资料网上已经有很多,但大都专注于某一方面,或对入门者略为抽象,或对熟悉者没有太大价值。本文旨在简而全地介绍和分析此技术,希望对其还不了解的传统ABAPer可以快速地上手,快速了解其特性,给更深入的学习开个头。同时,对于已经在使用此技术的SAP同行,希望可以互相交流,查漏补缺。


  • 为何会出现CDS?

抛开ABAP不谈,几乎任何一种数据库中,都会有定义数据库表、类型或视图的语句,我们一般叫做DDL(Data  Definition  Language),当然,很多数据库也提供图形化建模的方式,在你拖来拖去同时,最终实际生成的也是DDL。HANA来自SAP,因为SAP的业务特性,在产品开发过程中,需要经常地关联业务表、创建很多更方便查看的视图、对标准表/视图进行扩展增强、对数据进行权限控制等。将这些从SAP产品开发/实施中逐渐积累的需求汇总,便有了CDS,它包含最基本的DDL功能,但远远不限于此。

  • HANA CDS vs. ABAP CDS


我最开始在学习CDS的时候,在搜索引擎搜索相关的信息时,经常会看到HANA相关的资料,里面的语句似乎和ABAP半毛钱关系没有,于是觉得这东西太复杂,就放弃了。后来了解到,原来CDS只是个服务统称,在应用中,分为HANA  CDS和ABAP CDS。两者的基本设计目的和架构大致相同,但作为ABAPer,我们实际上更多接触的是后者。
CDS来源于HANA数据库,毕竟HANA的基本属性是数据库,只不过因为是SAP公司推出的,一般跟着SAP产品一起卖。但实际上它是可以作为独立的数据库产品使用的,上层并不一定要接SAP的产品。这样的话,CDS需要有独立于应用层或表现层的功能。这时,我们谈论的就是HANA  CDS。
但如果是使用SAP产品,内置ABAP工作台的,我们不可能所有实施阶段的数据建模,都到HANA数据库层去做,况且我们最常用的是SE11,已经可以满足我们建模的需要。这时,CDS为适应ABAP工作台,集成数据字典,就有了ABAP CDS。
因为ABAP  CDS的平台依赖性,可想而知,对比应用于底层HANA  CDS,肯定有其限制。但也会有其平台相关性的一些内置特性,比如,对于Client的处理(大多数默认情况下,还可以像原来OPEN  SQL一样,不用管MANDT字段,系统会自动取得当前Client的数据。这里不做展开讨论。)当然,ABAP  CDS也不是一成不变的,它的功能也在一直更新,越来越强大。


出于本篇文章的主要目的,下面内容再提到的CDS,都默认指的是ABAP CDS。

  • CDS View为什么只能看不能摸?


使用新版本SAP产品的同学,肯定早就在数据字典里一窥过CDS  View的真容。和View的界面差不多,只不过头部出现的是DDL ID。双击DDL  Source,会出现DDL的代码。同时会出现黄色警告消息:Data Definitions can only be edited using  ADT in Eclipse。


图片.png

图片.png

为什么呢?很明显,对于SAP今后的产品多样化通用化的策略来说,再在ABAP工作台开发一个支持CDS建模的工具,没什么必要了。倒不如直接让其在Eclipse中支持。所以,准备从CDS开始,适应新的Eclipse工具吧,虽然还不像ABAP工作台一样,各个功能间可以双击自由切换,但仅聊代码编辑的话,Eclipse还是更胜一筹的。笔者建议早点下一个试试,早晚会用到。


有两种方式:第一种是下载一个通用版本的Eclipse,再安装一个支持ABAP的补丁包。第二种是下载ADT(ABAP  Development  Tool),直接给你打包好了。两种方式稍有区别,如果你需要开发除ABAP之外的代码,第一种肯定更强大。如果你只需要ABAP相关的开发,第二种更好一些,安装后出错的概率小,也不用关心版本问题。


对于SAP内部员工,提醒一点,如果需要远程支持客户,当前只有ADT可以支持新建一个远程支持项目。I7P在GUI中同样没办法编辑CDS。本文之后的截图都是使用的ADT。


  • 概括CDS的特点及功能

本文目的不在详细地解读每种语句,但最基础的一些CDS的术语,还是需要介绍一下,这样有利于之后的讨论,也会方便读者更详细地查阅资料。如需查阅详细语法,可以参考Help链接:


https://help.sap.com/doc/abapdocu_740_index_htm/7.40/en-US/index.htm?file=abencds.htm
网上随便搜索一下就可以找到创建CDS View教程,我们不再赘述,直接来看一个系统里的Demo:


@AbapCatalog.sqlViewName: 'CDSFRWK_DEMO_1'@EndUserText.label: 'Calculations in SELECT list'@AbapCatalog.compiler.compareFilter: truedefine view CdsFrwk_Sales_Order_Item  as select from snwd_so_i  association [1] to snwd_pd as _product on snwd_so_i.product_guid = _product.node_key{ key snwd_so_i.node_key                                                            as so_item_guid,      parent_key                                                                    as so_guid,      snwd_so_i.product_guid,      snwd_so_i.so_item_pos,      currency_code,      gross_amount,      case net_amount          when 0 then 0          else          cast( ( division( tax_amount, net_amount, 4 ) * 100 ) as abap.dec( 15, 2 ) )      end                                                                           as tax_rate,      division( tax_amount, net_amount, 4 ) * 100                                   as demo,      _product }


这个简单的CDS View包含了以下几个部分/功能:

1. Annotation

@符号之后,冒号之前的一部分(比如EndUserText.label),即为Annotation,我们可以称它为标签。冒号后面的,即为这些标签的值。这些标签简单来讲可以理解为一些配置,CDS的很多功能扩展,基本也都通过此来实现。

它的机制是,当程序执行时,CDS的代码发送给后台,后台会通过CL_DD_DDL_HANDLER的各种方法来解析,并实现相应的功能。而这些标签在后台当然是Hard  code的,在接口IF_DD_DDL_ANNOTATIONS的属性中可以找到它们,ADT中F1也可以查看每个标签的相关文档。

虽然看似简单,一个标签,一个值,但很多标签后都是一整套强大的功能。比如EndUserText.label,看名字知道是来定义标签描述,但其背后是可以和翻译功能很好结合的。可以根据上面提到的标签名,自行查询这些标签的详细功能。这里不一一展开。


可以想象,今后CDS的功能升级和扩展,产品方可以增加可用标签和调整相应的代码。


2. SQL View vs. CDS view entity


在定义CDS时会有几个对象名容易混淆,如果你只想知道怎么用,不在乎原理,记得每次用Open SQL时,From后面只跟Define view后面的那个ID就低了,可以跳过此节。如果你想了解清楚其差异(其实也没什么用),请继续图片.png
如上图所示(图片来自于help.sap.com),在定义CDS时,整段的代码,叫做DDL  source,第一个Annotation:AbapCatalog.sqlViewName的值,叫做SQL View Name,define  view后面跟着的叫做CDS  Entity。在SE11中,在View的地方输入两个名字都是可以访问的。在低版本中,我记得两个名字可以一样,新的版本中系统会有检查。虽然都能访问,但两者代表的对象是不同的,下图(图片来自于help.sap.com)从用户操作角度,给出了它们的关系及区别:图片.png
下图(图片来自于blog.sap.com)给出了各对象在架构中所在的Layer。


图片.png

简而言之,在你激活的那一刻,一个CDS Entity在ABAP应用层生成,同时HANA数据库层,生成了SQL View。

再次强调,在Open SQL中使用时,要用CDS Entity名,这样能更多地发挥其特性。比如,CDS  Entity默认会自动处理Client,你读出的数据会默认为当前Client的数据,这也是我们一般做项目所期望的。但使用SQL  View就不会。另一个原因是,CDS Entity所在的Layer可以默认地处理和数据库的连接,而使用SQL View还会像之前传统的Open  SQL一样,打开一个ABAP层同数据库层的连接,某种意义上会耗费一些资源(这点我不知如何考证,关于performance问题我会在下面单独聊)。

官方只有建议用CDS Entity,但我并没有找到一个官方文档来列举其技术方便的优势。如有读者看到了,记得发给我学习一下。也有人说今后SAP为了避免混淆,可能会停止支持Open SQL使用SQL View Name。

上面提到的Client的处理,有兴趣的,可以阅读下面的Help,各种场景都是支持的,一般我们也不会用到:


https://help.sap.com/doc/abapdocu_752_index_htm/7.52/en-US/abencds_client_handling.htm


另,我在做Demo的时候,还发现一个有趣的现象。默认情况下,ADT中导航栏里看到的DDL名,就是CDS  Entity名,然后下面会有两个子对象:SQL View和CDS Entity。但我尝试在激活前,将CDS  Entity的名字改了一下,会发现,也是可以激活的,对比导航栏,这种子对象的关系就消失了。SE11也不能访问。但双击还是可以显示,我估计是有缓存。

而且,激活后,这些名字也是不能再改的,所以激活前要把名定好。不然只能删了重建。

图片.png

3. Association


上面代码看到的association[1]的信息,就是CDS里最常用的代替JOIN的方法。方括号里值叫做Cardinality。我们之前所使用的JOIN,只从数据层面简单地表明连接两个表之间的字段是哪些,以哪个表为主。而Association,不但有这些功能,还通过两部分数据(不一定是两个表,可能是两个CDS   Entity)的业务内容,给出了其之间的依赖关系。比如,我们看一段DDL,I_SalesDocumentBasic是系统标准的对销售订单的定义:


define view I_SalesDocumentBasic  as select from vbak
 //Association
 //--[ GENERATED:012:GlBfhyFV7kY4hGXbseDAyW  association [0..*] to I_BusinessAreaText            as _BusinessAreaText              on  $projection.BusinessArea = _BusinessAreaText.BusinessArea  association [0..*] to I_BusinessAreaText            as _CostCenterBusinessAreaText    on  $projection.CostCenterBusinessArea = _CostCenterBusinessAreaText.BusinessArea  association [0..*] to I_CreditControlAreaText       as _CreditControlAreaText         on  $projection.CreditControlArea = _CreditControlAreaText.CreditControlArea  // ]--GENERATED  association [0..*] to I_SalesDocumentItemBasic      as _ItemBasic                     on  $projection.SalesDocument = _ItemBasic.SalesDocument  association [0..1] to I_SDDocumentCategory          as _SDDocumentCategory            on  $projection.SDDocumentCategory = _SDDocumentCategory.SDDocumentCategory  association [0..1] to I_SalesDocumentType           as _SalesDocum  entType             on  $projection.SalesDocumentType = _SalesDocumentType.SalesDocumentType


一个销售订单可能有0到多个行项目,所以它和销售订单行项目数据I_SalesDocumentItemBasic的关系是[0..*],而一个销售订单,只能在定义时有一种确定的类型,所以它和I_SalesDocumentType的关系是[0..1]。

在技术特性方面,有一个词很好地概括了Association的特点:“Lazy   Join”。系统如果根据Cardinality判断出某条数据在被结合的数据实体中没有值,那它就不去真的Join,这某种程度上对性能很有帮助。但同样的SQL,如果Cardinality不同,最终出现的结果可能也完全不同,在使用时还是要彻底弄清其含义。


另外,当你在系统中查看CDS  Entity  I_SalesDocumentBasic时,会发现它已经不是简单的从VBAK,VBAP几个表而来,而是将所有与销售订单有关系数据,都结合到了一起,是一种业务对象的概念。S/4HANA系统底层很多逻辑,都慢慢过渡为从CDS  Entity中取值。如果你到系统标准Pakcage里查看,几乎常用的业务对象,都有这种复杂的CDS  Entity的定义,而且根据不同场景,从一个基本定义,封装出了很多更高层更多维度的定义。


所以,我们在之后项目中,如果熟练掌握了这些对象结构,便不用再去费力地寻找各个表之间的关系,针对一组业务对象,直接从一个定义好的CDS Entity,便可以方便快速地获取我们需要的信息。

4. 条件语句

你看到的CASE语句,即为一种条件语句,在一些简单情况下,我们不必再取出所有相关字段,再通过LOOP中进行条件控制。直接将其写在SQL中即可。

5. 内置函数


CDS的SQL中还提供了比较丰富的内置函数,比如常用的:字符串处理、数学计算、日期时间处理、类型转换、金额数量换算、数据统计、coalesce函数。


值得一提的是,字符串处理中还提供了ALPHA函数,平时困扰我们的很多Domain里带有转换ROUTINE的字段,都可以通过此函数解决。

还有,让人值得高兴的时,很多之前在ABAP中只能通过函数来计算的,现在也都有了基本的内置函数,比如日期和时间戳的转换。这些内置函数合理的搭配使用,还是可以做不少事情的。

但内置函数还没到特别灵活的地步,一般参数只支持直接输入,不能再嵌套简单的表达式。比如,我们最常用的合计功能,很多财务数据都是利用一个借贷标识S/H,和一个正的金额来存储数据。当我们要合计这些数据时,没法直接将正负先计算好,再用SUM合计。这时,我们需要先做一个基础的CDS  View,将正负根据借贷标识计算好,再用另一个CDS View来取数。有时复杂点的场景甚至要嵌套三层以上。这点暂时没有太好的解决办法。

丰富的内置函数无疑是要慢慢学习的,可以先大概看一下都有哪些,用的时候再来查详细语法:


https://help.sap.com/doc/abapdocu_752_index_htm/7.52/en-US/abencds_f1_builtin_functions.htm



除上述示例中看到的,CDS还有如下功能:
6. ODATA的发布

这点是通过上面提到的Annotation(@OData.publish: true)实现的,这也使得它可以和Fiori很好的集成。

可以参考以下Help文档:


https://help.sap.com/viewer/cc0c305d2fab47bd808adcad3ca7ee9d/7.5.9/en-US/79cb3bf4eafd4af9b39bc6842e5be8bd.html

7. 权限控制


传统的ABAP开发,会针对Tcode,或代码里的AUHOURITY-CHECK语句等方式对权限进行控制,但这时数据实际已经到了应用层,只是对用户实现了权限控制。CDS  View,提供了DCL(Data Control  Language)语句。这使得权限控制可以直接内置在SQL语句中,在ABAP层,再配合SU21等权限对象的配置来实现。

可以通过下面博客中的例子更直观了解:

https://blogs.sap.com/2017/02/27/abap-cds-views-with-authorization-based-on-access-control/


8. 参数传递


考虑到CDS   View的复用性,参数传递功能肯定是不可少,这点对限制从数据库抽取数据的量,也有很大帮助。参数根据可见性分为两种:一种是可见的,比如传入一个公司代码在WHERE条件中使用;另一种是隐藏的,一般在暴露OData时使用,不用显式地传递,比如执行时直接使用系统登录用户作为值。不过第二种现在也仅仅支持五个,分别对应ABAP工作台中的:SY-MANDT、SY-LANGU、SY-UNAME、SY-DATUM、SY-UZEIT。

可以参考以下Help文档:

https://help.sap.com/viewer/cc0c305d2fab47bd808adcad3ca7ee9d/7.52.2/en-US/97c5057a2302453b97e19641b0d8cbc7.html

9. 扩展性


像我们在Association中提到的,CDS支持扩展,我们可以将标准的CDS Entity通过扩展的方式增加字段或接口。类似于我们在SE11中做APPEND。
10. AMDP (ABAP Managed Database Procedures)


AMDP实际上提供了一种让你直接调用HANA数据库中SQL  Script的功能,类似于Native SQL,让你可以做的事更多,尤其在Open  SQL不够用的时候。举个例子,比如两套独立系统,底层用的是同一套HANA数据库,只是数据分成了不同的Schema。现在系统A由于业务需求,希望防范系统B中的数据。你第一想到的是不是通过接口来实现?有了AMDP,因为它执行的是HANA数据库的SQL  Script,通过简单的配置,就可以直接跨系统访问数据,甚至两个系统的表都可以做Join。

技术原理上实际非常简单,系统留了一个接口IF_AMDP_MARKER_HDB,你只需要创建一个类来实施它。将你的SQL Script写在这个类的某个方法中,需要的时候调用它就可以了。

看到这是不是发现和CDS View没啥关系,技术上来说确实没啥直接关系,只不过两者经常结合使用,所以在此提及。

AMDP的功能细节比较多,可以查看Help文档学习:


https://help.sap.com/doc/abapdocu_752_index_htm/7.52/en-US/abenamdp.htm


11. 其它

AS ABAP 7.53之后,还出现了CDS Hierarchy、Definition of Abstract CDS entity、Definition of Metadata Extensions等,因不太常用,可根据兴趣自行查询,这里只提及收录一下。

文章看到这,以上带数字编号标题的,都是在【概括CDS的特点及功能】下,了解完CDS View的这些特点及功能,下面我们回到High Level来讨论。

  • CDS View的优势是速度快吗?


提到CDS  View,往往会想到数据下沉,给人感觉利用CDS View会比传统的Open SQL更快,这并不是绝对的。有人对比了传统的Open  SQL、CDS View、带有新特性的Open  SQL(支持更多内置功能,变量前需要带@的)三种方法。如果在获取同一条件数据的情况下,执行多次,三者的平均耗时大同小异,CDS  View的表现并没有好多少。这是因为HANA底层的特性,已经使得传统Open  SQL变快。我们想让SQL更快,首先考虑的还是限制数据库到应用层的数据传输量,尽可能地将检索条件指明。


那为什么还要使用CDS   View呢?上面提到的丰富特性和功能,肯定是最重要的原因。还有一个重要的原因就是其复用性。举个简单的例子,如果一个需求是希望在某个表检索后,其中某个字段要经过简单的计算然后输出,并且这样的数据,在一个项目中的很多场景中都会用到。如果用传统ABAP,我们会先Open  SQL取数,然后在LOOP中编辑,最后使用。如果使用CDS View,我们可以直接将这些都放在CDS  Entity里,并且这个Entity是可以在SE11检索到,直接当做一个表来使用。还有,上面也提到,系统也从业务角度,创建了丰富的标准CDS  Entity,我们如果熟悉了这些,也可以直接拿来使用,或者在其基础上定义我们自己需要的。

  • 从辩证主义的角度,讲点劣势?

    CDS  View的使用肯定是个大趋势,S/4HANA底层很多数据建模也都已经替换成了CDS  Entity。如果你去SE11看一些常用的业务表,很多都有替代对象,也就是说即使你用的是某个表,底层系统也会使用其替代对象。这样可以保持原有代码不用更改,可以无缝切换到新的建模。
    但凡事都有利有弊。任何一项新技术的推出(其实已经不新了,国内的项目新技术总是用的晚几年,这样也好,有很多资料可以查),都会带来一些不便。比如,在项目实施和运维过程中,客户的很多开发资源,可能并没有接触过这个技术。如果整个项目在实施期间大量地采用这种方式,对于负责运维的同事,是个挑战。而且,传统项目的开发规范,基本只限制到了ABAP,对于新出现的CDS  View,则没有太多限制,比如命名和整体的建模设计思路,这也会给之后的运维带来困难。
    但技术就是在这样的情况下不断迭代的,SAP的车轮也会一直向前滚动。
    最后,这篇文章的初衷是自己学习的一个总结,所有内容都在阅读了不同来源不同语言的资料后,通过自己的理解组织而成。希望它也同时可以给不同背景的读者一点帮助。
    如果有意见建议,欢迎留言讨论,谢谢。



赞赏支持