SAP + AI 第2节 PS的三大对象间关系
SAP基于ABAP语言,定义了一套底层框架,用来解析CDS中的各种注解,再次感叹SAP这样搞,让国内的自研国产ERP怎么学啊,人家不是仅仅玩上层应用,人家先玩了一套底层框架,以ABAP为基础的底层框架。业务对象只能复制其行,无法复制其神啊。唉,国产ERP只能说任重道远。
现在写文档,大多都是AI了,最近都是对话了解学习信息,然后让AI总结信息,也方便自己查找。
今天主要讲解CDS视图的一些基础语法,主要研究的是项目定义、项目WBS和网络活动,有了这些对象视图,我们找数、取数弄报表,再也不是啥难事了,哈哈,都在自革命,知识壁垒越来越少了,真需要持续学习。
PS:以下全是AI生成
CDS视图基础篇文档
基于PS模块项目定义、WBS、网络活动的CDS视图体系分析整理
一、CDS视图基础概念
1.1 VDM三层架构
SAP的虚拟数据模型(VDM)将CDS视图分为三层:
| 层级 | 命名前缀 | 定位 | 示例 |
|---|---|---|---|
| 基础层 | I_ | 直接映射数据库表,完成字段重命名和类型转换 | I_Project、I_WBSElement |
| 组合层 | I_ / P_ | 基于基础层视图组合,通过UNION ALL合并运营与版本数据 | I_ProjectWithVersion、P_ProjectWithVersion |
| 消费层 | C_ | 面向Fiori应用和OData服务,包含UI注解 | C_ProjectBasicInfo、C_WBSElementBasicInfo |
1.2 命名规范
| 前缀 | 含义 | 说明 |
|---|---|---|
I_ | Interface View | 接口视图,供SAP内部和开发者复用 |
C_ | Consumption View | 消费视图,面向最终用户和OData服务 |
P_ | Private View | 私有视图,标注 @VDM.private: true,仅供内部使用 |
E_ | Extension View | 扩展视图,用于客户自定义字段扩展 |
R_ | RAP BO View | RAP业务对象基础视图 |
Z_ / Y_ | 自定义视图 | 客户自定义命名空间 |
1.3 关联(Association)机制
定义语法:
association [基数] to 目标视图 as _别名
on $projection.源字段 = _别名.目标字段
基数类型:
| 基数 | 含义 |
|---|---|
[1..1] | 一对一 |
[0..1] | 零或一对一 |
[1..*] | 一对多 |
[0..*] | 零对多 |
关键规则:
- 关联必须在上游视图的SELECT列表中显式暴露,下游才能继承
- 下游要使用关联,必须在自己的SELECT列表中显式写出
_别名 - 关联不是自动继承的,每层都要主动暴露
二、PS模块三大业务对象
2.1 项目定义
数据库表:PROJ(运营项目)、VSPROJ_CN(版本项目)
CDS视图链路:
proj(DB表)
└→ I_Project(基础层,运营项目)
vsproj_cn(DB表)
└→ I_ProjectVersion(基础层,版本项目)
I_Project + I_ProjectVersion
└→ P_ProjectWithVersion(私有组合层,UNION ALL合并)
└→ I_ProjectWithVersion(组合层)
└→ C_ProjectBasicInfo(消费层)
关键关联字段:
| 字段 | 数据元素 | 用途 |
|---|---|---|
ProjectInternalID | PS_PSP_PNR | 项目定义内部编号(关联键) |
Project | PS_PSPID | 项目定义外部编号(显示用) |
Version | VSNMR_V | 版本号 |
ProjectObject | J_OBJNR | 状态对象号 |
2.2 WBS元素
数据库表:PRPS + PRTE(运营WBS)、VSPRPS_CN + VSPRTE_CN(版本WBS)
CDS视图链路:
prps + prte(DB表)
└→ I_WBSElement(基础层,运营WBS)
vsprps_cn + prps + vsprte_cn(DB表)
└→ I_WBSElementVersion(基础层,版本WBS)
I_WBSElement + I_WBSElementVersion
└→ P_WBSElementWithVersion(私有组合层,UNION ALL合并)
└→ I_WBSElementWithVersion(组合层)
└→ C_WBSElementBasicInfo(消费层)
关键关联字段:
| 字段 | 数据元素 | 用途 |
|---|---|---|
WBSElementInternalID | PS_PSP_PNR / PS_POSNR | WBS内部编号(关联键) |
WBSElement | PS_POSID | WBS外部编号 |
ProjectInternalID | PS_PSP_PNR | 所属项目定义内部编号 |
WBSElementObject | J_OBJNR | 状态对象号 |
2.3 网络活动
数据库表:AFVC + AFVV + AFVU + AFKO + AUFK(运营)、VSAFVC_CN + VSAFVV_CN + VSAFVU_CN + VSAFKO_CN + VSAUFK_CN(版本)
CDS视图链路:
afvc + afvv + afvu + afko + aufk(DB表)
└→ I_NetworkActivity(基础层,运营活动)
vsafvc_cn + vsafvv_cn + vsafvu_cn + vsafko_cn + vsaufk_cn(DB表)
└→ I_NetworkActivityVersion(基础层,版本活动)
I_NetworkActivity + I_NetworkActivityVersion
└→ P_NetworkActivityWithVersion(私有组合层,UNION ALL合并)
└→ I_NetworkActivityWithVersion(组合层)
└→ C_NetworkActivityBasicInfo(消费层)
关键关联字段:
| 字段 | 数据元素 | 用途 |
|---|---|---|
ProjectNetwork | PS_S4_AUFNR | 网络编号 |
NetworkActivity | PT_VORNR_RECEIVER | 活动编号 |
WBSElementInternalID | PS_PSP_PNR | 所属WBS内部编号 |
NetworkActivityObject | J_OBJNR | 状态对象号 |
三、三大对象之间的关联关系
3.1 关联链路
项目定义(Project)
↓ ProjectInternalID
WBS元素(WBSElement)
↓ WBSElementInternalID
网络活动(NetworkActivity)
3.2 关联定义原文
项目定义 → WBS(定义在 I_Project):
association [1..*] to I_WBSElement as _WBSElement
on $projection.ProjectInternalID = _WBSElement.ProjectInternalID
WBS → 项目定义(定义在 I_WBSElement):
association [1..1] to I_ProjectByInternalKey as _Project
on $projection.ProjectInternalID = _Project.ProjectInternalID
WBS → 网络活动(定义在 I_WBSElementWithVersion 侧反向查看):
association [1..1] to I_WBSElementWithVersion as _WBSElement
on $projection.WBSElementInternalID = _WBSElement.WBSElementInternalID
and $projection.Version = _WBSElement.Version
版本场景必须双字段关联:ProjectInternalID + Version 或 WBSElementInternalID + Version。
3.3 关联能成立的底层原理
两个CDS字段能否关联,取决于它们底层是否使用同一个数据元素:
| 字段名 | 数据元素 | 能关联的原因 |
|---|---|---|
ProjectInternalID | PS_PSP_PNR | 项目定义和WBS共用同一数据元素 |
WBSElementInternalID | PS_PSP_PNR | WBS和网络活动共用同一数据元素 |
Version | VSNMR_V | 版本视图共用 |
数据元素在DDIC层通过域(Domain) 和外键定义了指向关系,CDS的association只是把这种已存在的关系显式声明出来。
3.4 单向 vs 互相定义的原则
| 场景 | 定义策略 | 原因 |
|---|---|---|
| 子→父(N:1) | 总是定义 | 核心导航方向,从明细反查主数据 |
| 父→子(1:N) | 按需定义 | 数据量大时性能风险高 |
| 合并视图的父→子 | 不定义 | UNION ALL无法用静态ON表达 |
| 循环引用 | 用辅助视图解耦 | 如 I_ProjectByInternalKey |
四、UNION ALL合并机制
4.1 运营与版本数据的融合
P_ProjectWithVersion 和 P_WBSElementWithVersion 都用 UNION ALL 合并两类数据:
| 分支 | 数据源 | Version字段值 |
|---|---|---|
| 运营数据 | I_Project / I_WBSElement | 硬编码为 ''(空字符串) |
| 版本数据 | I_ProjectVersion / I_WBSElementVersion | 实际版本号 |
关键设计:运营分支的Version硬编码为空字符串,保证合并后两分支数据类型一致,且下游关联的 and Version = ... 条件能同时命中两类数据。
4.2 合并后的关联重建
由于合并视图的数据源变了,关联必须重新定义:
// I_WBSElementWithVersion 中重新定义指向合并后的项目视图
association [1..1] to I_ProjectWithVersion as _Project
on _Project.ProjectInternalID = $projection.ProjectInternalID
and _Project.Version = $projection.Version
基础层指向 I_ProjectByInternalKey,组合层指向 I_ProjectWithVersion。每层关联目标不同,不是重复定义。
五、转换出口问题与CAST解决方案
5.1 什么是转换出口
转换出口(Conversion Exit)是SAP GUI时代的格式化机制,用于在内部存储格式和外部显示格式之间转换:
| 转换出口 | 作用对象 | 示例 |
|---|---|---|
ABPSN | 项目定义编号 | 内部12345678 ↔ 外部ABC-123 |
ABPSP | WBS元素内部ID | 内部编码 ↔ 外部显示 |
NUMCV | 网络/活动编号 | 外部'1234' ↔ 内部'00001234' |
ALPHA | 通用字母数字编号 | 前导零处理(RAP支持较好) |
5.2 为什么RAP不支持转换出口
| 维度 | SAP GUI(有状态) | OData/RAP(无状态) |
|---|---|---|
| 数据量 | 小 | 海量 |
| 操作层 | 应用服务器内存 | HANA数据库层 |
| 筛选排序 | 应用层执行 | 数据库层执行 |
| 转换出口 | 支持 | 不支持 |
转换出口是ABAP应用层的逻辑,无法在HANA数据库层执行,因此在RAP Service Binding发布时会被框架拦截。
5.3 CAST解决方案
原理:CAST创建一个类型全新的字段,不再继承原数据元素的任何属性(包括转换出口)。
// 错误写法:preserving type 会保留转换出口
cast( ProjectInternalID as ps_s4_proj_pspnr preserving type ) as ProjectInternalID
// 正确写法:纯类型转换,消除转换出口
cast( ProjectInternalID as abap.char(24) ) as ProjectInternalID
关键点:
- 必须去掉
preserving type关键字 - 目标类型用
abap.char(n)等基础类型 - 长度建议
24或40,足以容纳格式化后的值
5.4 CAST后重建关联
由于CAST后字段类型变了,原有继承的关联会因类型不匹配而失效。需要在Z视图中重新定义关联:
@AbapCatalog.sqlViewName: 'ZCNTWKACTYBSC'
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Z - Network Activity Basic Info'
@Metadata.ignorePropagatedAnnotations: true
define view Z_C_NETWORKACTIVITYBASICINFO
as select from C_NetworkActivityBasicInfo
// 重新定义关联,ON条件两边类型对齐
association [0..1] to I_WBSElementWithVersion as _WBSElementCast
on $projection.WBSElementInternalID = cast( _WBSElementCast.WBSElementInternalID as abap.char(24) )
{
key ProjectNetwork,
key cast( NetworkActivity as abap.char(24) ) as NetworkActivity,
key Version,
@ObjectModel.foreignKey.association: '_WBSElementCast'
cast( WBSElementInternalID as abap.char(24) ) as WBSElementInternalID,
NetworkActivityDescription,
Plant,
_Status,
_Supplier,
_WBSElementCast
}
关键规则:
- 关联目标必须选对(指向
I_WBSElementWithVersion) - ON条件右侧也要CAST,类型对齐
- 关联名建议换一个(如
_WBSElementCast),避免覆盖源视图的_WBSElement - 添加
@ObjectModel.foreignKey.association注解,满足RAP外键约束
5.5 不需要关联的场景
如果Z视图只取WBS内部ID的值,不做导航:
define view Z_C_NETWORKACTIVITYBASICINFO
as select from C_NetworkActivityBasicInfo
{
key ProjectNetwork,
key cast( NetworkActivity as abap.char(24) ) as NetworkActivity,
key Version,
cast( WBSElementInternalID as abap.char(24) ) as WBSElementInternalID,
NetworkActivityDescription,
// 不暴露 _WBSElement,编译通过
}
CAST后字段不再是外键,RAP的"字段+关联成对暴露"约束不再适用,可以直接编译通过。
六、OData服务发布流程
6.1 完整步骤
- 创建CDS视图:在ADT中定义Z视图,处理CAST和关联
- 创建Service Definition:暴露CDS实体
@EndUserText.label: 'Service Definition' define service ZSD_NETWORKACTIVITY { expose Z_C_NetworkActivityBasicInfo; } - 创建Service Binding:绑定类型选 OData V2(1909版本推荐)
- 发布(Publish):在Service Binding编辑器中点击Publish
- 网关注册:SAP GUI执行
/IWFND/MAINT_SERVICE,手动添加服务并分配传输请求
6.2 常见报错与解决方案
| 报错 | 原因 | 解决方案 |
|---|---|---|
Do not use conversion exit ABPSN here | 项目编号带转换出口 | CAST消除 |
Do not use conversion exit ABPSP here | WBS内部ID带转换出口 | CAST消除 |
Do not use conversion exit NUMCV here | 网络/活动编号带转换出口 | CAST消除 |
must be included together with '_WBSELEMENT' | 外键字段与关联未成对暴露 | 同时暴露字段和关联,或CAST消除外键属性 |
元数据未加载 | 静态检查失败 | 查看 /IWBEP/ERROR_LOG 定位具体字段 |
6.3 错误日志查看
- 事务码:
/IWBEP/ERROR_LOG - 日志内容:包含
ENTITY(视图名)、PROPERTY(字段名)、CONVEXIT(转换出口名) - 用途:精确定位是哪个字段触发了检查
七、关键总结
7.1 字段引用 vs 关联导航
| 写法 | 含义 | 是否需要暴露关联 |
|---|---|---|
WBSElement.Project | 读源视图的平铺字段 | 不需要 |
_Project.Project | 通过关联导航取字段 | 需要 |
WBSElement._Project.xxx | 沿源视图的关联路径导航 | 需要源视图已暴露 |
7.2 拍平不等于丢失导航
拍平(_Project.Project as Project)只是把值取出来变成普通字段,不影响关联本身。只要源视图同时暴露了 _Project,导航能力就完整保留。
7.3 关联继承规则
上游定义 + 上游暴露 + 下游显式写出 = 下游可用
缺任何一步都用不了下划线关联。
7.4 转换出口处理原则
| 场景 | 处理方式 |
|---|---|
| 标准视图不能改 | 在Z视图中CAST |
| CAST后不需要导航 | 只CAST,不定义关联 |
| CAST后需要导航 | CAST + 重新定义关联(ON条件两边类型对齐) |
| RAP需要外键 | 加 @ObjectModel.foreignKey.association 注解 |
7.5 关联字段选择原则
永远用内部ID关联(如 ProjectInternalID、WBSElementInternalID),因为:
- 纯数字类型,性能最优
- 无转换出口,RAP兼容
- 数据类型统一,ON条件稳定
不用外部ID关联(如 Project、WBSElement),因为:
- 带转换出口,RAP不支持
- 字符串类型,性能较差
附录:常用事务码与工具
| 工具 | 用途 |
|---|---|
ADT | ABAP Development Tools,CDS开发主环境 |
Ctrl + Shift + A | ADT全局搜索对象 |
Ctrl + F3 | 激活对象 |
SE11 | 查看数据元素、域、外键 |
SE80 | 查看包内所有对象 |
SE84 | 搜索CDS视图清单 |
DD26S | 反查表被哪些CDS引用 |
/IWFND/MAINT_SERVICE | OData服务注册与管理 |
/IWBEP/ERROR_LOG | 查看RAP发布错误日志 |
View Browser | Fiori应用,浏览所有CDS视图 |
—、
二、下面是我在学习过程中的一些关键疑问,算是学习过程吧,供参考
Q1:销售合同和销售订单是不是重复了?
核心答案:不重复。销售合同是框架协议(总量授权),销售订单是具体执行(单次提货)。合同通过“合同履行”机制被订单引用,释放数量达到目标后合同完成。
关键认知:SAP对“协议”和“执行”两类业务语义有标准区分,CDS视图也是分开建模的。
Q2:CDS视图为什么做成层级?
核心答案:为了解决“同一份底层数据,安全高效地服务于从交易到分析的众多场景”这一矛盾。VDM三层架构:
| 层级 | 职责 | 成本中心示例 |
|---|---|---|
| 基础层 | 技术解耦、字段重命名 | I_CostCenter |
| 组合层 | 语义组合、建立关系 | I_CostCenterHierarchyNode |
| 消费层 | 场景化呈现 | C_CostCenterQ2001 |
关键认知:分层的本质好处是单一事实来源、语义逐步精炼、关注点分离、权限内聚、扩展边界清晰。
Q3:I、C、P开头的视图有什么区别?
| 前缀 | 含义 | 定位 | 核心特征 |
|---|---|---|---|
I_ | Interface View | 基础/组合层 | 承载业务逻辑,供内部复用 |
C_ | Consumption View | 消费层 | 面向Fiori/OData,含UI注解 |
P_ | Private View | 消费层 | @VDM.private: true,内部特供 |
关键认知:P_本质也是消费层,但不对外发布,专为某个OData服务定制。
二、关联与导航机制类
Q4:关联字段如何确定?为什么两个字段能关联?
核心答案:由底层数据元素(Data Element)的语义一致性决定。
| 字段 | 数据元素 | 能关联的原因 |
|---|---|---|
PRPS.PSPNR | PS_PSP_PNR | 基准 |
AFVC.PROJN | PS_PSP_PNR | 同数据元素 |
PROJ.PSPNR | PS_PSP_PNR | 同数据元素 |
数据元素在DDIC层通过域和外键定义了指向关系。CDS的association只是把已存在的关系显式声明出来。
关键认知:两个CDS字段能否关联,取决于它们底层是否使用同一个数据元素。CDS的ON条件必须类型匹配,数据元素保证了这个匹配。
Q5:为什么能互相定义关联?什么时候单向?
| 场景 | 定义策略 | 原因 |
|---|---|---|
| 子→父(N:1) | 总是定义 | 核心导航方向 |
| 父→子(1:N) | 按需定义 | 数据量大时性能风险高 |
| 合并视图的父→子 | 不定义 | UNION ALL无法用静态ON表达 |
| 循环引用 | 用辅助视图解耦 | 如 I_ProjectByInternalKey |
关键认知:I_WBSElement._Project 指向 I_ProjectByInternalKey,不是 I_Project。SAP专门建辅助视图来解决循环引用和主键约束问题。
Q6:为什么 I_ProjectWithVersion 没有定义反向的1:N导航?
三重原因:
- 循环依赖:
I_WBSElementWithVersion已定义_Project指向它,反向再定义会闭环 - 数据源无法静态匹配:合并视图是UNION ALL,静态ON无法根据Version动态切换目标
- 性能:一个项目下几百上千WBS,父→子暴露会导致
$expand灾难
关键认知:SAP只在子→父方向定义关联,反向导航由OData层或消费层按需定义。
Q7:消费层能重复定义导航吗?为什么不继承?
核心答案:CDS关联是按需暴露,不是自动继承。
// 上游定义了 _Project
// 下游必须显式写出 _Project 才能继承
define view C_DOWN as select from I_UP {
_Project // ← 显式写出才继承
}
关键认知:下游不写 _Project,就用不了导航。这是CDS分层的核心——每层自己决定暴露什么,避免OData元数据爆炸和安全失控。
Q8:C_WBSElementBasicInfo 没定义 _Project,为什么能用 Project 字段?
核心答案:字段引用 ≠ 关联导航。
| 写法 | 含义 | 需要关联吗 |
|---|---|---|
WBSElement.Project | 读源视图的平铺字段 | ❌ 不需要 |
_Project.Project | 通过关联导航取字段 | ✅ 需要 |
Project 早在基础层(I_WBSElementVersion)就被 _Project.Project as Project 拍平成普通字段,上层直接读即可。
关键认知:拍平 = 把值取出来变普通字段;导航 = 走关联路径。两者是不同的操作。
Q9:拍平后关联能力是否丢失?
核心答案:不丢失。源视图里两个操作并存:
_Project.Project as Project, // 拍平
_Project, // 暴露关联本身
拍了平,但只要同时暴露了 _Project,导航能力就完整保留。
关键认知:关联导航是“路”,字段拍平是“把车从路上开出来”。车开出来,路还在。路没铺(没暴露),就自己铺(重新定义关联)。
Q10:底层定义了下划线,上层能直接引用吗?
核心答案:能,但有两个前提:
- 上游必须暴露:SELECT列表中写出
_Xxx - 下游必须显式写出:自己的SELECT列表中也要写
_Xxx
上游定义 + 上游暴露 + 下游显式写出 = 下游可用
关键认知:缺任何一步都用不了下划线关联。CDS关联不是自动继承的。
三、转换出口与CAST类
Q11:为什么RAP发布报错“Do not use conversion exit ABPSN here”?
核心原因:RAP OData服务不支持转换出口。
| 维度 | SAP GUI | OData/RAP |
|---|---|---|
| 数据量 | 小 | 海量 |
| 筛选排序 | 应用层 | HANA数据库层 |
| 转换出口 | 支持 | 不支持 |
转换出口是ABAP应用层的格式化逻辑,无法在HANA数据库层执行,因此RAP在静态检查阶段直接拦截。
关键认知:ABPSN(项目编号)、ABPSP(WBS内部ID)、NUMCV(网络活动编号)都是PS模块的转换出口,都会触发报错。
Q12:为什么必须CAST?原理是啥?
核心答案:CAST创建一个类型全新的字段,不再继承原数据元素的任何属性(包括转换出口)。
// 错误:preserving type 会保留转换出口
cast( Project as psb_bo_pspid_de preserving type ) as Project
// 正确:纯类型转换,消除转换出口
cast( Project as abap.char(24) ) as Project
关键认知:preserving type 是关键陷阱——它保留原数据元素的所有属性,转换出口不会被消除。必须用纯 abap.char(n) 类型。
Q13:源视图是官方的,不能改,怎么在Z视图处理?
核心答案:在Z视图里“自己造一条新路”:
define view Z_C_NETWORKACTIVITYBASICINFO
as select from C_NetworkActivityBasicInfo
// 重新定义关联,ON条件两边CAST对齐
association [0..1] to I_WBSElementWithVersion as _WBSElementCast
on $projection.WBSElementInternalID = cast( _WBSElementCast.WBSElementInternalID as abap.char(24) )
{
key ProjectNetwork,
key cast( NetworkActivity as abap.char(24) ) as NetworkActivity,
key Version,
@ObjectModel.foreignKey.association: '_WBSElementCast'
cast( WBSElementInternalID as abap.char(24) ) as WBSElementInternalID,
_Status,
_Supplier,
_WBSElementCast // 暴露新关联
}
关键认知:
- 关联目标必须选对(
I_WBSElementWithVersion) - ON条件右侧也要CAST,类型对齐
- 关联名换一个(
_WBSElementCast),避免覆盖源视图的 - 加
@ObjectModel.foreignKey.association注解满足RAP约束
Q14:什么时候不需要加 _WBSElement?
核心答案:如果只取WBS内部ID的值,不做导航,不需要加。
CAST后字段变成普通CHAR,不再是外键,RAP的“字段+关联成对暴露”约束不适用,直接编译通过。
关键认知:
- 需要导航 → 加关联
- 只需要值 → 不加关联
- 需要RAP事务 → 加关联+外键注解
Q15:项目版本未启用,是不是就没数据?
核心答案:是。项目版本功能需要显式配置(项目参数文件中关联版本参数文件)。未配置时,VSPROJ_CN 表没有数据,CDS视图的版本分支查不到记录。
关键认知:P_ProjectWithVersion 的UNION ALL中,运营分支有数据,版本分支为空。视图能正常返回运营数据,但Version字段显示空字符串。
Q16:Release状态会记录到版本吗?
核心答案:会,但前提是版本参数文件中配置了“Release时创建版本”。
- 系统状态触发:Release项目/网络时自动创建版本
- 用户状态触发:配置的用户状态变化时创建版本
- 未配置版本参数文件:即使Release也不创建版本
关键认知:SAP标准系统不提供预配置的版本参数文件,必须在 OPTS 中自行定义。
四、OData发布与调试类
Q17:如何把C开头视图发布成OData服务?
三种方式:
| 方式 | 做法 | 适用场景 |
|---|---|---|
@OData.publish: true | 注解自动暴露 | 简单视图,快速验证 |
| Service Definition + Binding | RAP标准做法 | 复杂业务,推荐 |
| SEGW | 传统方式 | 不推荐 |
关键认知:1909版本必须用OData V2,发布后必须在 /IWFND/MAINT_SERVICE 手动注册才能对外可用。
Q18:发布报错怎么看日志?
核心工具:事务码 /IWBEP/ERROR_LOG
日志关键信息:
ENTITY:哪个视图PROPERTY:哪个字段CONVEXIT:哪个转换出口
关键认知:报错日志精确定位到实体+属性+转换出口,据此可以逐个CAST解决。
Q19:ADT里怎么看哪些CDS支持增删改?
核心方法:
- 查看是否存在行为定义(BDEF)
- 查看CDS源码中的
@ObjectModel.createEnabled等注解 - 用Data Preview尝试编辑
关键认知:CDS视图本身不定义可写性,能否增删改由行为定义(BDEF) 决定。CDS可写视图(writable view entity)仅适用于简单单表维护。
五、ADT工具操作类
Q20:怎么在ADT里按应用组件筛选CDS视图?
三种方法:
Ctrl + Shift + A,输入appl:MM快速定位Ctrl + H,输入type:DDLS appl:MM组合筛选- 配置ABAP仓库树,按
Application Component层级浏览
关键认知:Data Definitions 文件夹里才是CDS视图(DDLS)。Access Controls 是权限对象,Behavior Definitions 是行为定义。
Q21:包切换后对象找不到怎么办?
核心答案:使用 Favorite Packages(收藏夹)功能。
- 右键
Favorite Packages→Add Package - 输入包名
- 树里会重新加载,展开
Source Code Library或Business Services找到对象
关键认知:$TMP 本地包对象不会记录到传输请求,正式开发必须切到自己的开发包。
Q22:GUI里怎么看CDS视图?
| 事务码 | 用途 |
|---|---|
SE11 | 查看CDS字段和结构 |
SE80 | 查看包内所有对象 |
SE84 | 搜索CDS视图清单 |
DD26S | 反查表被哪些CDS引用 |
/IWFND/MAINT_SERVICE | 查看OData服务状态 |
关键认知:GUI里看CDS源码体验很差,写代码、建服务、发布永远首选ADT。
六、核心认知总结
| 认知点 | 一句话 |
|---|---|
| 关联本质 | 由底层数据元素决定,CDS只是显式声明 |
| 关联继承 | 上游暴露 + 下游写出 = 可用,缺一不可 |
| 拍平vs导航 | 拍平不删关联,字段引用和关联导航是两回事 |
| 单向vs双向 | 子→父总是定义,父→子按需定义,合并视图不定义 |
| 转换出口 | SAP GUI时代的产物,与OData无状态架构冲突 |
| CAST原理 | 创建新类型字段,切断与原数据元素的继承关系 |
| CAST陷阱 | 不能用 preserving type,否则转换出口保留 |
| CAST后关联 | ON条件两边都CAST,类型对齐才能关联 |
| 版本关联 | 双字段关联:内部ID + Version |
| 版本数据 | 未启用版本参数文件 = 无版本数据 |
| OData发布 | 1909版本必须V2,必须网关注册 |
| 错误日志 | /IWBEP/ERROR_LOG 精确定位实体+属性+转换出口 |
精华整理完毕。
文档整理完毕。

3232

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



