ABAP CDS 和数据建模
前提:安装运行环境
Ps:如果你是在 Eclipse IDE 中创建 ABAP Project 直连已有的 SAP 系统,可以直接跳过第2步和第3步。当然,你也可以自己创建一个 BTP 试用账号学习 ABAP Cloud 开发。
1、安装 Eclipse IDE
Download the Eclipse IDE and add the ABAP Development Tools (ADT) Plugin
2、申请 BTP 试用账号
Get an Account on SAP BTP Trial
3、在 SAP BTP 上配置 ABAP 环境
1、登录 SAP BTP Trial ,点击 trial 进入子账号的界面。

2、选择 Services → Service Marketplace,创建 ABAP environment 的实例。

3、填写实例的名称(名称可以任意取)。

4、填写你的邮箱地址,用于登录验证。

5、点击创建完成。

6、在 Service → Instances and Subscriptions 可以看到创建的实例。

7、点击最右边的按钮创建 Service Key。

8、输入 Service Key的名称,然后点击创建。

9、查看 Service Key,然后将 Service Key 拷贝下来,之后创建 ABAP Cloud Project 会用到。

10、打开 Eclipse IDE,创建 ABAP Cloud Project。

11、点击 Extract。

12、将复制下来的 Service Key 粘贴到弹框里。之后在弹框下边的 Service Instance URL 中会生成一个地址,将该地址复制下来,然后关闭弹框。

13、将地址粘贴到如下的输入栏中,点击 next。

14、在浏览器中打开登录页面,输入你的邮箱账号(在第4步中填写)和密码进行验证。

15、最后,输入项目名称,点击 finish 就可以使用了。

第一节:数据建模基础
1.1、ABAP 字典的基本功能
ABAP 字典可用于定义数据库对象。ABAP 字典中的数据库表定义是数据库中表的表示。它与数据库的细节是独立的。例如,它使用的是自身的内置类型,而不是特定于数据库的类型。
该定义包含了表的字段列表和其它表属性。当 ABAP 代码使用 ABAP SQL 语句访问数据库表时,ABAP 语法检查会分析 ABAP 字典中的表定义。除此之外,它还会检查表和表字段是否存在等。
在运行时,数据库接口将 ABAP SQL 语句转换为数据库特定的 SQL 语法,并将其发送到数据库。在这个过程中,数据库接口还会查询 ABAP 字典中的表定义。

ABAP 字典的第二个作用是为 ABAP 代码提供数据类型。在 ABAP 字典中定义的数据类型在整个系统中都是可见的。这与使用 ABAP 关键字 TYPES 定义的数据类型不同。字典类型可以是标量类型(数据元素)、结构类型(结构)和表类型。数据库表的定义具有双重角色:首先,它们定义了一个数据库对象,但除此之外,它们也可以作为 ABAP 代码中的数据类型。

在传统的 ABAP UI 技术中,ABAP 字典承担了第三个任务。字典对象,主要是结构类型和数据库表定义,加入了语义信息,如外键关系和搜索帮助绑定。当 UI 元素引用字典对象时,这些附加信息用于提供终端用户文本、值帮助、输入检查等功能。ABAP 字典的这个任务与现代 UI 技术并不相关,即 ABAP RESTful 应用程序编程模型。ABAP RESTful 应用程序编程模型使用 CDS 实体中的元数据为用户界面提供服务。

1.2、ABAP CDS(Core Data Services)的基本功能:
长期以来,我们使用定义数据库表相同的方式在 ABAP 字典中定义视图。这些字典视图在 SQL 逻辑方面非常有限,仅支持内连接、字段选择(投影)和简单的过滤条件。但是,字典视图的定义在基于云的 ABAP 环境中是不支持的。SAP 引入 ABAP 核心数据服务(Core Data Services, CDS)的原因之一是需要在数据库上执行逻辑。
CDS View 主要有两种:
- CDS DDIC-based views (obsolete): 这种过时的 CDS 视图使用生成的字典视图作为数据库对象的技术表示。基于 DDIC 的 CDS 视图是通过
define view语句定义的。 - CDS View Entities: 新一代的 CDS 视图是通过
define view entity语句定义的。CDS 视图实体直接定义数据库对象,而不需要先生成字典对象。

ABAP CDS 不仅支持数据库对象的技术定义,还允许你用语义信息丰富这些技术定义。注解是用语义信息丰富技术视图定义的代码元素。注解以 @ 符号开头。只有少数注解会被 ABAP 系统评估,其余的注解则会被简单地传递给 CDS 实体的使用者,即那些使用 CDS 实体读取数据的框架。使用者自行决定评估哪些注解以及忽略哪些注解。ABAP CDS 实体最重要的使用者是现代 UI 技术,如 SAP Fiori 和 SAP S/4HANA 嵌入式分析。
ABAP RESTful 应用程序编程模型的核心是业务对象。业务对象的结构通过一个或多个 CDS view Entity 建模。CDS Behavior 定义用于添加事务逻辑。事务逻辑在 ABAP Behavior 池中实现,这是 ABAP 源代码库中的一个 ABAP 类。业务对象通常被业务服务使用,例如 OData 服务。但您也可以通过使用实体操作语言(EML)在 ABAP 代码中访问它们。
ABAP CDS 对象包含了如下四类:
CDS 数据定义
- CDS projection views 基于一个 CDS 视图,并投影其元素的子集。
- CDS Abstract Entities 仅描述类型属性,且不会实例化数据库对象。
- CDS Table Functions 在数据库函数中实现,并返回一个表格结果集。
- CDS Custom Entities 通过手动实现,例如在 ABAP 代码中实现。
- CDS Hierarchies 从 SQL 数据源定义 SQL 层次结构。
CDS 访问控制
- CDS access controls 包含 CDS 角色的定义。当访问分配了 CDS 角色的 CDS SQL 实体时,默认情况下会评估额外的访问条件。
CDS 元数据扩展
- CDS Metadata Extension 用于存储 CDS 注释,这些注释是为了某个 CDS 实体,而存放在其数据定义之外。
CDS 行为定义
- CDS Behavior Definitions 定义了业务对象的事务行为。
第二节 - 创建数据库表
2.1、表定义创建
数据库表的定义主要分为三个部分:
- 语义表属性:以 @ 符号开头的代码行称为注解,它们定义了语义表属性。
- 表定义语句:
define table语句后面接着数据库表的名称。在创建开发对象时指定这个名称。在源代码中更改它会导致语法错误。 - 字段列表:表名后的一对括号包含了表的字段列表。每个字段定义以分号(
;)结束,由字段名称和字段类型组成,二者之间用冒号(:)分隔。数据库表定义的模板建议第一个表字段命名为client,类型为abap.clnt。保留此字段可以确保表保持“客户端相关”(即依赖于客户端)。

补充:在定义字段列表时,字段类型可以使用数据元素也可以使用 ABAP 字典中的预定义类型。常用的预定义类型主要可以分为如下四种:

每个数据库表都需要一个主键。主键是表行的唯一标识,它由一组称为键字段的表字段组成。主索引是为表的主键创建的。这个索引在为键字段指定值时,为表行提供了优化的键访问。在数据库表定义中,可以通过在表字段名称前添加 key 来标记一个字段为键字段。至少必须有一个表字段被标记为键字段,每个表最多可以有16个键字段。表的键字段必须位于表的开头,这意味着两个键字段之间不允许有非键字段。

对于键字段,为其添加 not null 仍为语法的强制要求,虽然它的功能已被系统默认行为覆盖。最初,not null 用于强制数据库表字段使用类型特定的初始值(而非空值),尤其是对主键字段是强制要求,确保关键列数据有效。如今,not null 仍是主键字段的强制要求,但实际作用已经弱化。ABAP 字典工具默认强制几乎所有字段使用初始值,无论是否添加 not null 。
数据库中的null值在 ABAP 中会被替换为对应数据类型的初始值(如空字符串、0 等),避免与有效数据混淆。若为无初始值的字段类型添加not null会触发语法错误。比如:基于 STRG 类型的数据元素 /dmo/email_address。

在数据库表中定义基于预定义类型 curr 的金额字段,需要引用一个基于预定义类型cuky的货币代码字段。引用通过在金额字段之前添加注解@Semantics.amount.currencyCode来定义。注解的参数包含表名和货币代码字段名,两者之间用点号.分隔。同样地,定义基于预定义类型 quan 的数量字段需要引用一个基于预定义类型 unit 的单位字段。数量字段对应的注解是 @Semantics.quantity.unitOfMeasure。示例如下:
@EndUserText.label : 'Short Description'
@AbapCatalog.enhancement.category : #NOT_EXTENSIBLE
@AbapCatalog.tableCategory : #TRANSPARENT
@AbapCatalog.deliveryClass : #A
@AbapCatalog.dataMaintenance : #RESTRICTED
define table zlearn_employee {
key client : abap.clnt not null;
...
@Semantics.amount.currencyCode : 'zlearn_employee.currency_code'
amount : abap.curr(13,2);
currency_code : abap.cuky;
@Semantics.quantity.unitOfMeasure : 'zlearn_employee.unit'
quantity : abap.quan(13,3);
unit : abap.unit(3);
}
通过注解和技术表设置可以在定义数据库表时,为其提供更丰富的信息:
-
注解:它是从 @ 开头的代码行。注解是表定义本身的一部分,并定义了技术和语义属性。
在上面的数据库表定义中,注解@EndUserText.label定义了表的简短描述。注解@AbapCatalog.enhancement.category定义了表的类型,默认情况下为透明表。注解@AbapCatalog.deliveryClass用于控制表数据在安装、升级等过程中的传输,默认情况下设置为#A,表示该表是主数据或者业务数据的应用表。如果要定义自定义表、系统表或本地数据表,则需要使用其他值(比如:#C,表示该表是由客户维护的自定义表)。注解@AbapCatalog.dataMaintenance定义是否可以使用某些工具(例如ADT中的数据预览工具)显示或维护数据库表的内容。@AbapCatalog.enhancement.category用于控制表的可扩展性。 -
技术表设置:技术表设置构成了一个独立的开发对象,可以与表分开激活和传输。它们定义了物理数据库表的属性,并且影通过ABAP SQL的访问。
技术表设置是通过基于表单的编辑器来维护的,可以在 ADT 中选择数据库表,然后选择 Open Others → Technical Settings 来打开技术表对话框,它包括了三个部分:

-
通用设置:它的主要目的是影响表在数据库中的创建方式。是否将特定设置传递到数据库,取决于数据库系统。例如,数据类在使用SAP HANA作为数据库系统时不再起作用。然而,提供一个值始终是强制性的。它存在如下的设置选项:
-
Data Class: 它仅对 Oracle 数据库有效。对于所有其他数据库,特别是SAP HANA,它会被忽略。它虽然是强制性的,但仅作为文档记录的方式。
- APPL0 (master data) - 适用于很少更改的数据。
- APPL1 (transactional data) - 适用于经常更改的数据。
- APPL2 (organizational data) - 适用于在配置系统时自定义,然后很少更改的数据。
-
Size Category:它影响数据库中为表保留的初始内存区域的大小。可以指定0到9之间的值,并且这些值会分配到预期行数的区间。分配给每个大小类别的区间限制取决于数据库表的结构。如果超出了预留的初始空间,会根据选择的大小类别隐式地添加新的内存区域。
-
Storage Type:它仅在当前数据库是SAP HANA数据库时有效。
-
Column Store 列存储 - 适用于如下的场景:
- 适用于 DDIC 数据库表包含了大量的行数据,因为列存储提供了更好的压缩。
- 适用于 DDIC 数据库表中包含了仅列存储支持的 SAP HANA 数据类型的表字段。
- 适用于 DDIC 数据库表是为在 SAP HANA 中分析的应用数据设计的。
-
Row Store 行存储 - 适用于对数据库表进行频繁单行访问的场景。
-
-
Load Unit 加载单元仅在当前数据库是SAP HANA数据库时有效。表的加载单元指定了表的数据如何加载到SAP HANA数据库的主内存中。SAP HANA数据库提供以下设置:
- Column Loadable 整个表被视为内存中的表。表数据在系统启动时以列式格式加载到SAP HANA数据库的主内存中。
- Page Loadablee 通过使用SAP HANA数据库的一项叫做原生存储扩展(Native Storage Extension,NSE)的功能,表数据以页面而非列的形式存储在磁盘上。这些页面仅在请求时加载到SAP HANA主内存中的特殊缓冲区。缓冲区中未使用的数据可以被换出。(它适用于访问较少的大型表)
-
-
缓冲:通过缓冲设置,可以定义是否允许将字典数据库表缓存在应用服务器实例的表缓冲区中。使用ABAP SQL访问具有活动缓冲的表时,表缓冲区会被隐式使用。
-
数据更改:日志记录功能用于跟踪通过ABAP SQL对表的更改,适用于重要但很少更改的表。由于所有表的更改都记录在同一日志表中,可能会导致锁定问题,因此建议将日志记录操作留给应用逻辑处理。
-
第三节 - 定义基础 CDS View
3.1、
3.1、
总结 - 学习案例
一、定义数据库表
1.1、域定义
| Name | Description | Data Type | Length | Decimal |
|---|---|---|---|---|
| zd_lrn_amount | Amount | Curr | 13 | 2 |
| zd_lrn_employee_id | Employee Number | Numc | 6 | |
| zd_lrn_department_id | Department ID | Char | 10 |
1.2、数据类型定义
| Field | Type Name | Short | Medium | Long/Heading |
|---|---|---|---|---|
| ze_lrn_annual_salary | zd_lrn_amount | Salary | Annual salary | Annual salary |
| ze_lrn_employee_id | zd_lrn_employee_id | Employee | Employee No. | Employee Number |
| ze_lrn_birth_date | /dmo/date | Born | Born on | Date of Birth |
| ze_lrn_entry_date | /dmo/date | Entry Date | Company entry date | Works for the company since |
| ze_lrn_department_id | zd_lrn_department_id | Dep. | Department date | Department ID |
1.3、结构定义
@EndUserText.label : 'Admin'
@AbapCatalog.enhancement.category : #NOT_EXTENSIBLE
define structure zlrn_s_admin {
created_by : abp_creation_user;
created_at : abp_creation_tstmpl;
local_last_changed_by : abp_locinst_lastchange_user;
local_last_changed_at : abp_locinst_lastchange_tstmpl;
last_changed_at : abp_lastchange_tstmpl;
}
1.4、数据库表定义
@EndUserText.label : 'Employee'
@AbapCatalog.enhancement.category : #NOT_EXTENSIBLE
@AbapCatalog.tableCategory : #TRANSPARENT
@AbapCatalog.deliveryClass : #A
@AbapCatalog.dataMaintenance : #RESTRICTED
define table zlrn_employee {
key client : abap.clnt not null;
key employee_id : ze_lrn_employee_id not null;
first_name : /dmo/first_name;
last_name : /dmo/last_name;
birth_date : ze_lrn_birth_date;
entry_date : ze_lrn_entry_date;
department_id : ze_lrn_department_id;
@Semantics.amount.currencyCode : 'zlrn_employee.currency_code'
annual_salary : ze_lrn_annual_salary;
currency_code : waers;
include zlrn_s_admin;
}
@AbapCatalog.viewEnhancementCategory: [#NONE]
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Employee (Entity)'
@Metadata.ignorePropagatedAnnotations: true
@ObjectModel.usageType:{
serviceQuality: #X,
sizeCategory: #S,
dataClass: #MIXED
}
define view entity zlrn_r_employee as select from zlrn_employee
{
key employee_id as EmployeeId,
first_name as FirstName,
last_name as LastName,
birth_date as BirthDate,
entry_date as EntryDate,
department_id as DepartmentId,
@Semantics.amount.currencyCode: 'CurrencyCode'
annual_salary as AnnualSalary,
currency_code as CurrencyCode,
created_by as CreatedBy,
created_at as CreatedAt,
local_last_changed_by as LocalLastChangedBy,
local_last_changed_at as LocalLastChangedAt,
last_changed_at as LastChangedAt
}
778

被折叠的 条评论
为什么被折叠?



