在 CDS 视图中实施 SQL 表达式
学习目标
激励在 CDS 视图中使用代码下推。
在 CDS 视图中使用 SQL 表达式。
ABAP SQL 和 ABAP CDS 中的代码下推

在本学习之旅的上一部分,您了解到,使用 SAP HANA 的巨大数据分析功能时,建议您尽可能在数据库中执行计算。您还了解到 ABAP SQL 为此提供了大量表达式和内置函数。
其中大多数表达式和内置函数在 CDS 视图定义中也可用。这允许您将复杂的计算移动到 CDS 视图定义,然后从 CDS 视图中检索数据。
让我们看一个示例。在此 ABAP 代码中,ABAP SQL 语句使用算术表达式通过从座位总数中减去已占用座位数来计算航班的可用座位数。

在下一示例中,算术表达式将移动到 CDS 视图定义中。计算结果作为视图元素 seats_free 对视图的使用者可见。与任何其他视图元素一样,ABAP 代码读取视图元素 seats_free。
注意
对于 CDS 视图的使用者,如果视图元素只是数据库表字段的投影或复杂计算的结果,则没有区别。

将 SQL 逻辑从 ABAP SQL 移动到 CDS 视图具有以下几个优势:
封装
由于 SQL 逻辑隐藏在 CDS 视图定义中,因此 ABAP SQL 语句更易于读取。
重用
通过从同一 CDS 视图中读取,您可以在其他应用程序中轻松重用 SQL 逻辑。特别是,可以在使用 CDS 视图的框架中使用 SQL 逻辑,例如,嵌入式分析、SAP BW 的基于 CDS 的数据提取器、ABAP RESTful 应用程序编程等。
语义
您可以通过为元素指定有意义的名称并使用元素注释对其进行注释,向计算结果添加语义。
权限规则
您可以通过为 CDS 视图创建 CDS 访问控制来限制对已计算数据的访问。
ABAP CDS 中的文字

比较 ABAP SQL 中的文字和 ABAP CDS 中的文字时,您会注意到 ABAP CDS 提供的类型种类更大。
字符文字
虽然 ABAP SQL 仅知道预定义类型 C 的字符文字(对应于字典类型 CHAR),但 ABAP CDS 在字符文字仅包含数字时使用预定义的字典类型 NUMC。
数字文字
ABAP SQL 只知道正整数和负整数文字,并对所有整数文字使用预定义的 ABAP 类型 I(字典类型 INT4)。
另一方面,ABAP CDS 也使用字典类型 INT4、INT2 和 INT1,选择可保存文字值的最短类型。例如,文字值 255 仍为 INT1 类型,而 256 对于一个字节来说过大,需要类型 INT2。
ABAP CDS 还知道非整数文字。它们包含小数点并具有预定义的字典类型 FLTP。
注意
ABAP SQL 不支持非整数文字 - 主要是因为句点 (.) 保留为语句分隔符。
类型转换

与 ABAP SQL 一样,您可以使用 CAST 表达式实施技术类型转换。
cast 表达式的操作数不能只是文字,如本例所示。可以使用所有种类的其它表达式,例如,数据源的字段、算术表达式、CASE 区分、SQL 函数等。
可将目标类型指定为预定义的字典类型。这与 ABAP SQL 中 CAST 的使用相同。但请注意,在 CDS 中需要前缀 abap.。
源类型和目标类型的组合存在限制。某些组合根本不受支持。其他方法仅在有限制的情况下有效。例如,当前无法使用 FLTP 类型的操作数作为 CAST 表达式的源。可在 ABAP 语言文档中找到详细的矩阵。

它是 ABAP CDS 中 CAST 的特性,您也可以使用字典数据元素作为目标类型。这种转换不仅转换技术类型。它还从数据元素中获取语义信息,如字段标签。
如果操作数和目标数据元素的技术类型相同,则以数据元素作为目标类型的转换甚至非常有用。在这种情况下,仅修改操作数的语义信息。如果转换不更改技术类型,语法检查将发出警告。可以使用 cast 表达式中的附加项 PRESERVING TYPE 禁止此警告。
ABAP CDS 中的 CASE 区别

ABAP CDS 提供与 ABAP SQL 完全相同的 CASE 区分。简单的大小写和复杂的大小写区分遵循相同的语法规则,并且具有相同的功能。

这可以通过示例来说明。左侧的简单 case 表达式来自 ABAP SQL SELECT 语句。右侧的简单 case 表达式是 CDS 视图实体定义的一部分。除了两个编辑器中的不同格式和颜色外,没有区别。
ABAP CDS 中的算术表达式

与 ABAP SQL 一样,算术表达式可用于 CDS 视图定义的元素列表。这两种情况下都适用相同的规则和限制。与 ABAP SQL 中的情况一样,最重要的限制是仅允许在浮点表达式中使用除法运算符 (/)。
提示
通过使用 CAST() 将类型转换为 FLTP,可以在浮点表达式中使用任何数值操作数。

比较 ABAP SQL 和 ABAP CDS 中的这些示例。同样,差异主要是格式化。存在两个差异,它们与算术表达式实际上并不相关,而是与文字和铸造表达式的使用有关:
ABAP CDS 中的 cast 表达式需要预定义字典类型前的前缀 " abap. "。
可以在 ABAP CDS 中使用浮点文字。可以直接在浮点表达式中使用文字 100.0 。无需使用整数文字 100 并将其转换为预定义类型 FLTP。
在 CDS 视图中使用表达式
您想要使用 SQL 逻辑扩展 CDS 视图实体。在第一步中,将员工标记为部门负责人和助理,并计算月薪。
模板:
/LRN/C_EMPLOYEE_QRY(数据定义)
解决方案:
/LRN/C_EMPLOYEE_EXP(数据定义)
前提条件
在本练习中,您需要使用在上一练习中创建的 CDS 视图实体(建议名称为 Z##_C_EmployeeQuery,其中 ## 是您的组编号)。如果尚未完成该练习,请创建数据定义 /LRN/C_EMPLOYEE_QRY 的副本。
任务 1: 使用 CASE 区分
在用于评估员工数据的 CDS 视图实体(建议名称为 Z##_C_EmployeeQuery,其中 ## 是您的组编号)中,定义新的视图元素(建议元素名称:EmployeeRole)。如果员工是部门主管,则将元素返回值 'H',如果员工是部门助理,则将值设为 ' A',为所有其他员工设置值 ' '。
步骤
在视图实体的元素列表中,在公开关联之前添加案例区分,将
EmployeeID的值与关联_Department的目标中元素HeadID的值进行比较。如果值相同,则返回值'H'。如下调整代码:
define view entity Z##_C_EmployeeQuery
as select from Z##_R_Employee
{
key EmployeeId,
FirstName,
LastName,
DepartmentId,
_Department.Description as DepartmentDescription,
_Department._Assistant.LastName as AssistantName,
case EmployeeId
when _Department.HeadId then 'H'
添加第二个分支,将
EmployeeID的值与关联_Department的目标中元素AssistantID的值进行比较。如果值相同,则返回值'A'。如下调整代码:
case EmployeeId
when _Department.HeadId then 'H'
when _Department.AssistantId then 'A'
添加 else 分支以返回值
' '。如下调整代码:
case EmployeeId
when _Department.HeadId then 'H'
when _Department.AssistantId then 'A'
else ' '
关闭 CASE 表达式并指定元素名称(建议的元素名称:
EmployeeRole)。如下调整代码:
case EmployeeId
when _Department.HeadId then 'H'
when _Department.AssistantId then 'A'
else ' '
end as EmployeeRole,
添加所需注释以定义计算字段的标签(建议值:
员工角色)。如下调整代码:
@EndUserText.label: 'Employee Role'
case EmployeeId
when _Department.HeadId then 'H'
when _Department.AssistantId then 'A'
else ' '
end as EmployeeRole,
任务 2: 使用算术表达式
根据员工的年薪,计算月薪(建议要素名称:MonthlySalary)。
步骤
使用带有 / 运算符的算术表达式将
AnnualSalary的内容除以12。如下调整代码:
@EndUserText.label: 'Employee Role'
case EmployeeId
when _Department.HeadId then 'H'
when _Department.AssistantId then 'A'
else ' '
end as EmployeeRole,
cast( AnnualSalary as abap.fltp ) / 12.0 as MonthlySalary,
添加所需注释以定义计算字段的标签(建议值:
月薪)。如下调整代码:
@EndUserText.label: 'Employee Role'
case EmployeeId
when _Department.HeadId then 'H'
when _Department.AssistantId then 'A'
else ' '
end as EmployeeRole,
@EndUserText.label: 'Monthly Salary'
cast( AnnualSalary as abap.fltp ) / 12.0 as MonthlySalary,
将
CurrencyCode元素添加到元素列表,并使用 @Semantics.amount.currencyCode 注释将其链接到MonthlySalary元素。如下调整代码:
@EndUserText.label: 'Monthly Salary'
@Semantics.amount.currencyCode: 'CurrencyCode'
cast( AnnualSalary as abap.fltp ) / 12.0 as MonthlySalary,
CurrencyCode,
激活 CDS 数据定义。
按
Ctrl + F3激活开发对象。打开数据预览并分析输出。
按
F8打开数据预览。