第21课:CDS View(进阶)—— 聚合、参数与访问控制¶
45分钟 | 阶段:现代开发篇 | 建议边读边做
前置依赖¶
问题引入¶
明细视图有了,管理层要的是"每家航空公司多少航班、平均票价多少"的统计口径——这类口径会被十几个报表/接口反复使用,必须固化成资产。本课给课程库添加参数化统计视图 zac_flight_stats,并揭开上节课留的悬念:#CHECK 等待的 DCL 访问控制是什么、为什么说它是 CDS 的安全门。
时间安排¶
| 时段 | 内容 | 时长 |
|---|---|---|
| 场景引入 | 从明细到统计口径的需求升级 | 3 分钟 |
| Demo 跟做 | 参数化统计视图 + 带参消费 | 10 分钟 |
| 代码拆解 | 聚合/参数/Session 变量/DCL | 25 分钟 |
| 知识总结 | CDS 能力地图 | 4 分钟 |
| 课后思考 | 练习 | 3 分钟 |
本课目标¶
完成本课你将能够:
- 写带
WITH PARAMETERS的聚合 CDS 并按参数消费; - 使用标量函数、
CASE、$session变量增强视图表达; - 说清 DCL 的作用与
#CHECK/#NOT_REQUIRED的差别; - 用"下推"思维判断逻辑该放 CDS 还是 ABAP。
Demo:参数化统计视图(分步跟做)¶
课程库的 zac_flight_stats(src/zac_flight_stats.ddls.abap):
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: '航班统计视图'
define view entity ZAC_FLIGHT_STATS
with parameters p_carrid : abap.char3
as select from sflight
{
key sflight.carrid,
count(*) as flight_count,
sum(sflight.price) as total_price,
avg(sflight.price) as avg_price,
sum(sflight.seatsmax) as total_seats,
sum(sflight.seatsocc) as total_occupied
}
where sflight.carrid = $parameters.p_carrid
group by sflight.carrid
观察三个设计点:
with parameters p_carrid : abap.char3——视图自带入参,统计口径"按公司"被编码进对象;- WHERE 里
$parameters.p_carrid引用参数——数据库执行时就过滤,不是查回来再筛; - GROUP BY 只留 carrid——上节课 Demo 误把 seatsmax 也分了组(同一公司不同机型会被拆成多行),这是 GROUP BY 的经典陷阱:分组键多一个,口径就碎一层。
消费端(demo 程序 zac_cds_advanced 已随仓库下发):
REPORT zac_cds_advanced.
START-OF-SELECTION.
" 参数化 CDS:调用时传参,语法像函数
SELECT * FROM zac_flight_stats( p_carrid = 'AA' )
INTO TABLE @DATA(lt_stats).
IF lines( lt_stats ) > 0.
READ TABLE lt_stats INTO @DATA(ls_stats) INDEX 1.
WRITE: / |航空公司: { ls_stats-carrid }|.
WRITE: / |航班数量: { ls_stats-flight_count }|.
WRITE: / |平均票价: { ls_stats-avg_price }|.
WRITE: / |总占座/总座位: { ls_stats-total_occupied }/{ ls_stats-total_seats }|.
ELSE.
WRITE: / '未找到统计数据'.
ENDIF.
ADT 里 Data Preview 参数化视图时会弹参数输入框——先在预览里试不同 carrid,再写程序。
知识点¶
1. CDS 函数工具箱¶
| 类别 | 常用 | 示例 |
|---|---|---|
| 聚合 | count(*) / sum / avg / min / max |
sum(sflight.price) as total_price |
| 标量 | cast / division / coalesce / concat_with / upper / substring |
division(total_occupied, total_seats, 2) as occupancy |
| 日期 | dats_add_days / dats_days_between |
dats_days_between(sflight.fldate, $session.system_date) |
| 条件 | case when ... then ... else ... end |
见下 |
CDS 里没有 IF 语句——条件一律 CASE(第8课 COND 的 SQL 版)。
2. Session 变量:数据库层的"sy-"系列¶
$session.user(当前用户)、$session.system_date(当日)等在数据库执行时求值——与 ABAP 的 sy-uname/sy-datum 对应,但求值发生在下推的 SQL 里。用途:行级数据归属过滤、快照口径。
3. DCL:CDS 的访问控制(悬念揭晓)¶
第20课 @AccessControl.authorizationCheck: #CHECK 的含义:有配套 DCL 就执行检查。DCL(Data Control Language)是独立的一类对象(ADT 里 New → DCL / 事务码无经典对应):
@MappingRole: true
define role ZAC_FLIGHT_DATA {
grant select on ZAC_FLIGHT_DETAIL
where (carrid) = aspect pfcg_auth(S_CARRID, CARRID, ACTVT = '03');
}
- 语义:谁能读这个视图的哪些行,由 PFCG 权限对象(S_CARRID)决定——权限不过滤"功能入口",直接过滤"数据行";
- 消费端无法绕过:ABAP 任何 SELECT 走这个视图,DCL 都在数据库层执行——比"程序里自己查权限再 WHERE"可靠得多;
- 没有 DCL 时:
#CHECK视为放行;#NOT_REQUIRED声明"此视图无需 DCL"(纯技术视图用它,消掉激活警告)。
4. View Entity 能力补充¶
上节课已切换到 View Entity 写法,它相对老 define view 的红利:无中间 SQL 视图命名负担、更多函数(如上面部分标量/日期函数)、更好的检查。7.55 以下系统只有老写法——看到 @AbapCatalog.sqlViewName 就知道是老项目。
5. $self:RAP 世界的"自身"(看得懂即可)¶
大纲把 $self 列在 View Entity 名下,严格说它住在隔壁:$self 是 RAP 行为定义(BDL)的关键字,指代"当前实体自身"——第23课预告的 RAP 世界的词。两个高频现身位置:action 的返回类型 result [1] $self(动作执行完把实体自己返回给界面),以及 side effects 里 $self affects ...(本实体发生增删改后触发前端刷新)。
" BDL 片段(行为定义,不是 CDS DDL)——认得出即可
action ApproveOrder result [1] $self;
side effects {
$self affects field _Item.TotalPrice;
}
课程终点在 CDS,RAP 只是眺望——遇到 $self 知道"这是实体在指自己"就够,不必现在会用。顺带认全 $ 前缀家族:$parameters(本课)、$session(第 2 节)、$node(CDS 层级视图专用)、$self(RAP BDL)——都是框架保留词,认脸即可。
6. 下推思维:逻辑放哪层¶
flowchart TD
Q{"这段逻辑是什么性质?"}
Q -->|"拼数据/口径/权限"| C["CDS 层<br/>(数据库执行,天然高性能)"]
Q -->|"展示格式/交互/流程"| A["ABAP 层<br/>(ALV/消息/屏幕)"]
Q -->|"跨行复杂算法"| H["ABAP 层处理<br/>(CDS 不擅长过程式计算)"]
判断口诀:能下推尽下推,聚合过滤优先 CDS;展示与流程永远 ABAP。第5课"别把几百万行拉回 ABAP 再 REDUCE"的教训,在这里变成架构原则。
💡 实战经验¶
口径资产化
"平均票价"这类统计口径一旦被两个以上报表使用,就固化成 CDS——口径只在视图里活一次,月末对不上数的排查范围从 N 个程序缩到 1 个对象。
GROUP BY 前先写业务定义
动手前用一句话写清统计口径("每家航空公司的全部航班"),再决定分组键。分组键凭手感加字段,是统计视图最大的翻车源。
DCL 漏配 = 裸奔
#CHECK 只在 DCL 存在时生效;上线前清点所有对外暴露的 CDS 是否该配 DCL。涉敏感数据的视图没配 DCL,等于把门禁贴在玻璃门上。
📖 延伸阅读¶
- ABAP Flight Reference Scenario(/DMO/)——官方场景里 DCL 与参数化视图的成熟样例;
- ABAP Keyword Documentation——ABAP CDS → Data Control Language 章节。
课后思考¶
把你的回答写在页面底部评论区,注明题号,一起讨论。
- 参数化视图的参数在什么时机生效(数据库 or 应用层)?这带来什么性能含义?
- 把 Demo 的分组键从 carrid 改成 carrid + connid,统计口径变成了什么?哪种更接近"航线维度"的运营报表?
- 给
zac_flight_stats加一个occupancy(上座率,两位小数)计算列——用哪个函数?贴出你的 DDL 片段。 - DCL 与第7课的 PFCG 权限(VALUE CHECK/MATCHCODE)分别在什么层拦数据?为什么说 DCL 更难被绕过?
下一课:第22课:OO ALV