4. CDS视图核心语法与数据源

CDS(Core Data Services)视图的建模能力,本质上由三部分构成:数据源决定“从哪里取数”,SELECT语句结构决定“取哪些列、如何过滤与聚合”,注解决定“这个视图在ABAP运行时和SAP Fiori中如何被识别与消费”。本节围绕这三点展开,重点讲清关联(Association)、联合(Union)、参数(Parameter)与输入参数(Input Parameter)的语法差异和适用场景。

一、数据源与SELECT列表

CDS视图的 define view 后面紧跟视图名,as select from 指定主数据源。数据源可以是数据库表、其他CDS视图,也可以是带参数的CDS视图。SELECT列表中的字段必须显式命名,若字段来自表达式或函数,必须用 as 指定别名,否则激活时会报“缺少列名”错误。

@AbapCatalog.sqlViewName: 'ZCDS_SALES_01'
@AccessControl.authorizationCheck: #NOT_REQUIRED
define view ZCDS_SalesOrder
  as select from vbak as so
{
  key so.vbeln   as SalesOrder,
      so.erdat   as CreatedDate,
      so.netwr   as NetValue,
      so.waerk   as Currency
}
where so.vbtyp = 'C'

这里 @AbapCatalog.sqlViewName 是必须注解,它决定底层生成的数据库视图名;@AccessControl.authorizationCheck 控制权限检查行为。SELECT列表中的 key 用于标识视图主键,多个key字段共同构成复合主键。

二、关联(Association)

关联不是JOIN,它描述的是“实体之间的语义关系”,只有在路径被实际访问时才生成JOIN。语法为 association [0..1] to Target as _Alias on 条件。基数 [0..1]、[1..1]、[0..*] 表达目标端匹配数量,直接影响运行时是否允许空值。

define view ZCDS_SalesWithCustomer
  as select from vbak as so
  association [0..1] to kna1 as _Customer
    on $projection.Customer = _Customer.kunnr
{
  key so.vbeln   as SalesOrder,
      so.kunnr   as Customer,
      _Customer.name1 as CustomerName
}

关联的优势在于:同一视图可被多个上层视图复用,且路径 _Customer.name1 只在被选中时才展开为LEFT OUTER JOIN。若需强制内连接,可在路径后加 inner join 关键字。关联还支持在 where 中通过 _Customer.land1 = 'CN' 过滤,但要注意这会隐式改变连接语义。

三、联合(Union)

当需要把结构相同、来源不同的结果集合并时使用 union。CDS中union要求各分支列数、类型、顺序一致,且只能有一个 key 定义在第一个分支上。默认 union 去重,union all 保留重复行。

define view ZCDS_AllDocs
  as select from vbak as a
{
  key a.vbeln as DocNo,
      a.erdat as DocDate,
      'SO'    as DocType
}
union all
select from likp as b
{
  key b.vbeln as DocNo,
      b.erdat as DocDate,
      'DL'    as DocType
}

实际建模中,union常用于合并销售订单与交货单、合并不同公司代码的同类数据。注意union分支中不能直接使用参数,若需参数化,应把参数放在外层视图或使用 where 在分支内引用参数。

四、参数与输入参数

CDS参数分为两类:输入参数(Input Parameter)和普通参数(Parameter)。输入参数用 with parameters 声明,在视图体内通过 :参数名 引用,常用于 where 过滤;普通参数用 with parameters 声明但不带冒号引用,通常用于传递常量或作为计算因子。

define view ZCDS_SalesByDate
  with parameters
    p_date_from : dats,
    p_date_to   : dats
  as select from vbak as so
{
  key so.vbeln as SalesOrder,
      so.erdat as CreatedDate,
      so.netwr as NetValue
}
where so.erdat between :p_date_from and :p_date_to

调用时通过 ZCDS_SalesByDate(p_date_from = '20240101', p_date_to = '20241231') 传入。输入参数在ABAP CDS中会生成对应的方法参数,在Fiori应用中可绑定为筛选条件。若参数用于 case when 或计算表达式,需注意类型转换,例如 cast(:p_rate as abap.dec(5,2))。

五、基本注解

注解以 @ 开头,写在视图或字段上方。常用注解包括:@AbapCatalog.sqlViewName(必填)、@AccessControl.authorizationCheck(权限检查)、@EndUserText.label(描述文本)、@Semantics.amount.currencyCode(金额与币种关联)、@Semantics.quantity.unitOfMeasure(数量与单位关联)、@UI.lineItem 与 @UI.identification(Fiori列表与详情页字段)。

其中 @Semantics 系列注解直接影响Fiori应用的金额、数量显示格式,若缺失会导致前端无法正确格式化。例如金额字段必须同时标注 @Semantics.amount.currencyCode: 'Currency',并确保Currency字段存在于同一视图中。

CDS视图核心语法结构关系图 数据源 数据库表 / CDS视图 vbak、kna1、likp SELECT 语句核心 select from 数据源 as 别名 { key 字段 as 别名, ... } where 过滤条件 注解 @AbapCatalog @Semantics / @UI 关联 Association association [0..1] to 目标 on 连接条件 按需展开为 LEFT OUTER JOIN 联合 Union union / union all 列数、类型、顺序一致 key 定义在第一个分支 参数 Parameter with parameters 输入参数 :p_date_from 调用时传值,可绑定筛选 语法组合示例:带参数、关联与注解的CDS视图 @AbapCatalog.sqlViewName: 'ZCDS_SO_PARAM' @AccessControl.authorizationCheck: #NOT_REQUIRED define view ZCDS_SO_Param with parameters p_from : dats, p_to : dats as select from vbak as so association [0..1] to kna1 as _C on so.kunnr = _C.kunnr 注解控制行为 关联按需JOIN 参数运行时传入

六、语法选择与常见陷阱

关联与JOIN的选择:若目标实体是主数据(如客户、物料),且上层视图可能只取部分字段,优先用关联;若需要聚合后再连接,或连接条件复杂且必须立即生效,用JOIN更直接。union与关联不可混用在同一层级,union分支内不能直接引用外层参数。

参数与输入参数的区别:输入参数在ABAP端生成方法参数,可被Fiori筛选器绑定;普通参数通常用于传递常量,不参与运行时筛选。若在 where 中使用 :p_date,必须确保参数类型与字段类型一致,否则激活时报类型不匹配。

常见激活错误:① 缺少 @AbapCatalog.sqlViewName;② SELECT列表表达式未指定别名;③ union分支列数或类型不一致;④ 关联的 on 条件中引用了未在SELECT列表中出现的字段;⑤ 金额字段缺少 @Semantics.amount.currencyCode 导致Fiori显示异常。

掌握以上语法后,CDS视图的建模能力就从“单表取数”扩展到“多实体语义关联、多源合并、参数化查询与前端语义标注”。实际项目中,建议先确定数据源与主键,再决定用关联还是JOIN,最后补充注解与参数,这样激活成功率和可维护性都更高。