项目上有用到CDS和AMDP相关的东西。发现可以记录的东西挺多的,所以写一篇笔记将学习到的东西记录下来。以供后面复习和参考。
CDS 视图基础内容
一、核心数据服务CDS
1.CDS简介
CDS(Core Data Services)是基于SAP HANA的一种新的用于定义语义更加丰富数据模型的架构,表现形式是CDS View。用户可以通过CDS View定义实体类型(如order、BP、Product)以及它们之间的实际联系。CDS使用基于标准SQL的DDL(数据定义语言)语言定义。
2.CDS View作用
- 简化SQL语句
- 提升效率(使数据模型可以在DB层面定义和处理)
3.CDS View类型
(1)按照环境分类
- ABAP CDS:在AS ABAP环境下可以使用的CDS,ABAP CDS是开放的,不仅仅局限于SAP HANA是和数据库无关的。
- HANA CDS:在SAP HANA Studio环境下使用的CDS。
(2)按照是否带有参数分类
- CDS View without Parameters
- CDS View with Parameters
(3)开发者角度分类
- Basic:基本视图。可理解为为查询透明表而创建的视图。
- Composite:综合视图。这种视图大多时候会生成BOPF,就是会包含业务逻辑处理,大多也直接与表关联。常会提供给消费视图使用所以也可以叫做接口视图。有时也会被用作分析复杂逻辑用的分析类视图。
- Consumption:消费视图。通常是生成提供OData消费使用。用于实现GetEntity与GetEntitySet等方法。
(4)HAVA CDS 与ABAP CDS差异
① 相同点
ABAP 和 HANA环境的View都是基于DDIC中已经存在的Table进行创建。
② 不同点
- HANA CDS必须创建对应与DDIC Table的并作为CDS View一部分的基本实体类型。
- ABAP CDS需要考虑DDIC底层的所有Table View和CDS View内的类型,避免重复。
(5)AS ABAP使用HANA数据库作为中心数据库
AS ABAP使用HANA数据库作为中心数据库时,使用ABAP CDS 和HANA CDS 的场景
- 如果要在ABAP中将CDS实体用作数据类型或者Open SQL的访问对象,或者想要评估ABAP CDS中定义的annotations,则必须使用ABAP CDS。
- 如果不需要在ABAP中访问CDS实体,但是希望将它与其他ABAP存储库(repository)对象一样进行传输和升级,那么可以使用ABAP CDS。
- 如果不将CDS实体用作数据类型或者Open SQL的访问对象,则可以使用HANA CDS,后者更好地集成到SAP HANA中,然而在ABAP中只能使用Natice SQL(ADBC、AMDP)进行访问。
注意事项:
- 对于每个CDS视图,在激活时都会在数据库中创建一个对应的数据库视图(SQL视图,可以在HANA环境中访问该数据库视图)。
- CDS表函数由AMDP管理,还可以在本地访问相应的数据库函数。
- 在HANA本地环境中访问数据库视图(通过ABAP CDS视图生成)时会同时考虑相应的DCL中定义的授权逻辑。
(6)基本视图
① 含义
可理解为查询透明表而创建的视图。一般不会关联其他的业务表,只是作为查询表数据的视图使用。有很多的标准表也有基本视图,例如Mard的NSDM_V_MARD、MCHB表的NSDM_V_MCHB等。这些替代对象都是标准表的CDS视图,当我们在SAP使用SQL语句对这些表进行查询时其实他们是查询的替代对象(CDS视图)。
② 基本视图条件
作为基本视图还必须满足下面的条件:
- 公开了所有相关的业务数据;
- 可以直接访问数据库表和其他基本视图;
- 可以与其他基本视图相关联;
- 无冗余数据。
(7)复合视图
① 含义
复合视图仅使用基本视图和由基本视图中的关联提供的数据。可以简单理解为是根据业务需求将多个基本视图关联起来使用。例如如下业务场景,我们需要开发一个用于展示公司库存信息的视图,根据需求我们需要将批次库存与特殊库存组合到一个视图中进行展示。在这个业务场景中我们需要使用到的标准表与基本视图如下:
| 库存类型 | 标准表 | 基本视图(代理对象) |
|---|---|---|
| 工厂级别库存 | MBEW | MBVMBEW |
| 库存地点库存 | MARD | NSDM_V_MARD |
| 供应商寄售库存 | MKOL | NSDM_V_MKOL |
| 客户寄售库存 | MSKU | NSDM_V_MSKU |
| 供应商外包库存 | MSLB | NSDM_V_MSLB |
| 销售订单库存 | MSKA | NSDM_V_MSKA |
| 批次库存 | MCHB | NSDM_V_MCHB |
在编写上面的业务需求时,需要在CDS开发工具中(HANA Studio/Eclipse)中将上面的基本视图组合在一起将所有的库存信息查询出来。
② 复合视图条件
- 可以访问基本视图和其他复合视图;
- 本质上,引入了数据冗余;
- 复合视图是可重用的;
- 可以与其他基本视图相关联。
(8)消费视图
① 含义
消费视图通常称为分析视图,一般是生成提供给OData消费使用。用于实现GetEntity与GetEntitySet等方法。
② 消费视图条件
- 应报告其数据的子集,即提供基本数据的界面视图(尺寸视图或分析视图)上的投影和(可选)全局过滤器;
- 限制或计算所需的参数;
- 特定的限制措施,而不是重用视图中包含的基本措施;
- 特定的计算量度,特别是那些在聚合后需要计算的量度;
- 异常聚合,例如,实体计数器;
- 主数据文本和显示属性,通常与此报告相关;
- 用于此查询的报表中的层次结构;
- 参数和过滤器用作变量;及其静态或派生的默认值;
- 默认显示形式,用于在通用UI中高度可用的初始显示(轴:行与列,总计开/关,层次开/关等)。
上面三种视图(基本、复合和消费视图)介绍内容摘自《CDS从入门到精通–2视图的类型》
4.SAP系统中的CDS View
在数据库表TADIR中查询条件PGMID = ‘RTR3’,OBJECT = ‘DDLS’,可以在列DEVCLASS(Package)中找到所有DDL源代码和每个源代码的包,根据该包可以使用ADT(HANA Studio中的ABAP开发工具)来查看DDL源代码。
DDLDEPENDENCY表中包含了所有DDL源的名称和其中定义的CDS实体名称(列OBJECTTYPE的值为STOB),以及生成的数据库视图的名称(列OBJECTTYPE的值为VIEW),对于每个DDL源都有两行数据。
在CDS中必须有两个名称:
- 一个名称用于在数据字典中创建SQL视图(可以使用SE11查看该名称)
- 一个用于CDS视图实体,该实体用于Eclipse查看和维护
注:SQL View 和CDS View命名不能相同,可以使用SE11查看SQL视图但是不能修改;只有CDS View Entity才是我们在程序中的Select语句中使用的对象(作为data source使用)。
5.CDS的显著特征
(1)CDS是SQL的一种增强,它为我们提供了一种数据定义语言(DDL),用于在数据库中定义语言丰富的额数据表/视图(CDS实体)和用户定义的类型。
(2)增强点如下:
- **Annotations:**丰富了带有附加(特定领域的)元数据的数据模型,一个annotation就是一行以@开始的代码。
- **Associations:**概念级别的关联,用于查询中简单的路径表达式替代连接。
- **Expressions:**在数据模型中用于计算和查询的表达式。
(3)CDS视图可以通过ABAP数据字典管理,在CDS激活时,在HANA层上会创建一个数据库视图,但是只有ABAP CDS视图(CDS实体即DDL源)必须通过ABAP CTS传输。
- 语义更加丰富的数据模型
- 特定领域的语言(DDL、QL、DCL)
- 声明更接近于概念思维
- CDS完全基于SQL
- 标准SQL的特性都可以在CDS上直接使用
- 与所有的DB产品兼容
- 生成并管理SQL View
- 与SAP HANA的天然整合
- 与特定领域的 Framework有着通用的基础,例如UI、Analytics、OData
- 丰富的内置函数和代码下放
- 突破场景的Table Function
- 丰富的内在SQL函数
- 可扩展性
- 在建模层面可扩展
- 在元模型层面可使用注释
二、CDS视图的创建与调用
1.开发工具
(1)开发工具介绍
CDS View的开发工具主要有两种,一种是添加了ABAP开发插件的Eclipse,另一种是SAP官方推出的HANA Studio。两者在使用方面没有什么明显的区别,但是在这里介绍一下如何使用这两种开发工具去创建CDS视图。
这里有个注意事项,那就是使用下面两种开发工具开发之前都需要确保你的电脑安装有SAP GUI,并且其中有SAP客户端的连接信息。因为后面在连接SAP系统时的信息是从SAP GUI中获取的。
如果有需要开发工具的可以在评论区联系我,我这边有Hana Studio。
(2)Eclipse 2021 ADT
① 安装插件
使用Eclipse作为开发工具前需要先安装一个ABAP Development Tools插件。
② 连接SAP GUI
想要使用CDS视图则必须要将CDS的运行设置在自己系统的服务器上。所以在开始使用CDS之前必须先让Eclipse连接到自己的服务器。
点击Eclipse左上角的File –>New –>Project。
选择创建ABAP Project。
选择要连接的开发系统。
进入下一步,在这一步存在三个必输项,但是必输项的内容会从你之前选择的系统带过来所以直接下一步即可。
接下来就和登录SAP GUI一样输入客户端号、用户名、密码和语言种类。
当创建好ABAP Project后会在整个页面的最左边查看到刚刚新建好的ABAP Project。此时的项目名称为登录的系统名_客户端号_登录用户名_语言种类。
注意事项:一个ABAP Project只能只有一个人的账号,即一个项目与一个账号绑定。如果要使用别的账号创建CDS视图则需要使用新账号重新创建CDS视图。
(3)HANA Studio 连接SAP
① 新建ABAP Project
点击HANA Studio左上角的File -> New -> ABAP Project。
② 选择连接的系统
点击后会弹框你存储在SAP GUI中的系统信息,此时选择你需要连接的系统即可。后续会将系统的信息全部带出来,所以只需要一直下一步到输入登录系统的账号密码那一步即可。
选择号系统后点击下一步按钮会自动从你的SAP GUI中将SAP系统信息带出来。直接下一步即可。
③ 登录系统
进行完上面的操作之后到这一步就是输入密码登录SAP系统了。完成之后就会在左侧发现成功连接上的ABAP Project了。
ABAP Project创建成功。
2.创建CDS视图
(1)新建一个CDS视图
当你创建过CDS视图后,你可以在你的对应包/本地下面找到一个Core Data Services文件夹,在其下有一个Data Definitions文件夹。在这个文件夹下面就是你新建的所有CDS视图对象了。你可以直接在Data Definitions文件夹上单机鼠标右键新建一个CDS对象。但是考虑到可能有人没有创建过CDS视图,所以下面的步骤从包/本地的层级下新建CDS视图。
(2)Other ABAP Repository Object
在包名上右键按照下图所示的内容新建对象。
(3)Core Data Services -> Data Definitions
在弹出的框中寻找Core Data Services文件夹下的Data Definitions对象。单击Next。
(4)New Data Definitions
到这一步开始就和最上面提到的从Data Definitions文件夹新建的步骤对接上了。在那个位置新建CDS对象就会弹出下面的弹框输入CDS视图的名称,存放视图的包和视图描述信息等。
(5)选择传输的请求号
填写完上述的信息后单机Next。如果你存放的不是本地包,则需要为当前新建的CDS对象选择一个请求号对象。若是本地对象则继续Next即可。不要点击Finish。
(6)选择创建的模板
介绍一下我们开发工具(HANA Studio/Eclipse)创建CDS时的模板。为了方便开发人员开发CDS视图,开发工具本身提供了很多能简化开发的CDS模板程序。下图便是创建CDS时开发工具提供的模板内容。我们一般常用的就是图中所示的模板内容,但其实还有很多其他的例如需要关联其他视图或数据表的Define View with Join模板;用来开发带参数的CDS的模板Define View with Parameters等。
模板的种类很多,具体要使用什么模板可以根据技术的需求参照模板右侧的文本描述和下面的参考代码选择。
有个注意事项,当你在第(3)或(4)步点击Finish的话,开发工具会自动创建你上一次使用的模板对象。即如果你上次选择的是Define View模板的话,这次创建的CDS模板也是Define View。
(7)编写CDS代码
在新创建好的视图中编写如下内容:
1 | @AbapCatalog.sqlViewName: 'YTEMPLATE1_V' // SAP CDS视图名称 |
在上面的第一个注解后可以看到注释是SAP CDS视图名称。指在SAP中的视图名称。YTEMPLATE1_CDS是CDS视图实体对象,而YTEMPLATE1_V是CDS视图对象。如果要在SAP使用这个视图就需要使用到YTEMPLATE1_V这个名称。
3.在开发工具中运行CDS
当你在开发工具中开发完成一个CDS对象后如果想要查看运行结果可以按照下面的步骤进行。
(1)编写CDS视图并激活
(2)运行CDS视图
在视图的编辑框上右键或点击横幅上面的运行按钮选择ABAP Application。运行CDS视图。
(3)结果展示
4.删除CDS视图
选择你要删除的视图,右键删除按钮即可。
5.CDS视图的传输
当创建的CDS视图不是在本地存储时,系统会需要CDS绑定一个CTS号(SE09中的请求号)。但是在传输CTS时只有CDS视图实体保存在CTS中。所有变更对象和传输都在ABAP层进行端到端的管理,不需要传到较低层级二点数据库层来管理CDS实体和组件的传输。
6.带参数的CDS视图
(1)参数介绍
在as select语句前视图名称之后使用关键词,设置完该参数之后在调用视图时需要先输入参数值才能继续执行。类似于必输筛选字段。
1 | with parameters 变量名 : 参照的字段类型, |
(2)创建带参数的CDS视图
先填入CDS视图的名称与描述信息,然后一直下一步到选择模板的界面。
选择图中所示的模板,该模板代表创建的是带参数的CDS视图。
(3)编写视图逻辑
1 | @AbapCatalog.sqlViewName: 'YPARAMETERS_V' |
在声明参数时有两种定义类型的方式,一种是直接使用SE11数据字典中的类型,另一种是SAP的基本数据类型。
而在调用参数时也有两种方法,一种是在参数前加:引用,另一种是使用**$parameters.**的方式调用。
(4)执行CDS
在执行时如上面所说的,声明了参数就相当于是必输参数,在使用视图时需要先为参数赋值。完成之后再运行视图。
运行结果。
三、CDS系统变量
1.介绍
CDS中的系统变量一般是以**$session**作为开头来使用的,和SAP的系统系统变量是一样的效果。主要是下面四个变量。
| 变量名 | 用途 |
|---|---|
| $session.user | 当前用户 id 与 ABAP中系统字段 SY-UNAME 的值一样 |
| $session.client | 当前客户端,默认值与 SY-MANDT 一样,在Open SQL中使用 USING CLIENT语句指定,在 ABAP 中调用设定了 AMDP OPTIONS CDS SESSION CLIENT的AMDP方法时,需要指定 |
| $session.system_language | 当前内部会话的文本环境语言,ABAP中系统字段 SY-LANGU的值 |
| $session.system_date | ABAP 的当前日期,ABAP中系统字段SY-DATUM的值 |
使用的方法和上面使用参数创建的CDS一样,在需要引用的位置按照**$Session.vname**的形式进行使用。
2.示例
(1)作为关联条件
1 | @AbapCatalog.sqlViewName: 'YSYSTEM_VAR_V' |
(2)作为Where筛选条件
1 | @AbapCatalog.sqlViewName: 'YSYSTEM_VAR_V' |
四、CDS 语法介绍
1.基本语法
(1)Select
① 用途
和普通的SQL语句类似,代表查询。
② 示例
1 | define view YTEMPLATE1_CDS |
(2)Key
① 用途
用来标识视图中的主键字段。
@AbapCatalog.preserveKey: true 这句annotation 的值为TRUE时,SQL view中的key字段使用CDS中定义的key; 值为FALSE时,使用DB table中table的key field.
② 示例
1 | @AbapCatalog.sqlViewName: 'YTEMPLATE1_V' |
③ 效果截图
注解为True时
注解为False时

(3)Select Distinct
① 用途
在最终查询出来的结果集中对所有字段进行去重。值得注意的是无法只根据个别字段进行去重,只能根据整个结果集去重。
② 示例
1 | define view YTEMPLATE1_CDS |
③ 效果截图
示例代码运行结果
数据库表运行结果

(4)Where语句
① 用途
用来对数据进行筛选的条件语句,一般添加在CDS语句的最后。
② 示例
1 | define view YTEMPLATE1_CDS |
③ 运行结果
2.CDS 聚合与Join
(1)聚合函数
① 用途
注:在使用聚合函数时需要同时使用Group By语句对数据进行分组。
| 函数名称 | 函数描述 |
|---|---|
| MIN | 获取操作数的最小值 |
| MAX | 获取操作数的最大值 |
| AVG | 操作数的平均值(操作数必须是数字)。只有添加AS dtype时才支持类型INT8。不支持用于十进制浮点数的类型DF16、DF34。也不支持类型DATN、TIMN和UTCL。 |
| SUM | 操作数之和(操作数必须是数字)。不支持用于十进制浮点数的类型DF16、DF34。也不支持类型DATN、TIMN和UTCL。 |
| COUNT | 如果指定了DISTINCT操作数,则计算操作数的不同值数;如果指定为*,则计算结果集中的总行数。 |
② 示例
1 | define view YTEMPLATE1_CDS |
③ 运行结果
(2)Group By
① 用途
该语句是分组语句,一般不会单独使用。使用时基本都是和聚合函数一起使用。详细的使用方法和示例可以参照上面的结果。
(3)Having
① 用途
和Group By语句不同,该语句只能使用在有聚合函数的CDS中。其作用是针对聚合函数的结果再做一边筛选。例如我想要筛选出price字段最大值在600以上的数据,就可以按照下面的语句编写。
② 示例
1 | define view YTEMPLATE1_CDS |
③ 运行结果
可以发现运行结果和上面的相比没有最大价格在600以下的数据。
(4)Join
① 用途
| 连接类型 | 连接描述 | 理解 |
|---|---|---|
| left outer join | 将主数据源中的记录与辅助数据源的记录联接,以便 主数据源的所有记录都包含在结果中。 | 将主表的所有数据展示出来,辅助表的数据有则展示,无则返回Null |
| right outer join | 将主数据源中的记录与辅助数据源的记录联接,以便 辅助数据源的所有记录都包含在结果中。 | 将辅助表的所有数据展示出来,主表的数据有则展示,无则返回Null |
| inner join | 将来自主数据源的数据与来自辅助数据源的数据联接,以便 结果包含来自主数据源的所有数据,辅助数据源中至少有一个联接伙伴 存在。 | 取两个表的交集部分 |
| cross join | 将主数据源的所有记录与辅助数据源的所有记录合并。 生成的数据集包含的条目数等于主数据源中的记录数乘以 辅助数据源中的记录数。 | 将两个表的所有数据都取出来,然后按照笛卡尔积的形式进行组合。 |
使用上面的关联条件时有个注意事项,那就是当你使用了关联的同时,还是使用了Where子句当满足下面的条件时将会将结果变为inner join。
- 左外连接:Where子句的筛选条件包含了辅助表(关联表)的字段进行筛选时
- 右外连接:Where子句的筛选条件包含了主表的字段进行筛选时
- cross join:使用Where子句时结果变为inner join
② 示例
left outer join
1
2
3
4
5
6
7
8
9
10
11
12
13
14define view YJOIN_TEST_CDS
as select distinct from sflight as s
left outer join scarr as r
on r.carrid = s.carrid
left outer join spfli as p
on p.carrid = s.carrid
and p.connid = s.connid
{
key r.carrid,
key p.connid,
s.planetype,
p.distance,
r.carrname
}请注意下图红框圈中的数据,该条记录是我手动添加在sflight表中的数据。该条记录在另外两个外键表scarr与spfli中是没有相关记录的,所以才会在引用了这两张外键表字段的列中显示为初始值。
但是因为使用的是左外连接,所以在关联时会将主表sflight的所有数据都罗列出来。而下面红框圈中的数据虽然在两外键表中不存在,但因是主表的数据所以也被展示出来了。
right outer join
1
2
3
4
5
6
7
8
9
10
11
12
13
14define view YJOIN_TEST_CDS
as select distinct from sflight as s
right outer join scarr as r
on r.carrid = s.carrid
right outer join spfli as p
on p.carrid = s.carrid
and p.connid = s.connid
{
key r.carrid,
key p.connid,
s.planetype,
p.distance,
r.carrname
}使用右外连接会将关联表的所有数据都展示出来,而主表的数据不存在时则不会展示。和上面的数据对比后发现上面红框圈起来的只在主表存在的数据并没有被展示出来。因为这条数据在另外两张表中是不存在的。
inner join
使用下面语句时我们先将sflight表中所有的 AA 0017的数据全部删除掉,然后使用下面的SQL查询结果。
1
2
3
4
5
6
7
8
9
10
11
12
13
14define view YJOIN_TEST_CDS
as select distinct from sflight as s
inner join scarr as r
on r.carrid = s.carrid
inner join spfli as p
on p.carrid = s.carrid
and p.connid = s.connid
{
key r.carrid,
key p.connid,
s.planetype,
p.distance,
r.carrname
}由上面的连接条件得知在另外两张表中是存在Carrid字段为AA,Connid字段为0017的数据的。但是当我们删除掉主表sflight中对应的数据后,在下面的结果中并没有展示出来我们删除的数据,而是取出来了三个表中都存在的数据。所以可看出inner join是获取关联表与主表的交集数据的。
cross join
这种关联方式上面提过,是将关联的表的所有数据按照笛卡尔积的形式组合起来。下面对笛卡尔积进行解释。
存在两个集合A与B,其包含的值如下所示:
A = { 1,2 } B = { 3,4,5 }
两个集合交叉关联或说进行笛卡尔积 A×B B×A。
A×B = { (1,3),(1,4),(1,5),(2,3),(2,4),(2,5) }
B×A = { (3,1),(3,2),(4,1),(4,2),(5,1),(5,2) }
通过上面的演示可以发现笛卡尔积满足下面的条件:
- 两个结果不满足A×B = B×A的交换律
- 集合总个数 = A集合总个数 × B集合总个数
1
2
3
4
5
6
7
8define view YJOIN_TEST_CDS
as select distinct from spfli as s -- 14条记录
cross join scarr as r -- 18条记录
{
key r.carrid,
key s.connid,
r.carrname
}可以看到最终运行出来的总条数是 14 × 18 = 252条记录,我防止查询的最大展示条数为300。

(5)union
① 用途
将两个或多个结果集合并到一起输出,但是每个子结果集的字段名与数量等必须一致。十分好用的一个语句,当我们有需求需要将多个SQL的结果合并到一起时可以使用这个语句。他有两种合并方式。
- union:将结果集进行合并,当存在相同的数据时只展示其中一条。可理解为合并结果集时进行去重。
- union all:同样将结果集进行合并,但是不会对其中的数据进行去重,直接将结果集的数据原样有多少就合并多少。
② 示例
union
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18define view YJOIN_TEST_CDS
as select distinct from spfli
{
key carrid,
key connid,
countryfr,
cast( '' as abap.char( 20 ) ) as carrname
}
union
select distinct from scarr
{
key carrid,
key cast( '' as abap.numc( 4 ) ) as connid,
cast( '' as abap.char( 3 ) ) as countryfr,
carrname
}union all
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18define view YJOIN_TEST_CDS
as select distinct from spfli
{
key carrid,
key connid,
countryfr,
cast( '' as abap.char( 20 ) ) as carrname
}
union all
select distinct from spfli
{
key carrid,
key connid,
countryfr,
cast( '' as abap.char( 20 ) ) as carrname
}
③ 运行结果
union
沿用上面测试spfli表和scarr表的总数据条数可以看到合并后集合总数为 14 + 18 = 32。
union all
这次直接将两个SQL写成一样的,然后使用union all语句对结果进行验证发现合并时并没有将重复的数据去重,而是直接合并在一起了。

五、CDS视图中的内置函数
1.数值运算函数
(1)内容
| 方法名称 | 描述 |
|---|---|
| ABS(arg) | arg的绝对值 |
| CEIL(arg) | 不小于arg的最小整数 |
| FLOOR(arg) | 不大于arg值的最大的整数 |
| DIV(arg1,arg2) | arg1 除以 arg2。但是仅允许输入整数,且返回的结果也只是整数 |
| DIVISION(arg1,arg2,dec) | 常规除法,结果四舍五入到小数点后dec位。但是无法传入浮点数 |
| MOD(arg1,arg2) | 常规余数运算,计算余数值 |
| ROUND(arg, pos) | 按照指定的保留pos位小数,然后四舍五入的值 |
(2)代码示例
1 | define view YBUILTFUNCTION |
(3)运行结果
2.字符串函数
(1)内容
| 方法名称 | 描述 |
|---|---|
| LENGTH( str ) | 返回字符串str的长度 |
| INSTR( str, find ) | 返回字符串str中find字符/字符串所在的位置索引 |
| CONCAT( str1, str2 ) | 拼接两个字符串 |
| CONCAT_WITH_SPACE( str1, str2, space ) | 在两个字符串拼接处添加space(整数)个空格 |
| LEFT( str, len ) | 从左向右截取字符串str的len(整数)位,可以用在关联条件中 |
| RIGHT( str, len ) | 从右向左截取字符串str的len(整数)位,可以用在关联条件中 |
| LOWER( str ) | 将字符串str转换为小写 |
| UPPER( str ) | 将字符串str转换为大写 |
| LPAD( str1, len, str2 ) | 字符串填充,从字符串str1的最左侧填充字符串str2。最后填充后的字符总长为len。 |
| RPAD( str1, len, str2 ) | 字符串填充,从字符串str1的最右侧填充字符串str2。最后填充后的字符总长为len。 |
| LTRIM( str, cha ) | 从最左侧开始删除字符串str中的字符cha,直到字符串str1中的第一个字符不为cha为止 |
| RTRIM( str, cha ) | 从最右侧开始删除字符串str中的字符cha,直到字符串str1中的第一个字符不为cha为止 |
| REPLACE( str1, str2, str3) | 在字符串str1中寻找字符/字符串str2替换为字符/字符串str3 |
| SUBSTRING( str, pos, len ) | 从做开始的第pos(正整数)位截取字符串str长度为len(正整数)的内容 |
(2)代码示例
1 | define view YSTRINGFUNC |
(3)运行结果
3.日期函数
(1)内容
下表中所有的Error均为参数中日期异常时的处理方案,均为可选。
| 方法名称 | 描述 |
|---|---|
| DATS_ADD_DAYS( dats, day, [error] ) | 为日期dats新增或减去day天。day为正数时为加,负数时为减 |
| DATS_ADD_MONTHS( dats, month, [error] ) | 为日期dats新增或减去month月。error为异常时的处理方案 |
| DATS_DAYS_BETWEEN( dats1, dats2 ) | 计算两日期间相差的天数。 |
| DATS_IS_VALID( dats ) | 校验dats是否时有效日期。有效返回1,无效返回0。 |
下表是异常处理状态表
| 异常名称 | 描述 |
|---|---|
| FAIL | 发生错误时,运行一个异常状态 |
| NULL | 发生错误时返回null |
| INITIAL | 发生错误时返回initial |
| UNCHANGED | 发生错误时返回一个未修改的日期值 |
(2)代码示例
1 | define view YDATETIMEFUNC |
(3)运行结果
4.时间函数
(1)内容
| 函数名称 | 描述 |
|---|---|
| TIMS_IS_VALID( tims ) | 判断传入的tims字段是否是时间数据 |
| TIMS_TO_TIMN( tims, [error] ) | 将时间tims转换为timn类型 |
| TIMS_FROM_TIMN( timn, [error] ) | 将timn类型转换为tims类型 |
(2)示例代码
1 | define view YDATETIMEFUNC |
(3)运行结果
5.时区与时间戳函数
(1)内容
| 函数名称 | 描述 |
|---|---|
| ABAP_SYSTEM_TIMEZONE( client, [error] ) | 获取传入客户端的时区 |
| ABAP_USER_TIMEZONE( user, client, [error] ) | 获取用户主数据的时区 |
| TSTMP_CURRENT_UTCTIMESTAMP( ) | 获取当前的时间戳 |
| TSTMP_IS_VALID( tstmp ) | 判断传入的字段是否是时间戳格式 |
| DATS_TIMS_TO_TSTMP( dats, tims, timezone, client, [error] ) | 将传入的日期dats和时间tims组合成时间戳。timezone时区,client客户端 |
| TSTMP_ADD_SECONDS( tstmp, sec, [error] ) | 为时间戳tstmp加/减去sec秒 |
| TSTMP_SECONDS_BETWEEN( tstmp1, tstmp2, [error] ) | 计算两时间戳字段之间相差的秒数 |
| TSTMP_TO_DATS( tstmp, tzone, cilent, [error] ) | 从传入的时间戳中获取日期,返回D类型数据 |
| TSTMP_TO_TIMS( tstmp, tzone, cilent, [error] ) | 从传入的时间戳中获取时间,返回T类型数据 |
| TSTMP_TO_DST( tstmp, tzone, cilent, [error] ) | 将时间戳数据转换为DST数据 |
(2)示例代码
1 | define view YDATETIMEFUNC |
(3)运行结果
6.计量单位转换函数
(1)函数介绍
1 | unit_conversion( quantity => 重量数值, |
(2)其余内容
异常处理方式有两种。单位转换和货币转换两种的异常处理方式都是一样的。
| 异常处理名称 | 异常处理描述 |
|---|---|
| FAIL_ON_ERROR | 异常处理的默认值,发生异常时抛出异常 |
| SET_TO_NULL | 异常时返回NULL值 |
| KEEP_UNCONVERTED | 异常时返回一个未转换的货币金额 |
计量单位的转换规则使用事务代码CUNI进行维护,数据存储在T006表中。而在SAP中可以使用下面的Function对计量单位进行转换。详细的可以参考这篇博文:SAP 基本单位与物料计量单位间的转换。里面介绍了这三种SAP中单位转换的Function并附有参考代码。
| 函数名称 | 函数描述 |
|---|---|
| UNIT_CONVERSION_SIMPLE | 基本单位间的转换 |
| MD_CONVERT_MATERIAL_UNIT | 计量单位之间转换 |
| MATERIAL_UNIT_CONVERSION | 每基本单位等于多少计量单位 |
(3)代码示例
1 | define view ZUNITCONVERSION |
(4)运行结果
7.货币转换函数
(1)函数介绍
1 | currency_conversion( amount => 货币金额, |
(2)其余内容
使用该内置函数转换货币金额时需要传入汇率日期,函数会自动去数据库表TCURR中查找对应的汇率信息。当你填入的汇率日期在数据库表中不存在或小于对应的有效期则会报错。此时就需要使用事务码OB08或视图V_TCURR去维护汇率信息。
即使内置函数使用的是SAP一样的功能模块和相同的规则等信息,但是因为舍入规则等并无法保证两者得到的结果是一致的。
查看SFLIGHT表中的货币类型为 USD(美元)、EUR(欧元)、JPY(日元)、AUD(澳元)和SGD(新加坡货币)。所以在视图V_TCURR中维护它们几种货币M类型的汇率信息。
(3)代码示例
1 | define view YCURRENCYCONV |
(4)运行结果
8.小数点移位函数
(1)函数内容
该函数会根据传入的货币金额还有货币的币种来处理货币的小数点位置,例如日元和韩元货币是没有小数点的,但是在航班表中金额却是带小数点的,这是因为在数据库表中韩元和日元被缩小了100倍,此时就可以使用小数点移位函数来处理这种货币。
1 | decimal_shift( amount => 转换用的货币金额 |
(2)示例代码
1 | define view YDECIMALSHIFT |
(3)运行结果
9.处理NULL函数
(1)函数内容
在CDS中关联其他视图或数据表对象时当关联不到数据时就会返回Null。而需要对返回Null的字段做初始值设置就可以使用函数COALESCE。
当field1字段为Null时,返回Value值。Value值可以是常量、变量或另一字段值。反之当field1字段不为Null时就返回field1字段值。
1 | coalesce(field1, value) |
(2)示例代码
1 | define view YTEMPLATE1_CDS |
(3)运行结果
10.Case … When … Then …
(1)语法介绍
该语法和ABAP新语法的用法其实一样,既可以使用Case 变量 When 变量值1 Then 返回值 …的形式,也可以使用Case When 表达式1 Then 返回值 …的形式。代表的都是类似于if语句的判断语法。
1 | --方式一 变量+常量形式 |
(2)示例代码
1 | define view YCASEWHEN_CDS as |
(3)运行结果
11.Cast类型转换函数
(1)语法介绍
在CDS视图中进行强制类型转换的函数。可以将操作数转换为ABAP字典类型或数据元素。但是在添加时有如下注意事项。
- 数据元素:将操作数转换为数据元素时可以指定可选的PRESERVING TYPE。但如果使用了此方法,则内置数据类型、操作数长度和小数位以及目标数据类型必须完全匹配。
- 字典类型:ABAP中的基本数据类型,如果指定这种类型则无法使用可选的PRESERVING TYPE。
下图是用于指定内置数据类型的表格图片。
允许的操作数类型:
- 常量文本对象
- 当前的CDS视图字段
- 标准系统变量
- 带参数视图的参数
- 聚合表达式
- 一个路径表达式,用于标识数据源data_source的字段
- 内置函数
- 算数表达式
- case的返回值/case语句
- 嵌套的强制类型转换表达式
下表显示了ABAP字典中内置数据类型的哪些组合当前可以相互转换,以及每种情况下的要求。每个组合都有一个特殊的转换规则列表。
与”X”组合使用时无需注意其他限制。以下规则适用于其他组合:
- 与”Y”组合使用时,目标数据类型的长度必须足够
- 与”Z”组合使用时,数据类型长度必须完全匹配
- 在”P”或”D”组合情况下,必须将数据元素指定为目标数据类型。无法从ABAP字段中指定内置数据类型。
- 与”D”组合使用时,数据元素可以具有符合上表的合适目标类型和任何长度。
- 与”P”组合使用时,数据元素必须具有内置的数据类型,并且长度与操作数的数据类型相同。
在类型不兼容的情况下,操作数的内容将转换为目标类型(如果值不合适,则可能引发异常)。在兼容类型中,会出现语法检查警告(除非使用添加的PRESERVING type将目标数据类型指定为数据元素)。
(2)示例代码
1 | define view YJOIN_TEST_CDS |
(3)运行结果
六、CDS的注解开发
下面的注解只是一小部分,我在总结的时候发现注解相关的内容太多了,所以要另开几篇笔记记录。到时候把链接贴在这个地方,下面写的这部分先作个参考吧。请注意下面的注解不是全部。
1.SAP ABAP CDS view里的注解在ABAP后台是如何被解析的
SAP ABAP CDS view里的注解在ABAP后台是如何被解析的?
2.ABAP 字典名称注解 AbapCatalog.sqlViewName
(1)注解
1 | @AbapCatalog.sqlViewName: ‘<SQL VIEW NAME>’ |
(2)描述
ABAP字典中CDS数据库视图名称。最有多由16个字符组成的字符串。字符串由字母数字和下划线组成。可以简单理解成该CDS视图在ABAP中使用的名称。
CDS的视图每个定义都必须包含ABAP注解。
(3)示例
1 | @AbapCatalog.sqlViewName: 'YSYSTEM_VAR_V' |
在SAP的数据字典中如下所示。在使用时需要使用的是在注解**@AbapCatalog.sqlViewName**中书写的名称。
如果直接使用CDS Entity的名称则会提示需要在相应的开发工具中查看视图。
3.CDS视图的过滤条件 AbapCatalog.compiler.compareFilter
(1)注解
1 | @AbapCatalog.compiler.compareFilter: ‘<VALUE>’ |
(2)描述
定义CDS视图的路径表达式中过滤器条件的评估。
(3)可能的值
- true:比较路径表达式中多次出现的CDS关联的过滤条件,如果它们匹配,则只创建一次相关联的联接表达式。
- false:对于具有过滤条件的每个CDS关联,将创建并评估单独的联接表达式。
4.访问CDS的隐式访问控制 AccessControl.authorizationCheck
(1)注解
1 | @AccessControl.authorizationCheck: ‘<VALUE>’ |
(2)描述
定义ABAP SQL用于访问CDS视图时的隐式访问控制。可简单理解成权限检查。
(3)可能的值
- #CHECK:如果ABAP SQL用于访问视图,则在为视图分配CDS角色的情况下隐式执行访问控制。如果视图没有角色,则会出现语法检查警告。
- #NOT_REQUIRED:类似#CHECK,但没有语法检查警告。
- #NOT_ALLOWED:不执行访问控制。这会在视图的角色的DCL源代码中生成语法检查警告。
- #PRIVILEGED_ONLY:Privileged CDS association (evaluated by SADL).
以下内容摘自:ABAP CDS注解详解 与 访问控制注释
ABAP CDS 支持基于数据控制语言 (DCL) 的访问控制。ABAP CDS 中的访问控制进一步限制了从 ABAP CDS 中的 CDS 实体返回的数据。CDS 访问控制基于以下几点:
使用 DCL 语句 DEFINE ROLE 定义的 CDS 角色。目前,CDS 角色隐式映射到每个用户。这就是为什么它们也被称为映射角色的原因。
在 CDS 角色 CDS 实体中定义的访问条件。访问条件可以如下:
- 将 CDS 实体的元素与文字值进行比较的文字条件。
- 将 CDS 实体的元素与 SAP 授权概念中的授权相关联的 PFCG 条件。
如果为 CDS 实体定义了 CDS 角色,则每次使用 Open SQL 或使用服务适配描述语言 (SADL) 查询访问对象时都会隐式评估访问条件(除非使用值 #NOT_ALLOWED 禁用访问控制)注解@AccessControl.authorizationCheck)。如果启用访问控制,则只读取满足访问条件的数据。
注:SADL(Service Adaptation Description Language)是一种ABAP技术,基于模型驱动的方式,可以在具有共同开发体验的各种场景下,实现类实体关系的ABAP数据模型的消费。因此,SADL 可以使用查询下推实现对基于 SAP HANA 的移动和桌面应用程序场景的数据的快速读取访问。
4.最终用户文本注解 EndUserText.label
(1)注解
1 | @EndUserText.label:’<String>’ |
(2)描述
CDS 视图的可翻译短文本,用户看到的文本。可以简单理解成对该CDS视图的描述。
(3)可能的值
最多 60 个字符的字符串。引入了ABAP 注释@EndUserText.label来定义 CDS 对象的可翻译语义文本。像这样的注释的值保存在具有语言键且可翻译的特殊表中。源代码中指定的值应由 CDS 源代码原始语言的文本组成,并被翻译成所需的语言。
(4)示例
1 | @AbapCatalog.sqlViewName: 'YSYSTEM_VAR_V' |
在SAP中使用SE11查看YSYSTEM_VAR_V的信息。该界面是系统的英文界面
(5)文本翻译
在这里介绍下如果翻译由@EndUserText.label注解和@EndUserText.quickinfo注解的文本内容。使用事务代码SE63,选择短文本 –> A5用户界面文本 –> DDLS 统一数据存储视图。
在对象名称处填写CDS Entity名称。注意是CDS实体对象名称而不是ABAP中CDS的名称。
之后点击编辑按钮,就会出现和以往翻译程序一样的翻译列表,在其中填写翻译的文本内容。点击保存按钮,最后到传输翻译文本的事务代码:SLXT。按照图中所提示的内容填写传输内容。
5.字段文本注解 EndUserText.quickinfo
(1)注解
1 | @EndUserText.quickinfo:’<String>’ |
(2)描述
只能在字段上使用的文本注解,不限制长度。和上面的最终用户文本注解一样,可以在SE63中进行翻译。
(3)示例
1 | @AbapCatalog.sqlViewName: 'YANNOTATION_1_V' |
七、参考资料
[SQL快速入门-38] SQL CROSS JOIN:交叉连接
SAP CDS View语法进阶(聚集、JOIN、UNION)
SAP CDS View基础语法(创建你的第一个CDS View)