ABAP-CDS View

一、CDS View是什么

CDS View = S/4HANA 时代的 “增强版视图” + 语义模型 + 注解驱动 + 性能下推到 HANA。替代传统 SE11 数据库视图,是 Fiori、OData、RAP、嵌入式分析 的底层数据模型,深度集成了业务语义、访问控制和数据消费能力

核心概念与理解

  • 定义:ABAP CDS View 是定义在 ABAP 服务器上的第一等数据模型对象。它在 ABAP 数据字典中创建,激活时会自动在数据库中生成一个对应的 SQL 视图。

  • 核心理念:Code Pushdown:它将复杂的数据处理逻辑(如连接、聚合、计算)从 ABAP 应用层“下推”到数据库层执行,减少数据传输,充分利用了 SAP HANA 等数据库的性能优势。

使用场景

  • Fiori 应用/ OData 服务生成:通过 @OData.publish: true 注解,可直接将 CDS View 发布为 OData 服务,供 Fiori 应用高效消费。

  • 在 ABAP 程序中消费:可直接在 SELECT 语句的 FROM 子句中使用 CDS View,如同使用数据库表一样。

  • 数据提取与分析:通过 @Analytics.dataExtraction.enabled: true 注解,适合作为数据源提供给 SAP BW/4HANA 或 SAP Analytics Cloud 等分析系统

核心优势(对比 SE11 视图)

  •  注解(@):UI、权限、OData、标签全部写在模型里
  •  关联(Association):JOIN 可复用,支持导航
  •  计算字段 / 聚合 / 参数:比 SE11 强太多
  •  性能极高:逻辑下推 HANA,避免 ABAP 层循环
  •  直接发布 OData:一行注解暴露服务

二、CDS View 三层架构

  1. 基础视图(I_xxx) :只做表关联、字段映射、计算 → 对内
  2. 组合视图(P_xxx):过滤、聚合、业务逻辑 → 对内
  3. 消费视图(C_xxx):注解、UI、权限、OData → 对外给 Fiori/OData

三、CDS DEMO

开发环境:

  • 安装 Eclipse IDE 并配置 ABAP Development Tools (ADT) 插件,安装参考:ADT安装和CDS View入门
  • 确保可访问 ABAP NetWeaver 7.4 以上或 SAP BTP ABAP 环境

1. 基础视图(ZI_DEMO)– 只做表关联、字段映射、计算

@AbapCatalog.sqlViewName: 'ZKJ_CSD_01'            
@AbapCatalog.compiler.compareFilter: true         
@AbapCatalog.preserveKey: true                    
@AccessControl.authorizationCheck: #NOT_REQUIRED   
@EndUserText.label: 'Base View'
@Metadata.ignorePropagatedAnnotations: true
define view ZCDS_DEME_01 as select from sflight inner join scarr on sflight.carrid = scarr.carrid
{
  // 主键
  key sflight.carrid,
  key sflight.connid,

  // 原始字段
  scarr.carrname,
  sflight.seatsmax,
  sflight.seatsocc

}

激活后可以在SAP GUI使用SE16N事务代码查看CDS View,名称为'ZKJ_CSD_01'(取决于注解的自定义的名称)

可以看到通过CDS View进行查询的时候会出来一个有数据的视图,数据来源是通过CDS View封装好的SQL逻辑从SFLIGHT物理表和SCARR物理表取数,CDS View底层本质是封装好的一条 SQL 查询+注解、关联、分层建模、能给前端直接用的高级业务视图

那创建好的ABAP CDS View 是如何被消费的呢?我们以SAP GUI的Report为例:

CDS View:

@AbapCatalog.sqlViewName: 'ZI_DEMO_01'
@AbapCatalog.compiler.compareFilter: true
@AbapCatalog.preserveKey: true
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'test'
@Metadata.ignorePropagatedAnnotations: true
define view ZI_DEMO_VIEW_01 as select from sflight as f
join scarr as c on f.carrid = c.carrid
{
  f.carrid,
  f.connid,
  c.carrname,
  f.seatsmax - f.seatsocc as seats_avail  // CDS 计算字段
}

SAP GUI ABAP代码

SELECT * INTO TABLE @DATA(lt_cds_entity) FROM  zi_demo_view_01.

cl_salv_table=>factory( IMPORTING r_salv_table = DATA(gr_table) CHANGING t_table = lt_cds_entity ).

gr_table->display( ).

运行效果:

2. 带参数视图(ZP_DEMO)– 过滤 + 参数

带参数 CDS 视图 = 留好过滤入口,调用时再给条件,动态查数据。

CDS VIEW:

@AbapCatalog.sqlViewName: 'ZP_DEMO'
@AbapCatalog.compiler.compareFilter: true
@AbapCatalog.preserveKey: true
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'TEST'
@Metadata.ignorePropagatedAnnotations: true
define view ZP_DEMO_VIEW 
with parameters
  P_FROM : abap.dats, // 输入开始日期
  P_TO   : abap.dats  // 输入结束日期
as select from sflight
{
  key carrid,
  key connid,
  key fldate,
      seatsmax,
      seatsocc
}
where fldate between $parameters.P_FROM and $parameters.P_TO

SAP GUI ABAP 代码:

DATA: lt_data TYPE TABLE OF zp_demo.


START-OF-SELECTION.

  " 🔥 正确调用带参数CDS
  SELECT * FROM zp_demo( p_from = '20250510', p_to = '20250513' )
   INTO CORRESPONDING FIELDS OF TABLE @lt_data.

  LOOP AT lt_data INTO DATA(ls).
    WRITE: / ls-carrid, ls-connid, ls-fldate.
  ENDLOOP.

运行结果:

3.消费视图(UI5+ODATA)

通过注解@OData.publish: true发布OData Service 给 Fiori调用

CDS VIEW:

@AbapCatalog.sqlViewName: 'ZI_SO'
@AbapCatalog.compiler.compareFilter: true
@AbapCatalog.preserveKey: true
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Get SO'
@Metadata.ignorePropagatedAnnotations: true
@OData.publish: true
define view ZI_SO_VIEW as select from vbak
{
        key vbeln as Vbeln, 
        erdat as Erdat,
        erzet as Erzet,
        ernam as Ernam,
        vkorg as Vkorg,
        vkgrp as Vkgrp
}

Fiori运行效果:

四、核心语法详解

1. 注解(@)– CDS 灵魂

@EndUserText.label: '自定义标签'     // 字段/视图显示名
@OData.publish: true                 // 发布OData V4
@UI.lineItem: true                   // Fiori列表显示
@AccessControl.authorizationCheck: #REQUIRED // 权限控制
@Consumption.filter.mandatory: true  // 必输过滤条件

 CDS View(常用) 注解功能附表:

注解名称主要作用与应用场景注解示例
@OData.publish将 CDS View 一键发布为 OData v4 服务,供 Fiori 应用直接消费@OData.publish: true
@UI为 Fiori Elements 提供 UI 渲染指令(列表报表、筛选字段、详情页布局)@UI.lineItem: [{position: 10, label: '订单号'}]
@ObjectModel为 OData / RAP 服务定义行为语义(只读、创建启用、关联实体类型)@ObjectModel.readOnly: true
@Semantics标记字段的业务类型(货币、金额、日期、时间、单位等),确保前端/OData正确解析@Semantics.amount.currencyCode: 'Currency'
@AccessControl.authorizationCheck激活权限控制(结合 DCL),SELECT 时自动过滤无权限的行@AccessControl.authorizationCheck: #CHECK
@ClientHandling.type控制多客户端行为(按当前客户端过滤、跨客户端查询、忽略客户端字段)@ClientHandling.type: #CLIENT_DEPENDENT
@AbapCatalog.sqlViewName传统 CDS View 必备:指定底层 SQL 视图名(最多 16 字符)@AbapCatalog.sqlViewName: 'ZSQL_MYVIEW'
@AbapCatalog.compiler.compareFilter性能优化:避免关联中筛选条件被重复评估@AbapCatalog.compiler.compareFilter: true
@EndUserText.label为视图提供面向最终用户的描述文本(推荐所有视图都加)@EndUserText.label: '销售订单分析视图'

注:若使用现代 CDS View EntityDEFINE VIEW ENTITY),则无需 @AbapCatalog.sqlViewName

2. 关联(Association)– 替代 JOIN 并可复用

简单来说,CDS Association 是一种在 Core Data Services (CDS) 中声明并复用两个实体(表或视图)关系的机制。它像一段“关系代码”被嵌入源实体中,为数据的关联查询带来了更强的灵活性、可读性与性能优化潜力,只有你真正用到关联表的字段时,系统才自动关联查询,性能更好、更灵活。

Association的核心是在 SELECT 语句后,使用 ASSOCIATION 关键字定义一段关系,它包含了目标实体、关联名称、关联基数和连接条件。基本语法如下:

ASSOCIATION [min..max] TO target_cds_view AS _assoc_name ON $projection.source_field = _assoc_name.target_field

各部分解释如下:

组成部分含义说明
ASSOCIATION [min..max]关联基数用于定义两个实体间关系的类型,代码中的“智能指针”。
TO target_cds_view目标实体声明此Association要连接到的目标CDS视图或数据库表。
AS _assoc_name关联名称给这个Association起一个别名,以便在后续查询中引用。
ON condition连接条件定义源实体和目标实体如何连接的字段匹配规则,类似于SQL中的ON条件。

补充说明关联基数 [min..max] 并不是一个严格的数据库约束,它更像一种“语义提示”或“元数据”。例如:

  • [1..1]: “一个订单必须有且只有一个客户”。

  • [0..*]: “一个客户可以有零个、一个或多个订单”。该基数并不控制最终SQL生成的连接类型是 INNER 还是 OUTER,在设计数据模型时主要用于表达业务关

Association 和 JOIN的区别

  • JOIN:不管用不用,都强行关联,性能差
  • Association:用到才关联,不用不关联,性能高

创建 EKPO + MAKT 的视图:

define view ZEKPO_WITH_MAKT
  as select from ekpo

  association [0..1] to makt as _makt
    on ekpo.matnr = _makt.matnr
    and _makt.spras = $session.system_language

{
  key ekpo.ebeln  as Ebeln,
  key ekpo.ebelp  as Ebelp,
      ekpo.matnr  as Matnr,
      ekpo.menge  as Menge,
      ekpo.meins  as Meins,
      _makt.maktx as Maktx
}

数据预览:

创建 EKKO + 上方CDS VIEW的视图:

@AbapCatalog.sqlViewName: 'ZEKKO_EKPO_TEST'
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: '采购订单抬头 + 行项目(含物料描述)'
define view ZEKKO_WITH_ITEMS
  as select from ekko

  association [0..*] to ZEKPO_WITH_MAKT as _items
    on ekko.ebeln = _items.Ebeln

{
  key ekko.ebeln as Ebeln,
      ekko.bsart as Bsart,
      ekko.bukrs as Bukrs,
      ekko.lifnr as Lifnr,
      _items.Ebelp as ItemNo,
      _items.Matnr as Material,
      _items.Menge as Quantity,
      _items.Maktx as MaterialDesc
}

数据预览:

3. 计算字段 & 函数

示例1:算术运算(计算剩余座位)

@AbapCatalog.sqlViewName: 'ZFLTSEAT'
@AccessControl.authorizationCheck: #NOT_REQUIRED
@AbapCatalog.preserveKey: true 
@EndUserText.label: '航班座位占用情况'
define view ZFLIGHT_SEATS
  as select from sflight
{
  key carrid   as Airline,
  key fldate   as FlightDate,
      seatsmax as TotalSeats,
      seatsocc as OccupiedSeats,
      seatsmax - seatsocc as AvailableSeats   // 算术运算
}

示例2:类型转换(货币字段规范化)

@AbapCatalog.sqlViewName: 'ZFLTPRICE'
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: '航班价格(格式化)'
define view ZFLIGHT_PRICE
  as select from sflight
{
  key carrid,
  key connid,
  key fldate,
      // 将价格字段转换为 15 位总长、2 位小数的货币类型
      cast( price as abap.curr(15,2) ) as FormattedPrice
}

示例3:字符串处理(拼接、截取)

@AbapCatalog.sqlViewName: 'ZFLTSTR'
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: '航班字符串处理'
define view ZFLIGHT_STRING
  as select from spfli
  inner join scarr on spfli.carrid = scarr.carrid
{
  key spfli.carrid,
  key spfli.connid,
      // 拼接:航空公司代码 + 航班号
      concat( spfli.carrid, spfli.connid ) as FlightId,
      // 截取:只取航空公司名称的前 10 个字符
      substring( scarr.carrname, 1, 10 )    as AirlineShort
}

示例4:字符串处理(拼接、截取)

@AbapCatalog.sqlViewName: 'ZFLTAGG'
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: '航班聚合统计'
define view ZFLIGHT_AGGREGATE
  as select from sflight
{
  key carrid,
  key connid,
      sum( price )   as TotalRevenue,      // 总和
      count( * )     as FlightCount,       // 所有行计数(包含 NULL)
      count( fldate ) as FlightDateCount,  // 仅非空计数
      avg( price )   as AvgPrice           // 平均价格(可选)
}
group by carrid, connid

关键说明:

操作类别关键函数/语法说明
算术+ - * /字段间直接计算,如 seatsmax - seatsocc
类型转换cast( ... as abap.curr(p,s) )也可转换为 abap.dec(p,s)abap.int4 等
字符串concat( a, b )拼接,等价于 a || b(HANA 风格)
字符串substring( str, start, length )截取子串,start 从 1 开始
聚合sum(), count(), avg(), min(), max()必须配合 group by 使用非聚合的 key 字段

总结

       CDS View 是 SAP 现代化的数据建模利器,它用关联导航取代笨重的 JOIN,把计算逻辑和数据关系推给数据库,从而让 ABAP 开发更简洁、更高效。 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值