Mark的技术博客

SAP顾问 | 咨询专家 | IT与AI技术探索者

吴让宇(Mark)

吴让宇(Mark)

SAP顾问 | 咨询专家 | IT与AI技术探索者

吴让宇(Mark)的个人技术博客,专注于SAP系统实施、行业方案咨询、IT技术与AI技术的研究与分享。

SAP Fiori ABAP CDS OData Dify Docker AI LLM

最新文章

域固定值检查 (★★★)

#abap #abap-dictionary #abap-validation

概览表

Mechanism (机制) Level (层级) Description (描述)
域固定值 Domain 离散值或区间限制
外键检查 Table Field 引用检表验证
文本表 Table 语言相关文本验证

域值范围 (Value Range)

在域定义的 Value Range 选项卡中设置:

Type (类型) Description (描述) Example (示例)
Fixed Values (固定值) 离散允许值列表 A, F, S
Intervals (区间) 允许值的范围 1 - 999

固定值示例

1
2
3
4
5
6
Domain: Z_AREA
Value Range:
Fixed Values:
A → Administration personnel (管理人员)
F → Flight personnel (飞行人员)
S → Service personnel (服务人员)
💡固定值 vs 检表
  • 固定值: 少量、稳定的值(如状态码)→ 定义在域上
  • 检表: 大量、可能增长的值(如客户列表)→ 使用外键检查

固定值检查的工作方式

1
2
3
用户输入值 → 检查域的固定值/区间 → 通过/拒绝

同时作为 F4 帮助的值来源
  • 固定值自动成为 F4 帮助的候选值
  • 所有使用该域的数据元素都会受到约束
  • 修改域的固定值会影响所有引用该域的字段
⚠️固定值限制
固定值适用于少量且稳定的值。如果值经常变化或数量多,应使用外键检查。

输入检查层次

Priority (优先级) Mechanism (机制) 适用场景
1 域固定值 枚举值
2 外键检查 引用完整性
3 程序内检查 复杂业务逻辑

考试/测试模式

Scenario/Keyword (场景/关键词) Answer (答案)
“固定值定义在哪里?” 域的 Value Range 选项卡
“固定值会影响 F4 帮助吗?” ,自动成为 F4 候选
“大量可选值用什么机制?” 外键检查(检表),不用固定值

透明表与 Include 结构 (★★★★)

#abap #abap-dictionary #abap-tables

概览表

Concept (概念) Key Point (要点)
Transparent Table (透明表) Dictionary 定义 = 数据库结构,同名同字段
Two-Level Domain Concept 域(技术) → 数据元素(语义) → 字段
Include Structure 避免冗余,可传递外键定义
Currency/Quantity Fields 必须指定引用表和引用字段

透明表 (Transparent Table)

透明表在激活时自动在数据库中创建,Dictionary 与数据库的对应关系:

Dictionary Database
同名 同名
同字段名 同字段名
Dictionary 数据类型 转换为对应 DB 数据类型
💡字段顺序
Dictionary 中的字段顺序可以与数据库中的不同。这允许插入新字段而不转换表(ALTER TABLE 添加新列)。

两级域概念 (Two-Level Domain Concept)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
           ┌─────────┐
│ Domain │ 技术属性(类型、长度、值域)
│ S_AIRPID │
└────┬─────┘
┌─────────┴─────────┐
┌─────┴──────┐ ┌─────┴──────┐
│ Data Element│ │ Data Element│ 语义属性(含义、标签)
│ S_FROMAIRP │ │ S_TOAIRP │
│ (出发机场) │ │ (到达机场) │
└─────┬──────┘ └─────┬──────┘
│ │
┌─────┴──────┐ ┌─────┴──────┐
│ AIRPFROM │ │ AIRPTO │ 表字段
│ (SPFLI 表) │ │ (SPFLI 表) │
└────────────┘ └────────────┘
  • 同一个域(S_AIRPID)可被不同数据元素复用
  • 不同数据元素赋予不同的语义含义(出发 vs 到达)

表字段定义

Component (要素) Description (描述)
Key Fields (键字段) 主键,唯一标识每条记录
Data Elements (数据元素) 定义字段的语义和技术属性
Built-in Type 可直接指定类型(不经过域/数据元素)
Currency/Quantity CURR/QUAN 类型必须指定引用表和引用字段
⚠️货币/数量字段引用
CURR 字段 → 引用表中的 CUKY 字段
QUAN 字段 → 引用表中的 UNIT 字段
引用字段在运行时才关联,不是定义时。

Include 结构

规则

Rule (规则) Detail (详情)
用途 避免冗余结构定义
链中数据库表 只能有一个(表本身)
嵌套 Include Include 中可以包含 Include
外键传递 Include 中的外键定义会传递到父表
整表 Include 必须包含整个表

操作方式

  1. 菜单方式: Edit → Include → Insert
  2. 手动方式: 在 Component 列输入 .INCLUDE(注意前面的点),然后指定结构名
1
2
3
4
5
6
7
8
9
10
11
ZEMPLOY## 表
├── CLIENT (S_CLIENT)
├── CARRIER (S_CARR_ID) ← Key
├── EMP_NUM (ZEMP_NUM##) ← Key
├── FIRST_NAME (S_FNAME)
├── LAST_NAME (S_LNAME)
├── .INCLUDE ZCHANGE## ← Include 结构
│ ├── CHANGED_BY
│ └── CHANGED_DATE
├── SALARY (ZSALARY##)
└── CURRENCY (S_CURRCODE)

表的透明表 vs 结构

Feature Transparent Table Structure
数据库对象 有(自动创建)
可存数据 否(仅类型定义)
用途 数据存储 + 类型定义 仅定义类型

索引与表缓冲 (★★★★)

#abap #abap-dictionary #abap-performance

概览表

Technique (技术) Purpose (目的) Impact (影响)
Primary Index (主索引) 键字段排序查找 自动创建
Secondary Index (二级索引) 非键字段加速 需手动创建
Full Buffering (完全缓冲) 全表加载到内存 小表、读频繁
Generic Buffering (通用缓冲) 按键前缀加载 分组访问
Single-record Buffering (单记录) 仅加载访问的记录 大表、随机访问

索引 (Indexes)

结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Index (索引) = 排序的字段子集 + 指向原表的指针

Table: SPFLI
┌────────┬────────┬──────────┬───────────┐
│ CARRID │ CONNID │ CITYFROM │ CITYTO │ ← 原表
├────────┼────────┼──────────┼───────────┤
│ AA │ 0017 │ NEW YORK │ SAN FRAN │
│ LH │ 0400 │ FRANKFURT│ NEW YORK │
└────────┴────────┴──────────┴───────────┘

Secondary Index A11 (CITYFROM, CITYTO):
┌──────────┬───────────┬────────┐
│ CITYFROM │ CITYTO │ → PTR │ ← 索引(排序存储)
├──────────┼───────────┼────────┤
│ FRANKFURT│ NEW YORK │ Row 2 │
│ NEW YORK │ SAN FRAN │ Row 1 │
└──────────┴───────────┴────────┘

索引类型

Type ID Description
Primary Index 0 键字段,自动创建
Secondary Index Y/Z 开头 客户创建
Unique Index 索引字段唯一标识记录

索引使用规则

📌索引使用条件
  1. 索引只能使用到最后一个在 WHERE 中指定的字段
  2. 跳过中间字段 → 后续字段无法使用索引
  3. WHERE 中出现频率高的字段应放在前面
  4. 只有显著减少数据量的字段才有意义加入索引

创建索引注意事项

考虑因素 建议
字段顺序 高频 WHERE 字段在前
字段数量 选择区分度高的字段
表修改频率 频繁修改的表不要太多索引
索引互斥性 同一表的索引尽量不相交
数据库特定 可指定只在特定 DB 上创建
唯一性 如有键功能,设为 Unique Index
⚠️索引维护开销
每次修改表数据都需调整索引排序。频繁修改的表应控制索引数量

表缓冲 (Table Buffering)

缓冲将表数据加载到应用服务器的本地内存中,性能提升 10-100 倍

缓冲类型对比

1
2
3
4
5
6
7
8
9
10
11
12
13
14
完全缓冲 (Full):
触发: 访问任一记录
加载: 全表所有记录
适用: ≤10,000 条,读频繁,很少修改

通用缓冲 (Generic):
触发: 访问某记录
加载: 同一左键前缀的所有记录
适用: 按键前缀分组访问

单记录缓冲 (Single-record):
触发: 访问某记录
加载: 仅该条记录
适用: 大表、随机访问

缓冲同步机制

1
2
3
4
5
6
7
App Server A (Buffer)          Database
├── Table T records ←→ Table T
├── 读取: 直接从缓冲 ↓ 修改
└── 命中: 快速返回 同步通知

App Server B (Buffer) 其他服务器缓冲失效
└── 失效后重新加载
  • 数据修改时,所有应用服务器的缓冲被标记失效
  • 失效后的第一次访问需要从数据库重新加载
  • 同步是异步执行的
⚠️缓冲重置
/$TAB 命令重置表缓冲——仅在出现不一致时使用
大型系统重置后需数小时重新填充,期间性能大幅下降

缓冲建议

场景 建议
读多写少,数据量小 完全缓冲
按键前缀分组读 通用缓冲
大表随机读 单记录缓冲
频繁修改 不缓冲
实时性要求高 不缓冲

考试/测试模式

Scenario/Keyword (场景/关键词) Answer (答案)
“索引使用到哪个字段?” 最后一个在 WHERE 中指定的字段
“二级索引 ID 命名?” 客户创建以 Y 或 Z 开头
“完全缓冲触发条件?” 访问任一记录时加载全表
“缓冲能提升多少性能?” 10 到 100 倍
“/$TAB 命令用途?” 重置表缓冲(仅修复不一致)

文本表 (★★★)

#abap #abap-dictionary #abap-validation

概览表

Element (要素) Description (描述)
Purpose (目的) 存储多语言文本描述
Key Structure (键结构) 主表键 + Language (SPRAS)
Relationship (关系) 与主表 N:1(一条主表记录对应多条语言文本)
Auto Usage 自动用于 F4 帮助的文本显示

文本表结构

文本表是主表的附加描述表,按语言存储文本。

1
2
3
4
5
6
7
8
9
主表: ZDEPMENT##              文本表: ZDEPMENTT##
┌────────┬──────────┬───┐ ┌────────┬──────────┬──────┬──────┐
│ CLIENT │ CARRIER │DEP│ │ CLIENT │ CARRIER │ LANG │ TEXT │
│ (Key) │ (Key) │(K)│ │ (Key) │ (Key) │(Key) │ │
├────────┼──────────┼───┤ ├────────┼──────────┼──────┼──────┤
│ 100 │ AA │01 │ │ 100 │ AA │ E │Sales │
│ 100 │ AA │02 │ │ 100 │ AA │ D │Verk. │
└────────┴──────────┴───┘ │ 100 │ AA │ E │Mkt │
└────────┴──────────┴──────┴──────┘

文本表的必要条件

Condition (条件) Detail (详情)
键结构 主表键字段 + Language 字段
Language 字段 使用域 SPRAS
Language 外键 引用表 T002(语言表)
文本字段 第一个字符型非键字段
外键类型 Key fields of a text table

创建步骤

1
2
3
4
1. 创建文本表(结构与主表键 + LANG + TEXT)
2. 定义 DepCode → 主表的外键(从主表复制时已自动创建)
3. 定义 Language → T002 的外键
(因使用域 SPRAS,系统会自动提出 T002 作为检表)

文本表的自动使用

Context (上下文) Behavior (行为)
F4 帮助 自动显示当前登录语言的文本
SELECT text_table 的文本自动关联
维护视图 语言字段自动填入登录语言
💡文本表与 F4 帮助
当主表字段有检表(且该检表有文本表)时,F4 帮助自动显示:
  • 检表的键字段
  • 文本表中当前语言的文本

与主表的关系

1
2
3
4
ZDEPMENT## (主表)     1 ←──→ N     ZDEPMENTT## (文本表)

外键方向: 文本表 → 主表(文本表引用主表)
基数: 1:CN(一条主表记录可对应 0 或多条不同语言的文本记录)
⚠️文本表不是反方向
外键定义在文本表上(文本表引用主表),不是主表引用文本表。

考试/测试模式

Scenario/Keyword (场景/关键词) Answer (答案)
“文本表的键结构?” 主表键字段 + Language (SPRAS)
“Language 字段引用哪个检表?” T002(语言表)
“文本表与主表的基数?” 1:CN(一条主表 → 多条语言文本)
“F4 帮助如何使用文本表?” 自动显示当前登录语言的文本

对象依赖关系 (★★)

#abap #abap-dictionary

概览表

Concept (概念) Key Point (要点)
Runtime Object ABAP 程序使用的内部格式
Where-Used List 查找对象引用关系
Activation 修改后必须激活才能生效

依赖关系类型

Dictionary 中的对象之间存在复杂的依赖关系:

1
2
3
4
5
6
7
8
9
10
11
12
Domain
└── Data Element
├── Structure
│ └── Table
│ ├── View
│ ├── Index
│ ├── Lock Object
│ └── Search Help
└── Table Type

外键 → Check Table
搜索帮助 → Selection Method (Table/View)

运行时对象 (Runtime Object)

  • Dictionary 中的定义被编译为运行时对象
  • 存储在系统表中(如 DD02L for tables, DD03L for fields)
  • ABAP 程序和 Screen Painter 访问的是运行时对象
  • 修改后必须激活才能更新运行时对象
⚠️不一致问题
如果运行时对象与 Dictionary 定义不一致,ABAP 程序可能出错。
激活时系统自动检查并更新运行时对象。

Where-Used List (使用处清单)

Function (功能) Access (访问)
查找域的使用 SE11 → Domain → Where-Used
查找数据元素的使用 SE11 → Data Element → Where-Used
查找表的使用 SE11 → Table → Where-Used

用途:

  • 评估修改影响范围
  • 确定哪些程序/表会受变更影响
  • 计划重构或迁移

激活过程

1
2
3
4
修改对象 → 保存( inactive version )
→ 激活 → 检查依赖 → 更新 runtime object → 更新数据库(如需要)
↓ 失败
→ 激活日志 (Activation Log)
  • 可通过 Utilities → Activation Log 查看激活结果
  • 失败的激活会给出具体错误信息
  • 依赖的对象可能需要一起重新激活

外键与一致性检查 (★★★★★)

#abap #abap-dictionary #abap-validation

概览表

Concept (概念) Key Point (要点)
Foreign Key (外键) 确保引用完整性
Check Table (检表) 提供允许值的参考表
Cardinality (基数) 描述记录对应关系
Foreign Key Field Type 键字段/非键字段候选

外键定义

外键建立外键表 (Foreign Key Table) 字段与检表 (Check Table) 字段之间的关联。

1
2
3
4
5
6
7
8
9
10
11
外键表                    检表
┌──────────────┐ ┌──────────────┐
│ ZEMPLOY## │ │ SCARR │
│ │ │ │
│ CARRIER ─────┼──FK────→│ CARRID │ 外键关系
│ │ │ CARRNAME │
│ ... │ │ ... │
└──────────────┘ └──────────────┘

外键字段: CARRIER (外键表)
检表字段: CARRID (检表)

创建外键

  1. 在表维护界面选择字段
  2. 点击键图标(Foreign Key)
  3. 输入检表名 → 系统自动提出字段分配建议
  4. 确认基数和字段类型
  5. 激活

基数 (Cardinality)

基数描述检表记录与外键表记录的对应关系:

1
2
3
4
5
6
7
8
Cardinality = N : M

N (检表侧) — 始终为 1
M (外键表侧) — 可以是:
1 → 每个检表记录必须对应1条外键记录
C → 每个检表记录对应0或1条外键记录
N → 每个检表记录对应多条外键记录(必须)
CN → 每个检表记录对应0或多条外键记录(可选)
Cardinality Meaning Example
1:1 必须一一对应 员工必须有唯一部门
1:C 可选对应 员工可能有办公室
1:N 必须一对多 部门有多个员工
1:CN 可选一对多 机场可能有员工
📌基数第一个数字
基数的第一个数字始终为 1(从检表角度看,每条检表记录)

外键字段类型

Type (类型) Description (描述)
Key fields / candidates 外键字段是检表的键字段(或候选键)
Non-key fields / candidates 外键字段是检表的非键字段
Key fields of a text table 文本表专用类型
No key fields / candidates 非键非候选

字段分配原则

  • 外键表字段与检表字段按位置对应
  • 系统会自动提出建议(基于字段名/类型匹配)
  • 可以手动调整对应关系

外键对输入帮助的影响

1
2
3
4
外键定义 → 自动提供 F4 帮助:
├── 显示检表的键字段
├── 如有文本表 → 显示第一个字符型非键字段
└── 可在检表上附加搜索帮助自定义显示

特殊场景

自引用外键

表可以引用自身作为检表:

1
2
ZEMPLOY##-MANAGER → ZEMPLOY##-EMP_NUM
(经理也是员工)

复合外键

多个字段组合成一个外键:

1
ZEMPLOY##: CLIENT + CARRIER → SCARR: MANDT + CARRID

考试/测试模式

Scenario/Keyword (场景/关键词) Answer (答案)
“基数 1:CN 含义?” 一条检表记录对应 0 或多条外键记录
“基数第一个数字?” 始终为 1
“外键字段类型 key fields 含义?” 外键字段是检表的键字段
“外键自动提供什么?” F4 输入帮助(检表键+文本)

单元 4:输入检查练习(10 道题)

#practice #abap #abap-dictionary #abap-validation

相关概念

📌关键模式(点击展开)
Keyword (关键词) Answer (答案)
固定值定义位置 域的 Value Range 选项卡
固定值与 F4 帮助 自动成为 F4 候选值
基数第一个数字 始终为 1
基数 1:CN 一条检表记录对应 0 或多条外键记录
文本表键结构 主表键字段 + Language (SPRAS)
文本表语言引用 T002

问题 1 - 域固定值检查 [recall]

域的固定值(Fixed Values)定义在哪里?它如何影响使用该域的字段?

📌显示答案
固定值定义在域的 Value Range 选项卡中。影响方式:
  • 所有使用该域的数据元素都会受到约束
  • 固定值自动成为 F4 帮助的候选值
  • 修改域的固定值会影响所有引用该域的字段
  • 固定值适用于少量且稳定的值(如状态码 A/F/S)

问题 2 - 固定值 vs 检表 [recall]

什么时候应该使用域固定值,什么时候应该使用外键检表?

📌显示答案
  • 域固定值:少量、稳定的值(如状态码 A=Admin, F=Flight, S=Service)
  • 外键检表:大量、可能增长的值(如客户列表、产品列表)
  • 固定值定义在域上,检表通过外键关系定义

问题 3 - 外键定义 [recall]

什么是外键?它建立了哪两个表之间的关系?

📌显示答案
外键建立外键表 (Foreign Key Table) 的字段与检表 (Check Table) 的字段之间的关联。外键确保引用完整性——用户只能输入检表中存在的值。创建外键时,系统会自动提出字段分配建议。

问题 4 - 基数 [recall]

解释基数 (Cardinality) 的含义。1:CN 表示什么?

📌显示答案
基数描述检表记录外键表记录的对应关系,格式为 N:M。
  • N(检表侧):始终为 1
  • M(外键表侧)
    • 1 → 必须一一对应
    • C → 0 或 1 条(可选)
    • N → 多条(必须)
    • CN → 0 或多条(可选)

1:CN 表示:一条检表记录对应 0 或多条外键记录。


问题 5 - 外键字段类型 [recall]

外键字段类型有哪些?分别表示什么?

📌显示答案
类型 含义
Key fields / candidates 外键字段是检表的键字段(或候选键)
Non-key fields / candidates 外键字段是检表的非键字段
Key fields of a text table 文本表专用类型
No key fields / candidates 非键非候选

问题 6 - 文本表结构 [recall]

文本表的键结构必须满足什么条件?

📌显示答案
文本表的键结构必须包含:
  1. 主表的所有键字段
  2. Language 字段(使用域 SPRAS

Language 字段必须引用表 T002(语言表),外键类型为 “Key fields of a text table”。文本字段是第一个字符型非键字段


问题 7 - 文本表自动使用 [recall]

文本表在什么场景下会被自动使用?

📌显示答案
文本表在以下场景被自动使用:
  • F4 帮助:自动显示当前登录语言的文本
  • SELECTtext_table 的文本自动关联
  • 维护视图:语言字段自动填入登录语言
  • 当主表字段有检表(且该检表有文本表)时,F4 帮助自动显示检表键字段 + 文本表中当前语言的文本

问题 8 - 自引用外键 [application]

员工表中有一个 MANAGER 字段,需要确保经理也是该表中的员工。如何实现这种检查?

📌显示答案
使用自引用外键:将 MANAGER 字段定义为引用同一张表的外键:
1
ZEMPLOY##-MANAGER → ZEMPLOY##-EMP_NUM

表引用自身作为检表,确保经理编号必须是该表中已存在的员工编号。


问题 9 - 基数应用 [application]

一个航空公司表 (SCARR) 和一个航班表 (SFLIGHT) 之间的关系:每个航空公司可以有多个航班,但也可能有一个新成立的航空公司暂时没有航班记录。SCARR 作为 SFLIGHT 的检表时,基数应该设为什么?

📌显示答案
基数应设为 1:CN
  • 1(检表 SCARR 侧):每条航空公司记录(始终为 1)
  • CN(外键表 SFLIGHT 侧):一个航空公司可以有 0 或多条航班记录
  • C = 可选(可能没有航班),N = 多条(也可能有很多航班)
  • 这符合 “新成立的航空公司可能还没有航班” 的场景

问题 10 - 输入检查层次分析 [analysis]

一个字段同时有域固定值检查和外键检查。哪个优先?如果检表的值与域固定值冲突,会发生什么?

📌显示答案
输入检查按优先级执行:
  1. 域固定值(优先级 1)
  2. 外键检查(优先级 2)
  3. 程序内检查(优先级 3)

域固定值先于外键检查执行。如果检表的值与域固定值冲突(即检表中存在不在域固定值列表中的值),那么这些值不会被接受——域固定值检查会首先拒绝它们。因此在设计时,应避免在同一字段上同时使用域固定值和外键检查,除非两者完全一致。通常选择其中一种机制即可。


📌模式总结(点击展开)
Keyword (关键词) Answer (答案)
固定值定义位置 域的 Value Range 选项卡
固定值自动效果 成为 F4 帮助候选值
固定值 vs 检表 少量稳定用固定值,大量可变用检表
外键作用 确保引用完整性
基数第一个数字 始终为 1
1:CN 含义 一条检表记录对应 0 或多条外键记录
文本表键结构 主表键 + Language (SPRAS)
语言引用检表 T002
自引用外键 表引用自身作为检表
输入检查优先级 域固定值 > 外键检查 > 程序检查

Append 结构与表增强 (★★★★)

#abap #abap-dictionary #abap-tables

概览表

Enhancement Type (增强类型) Description (描述) Need Reservation (需预留)
Customizing Include SAP 预留的增强位置
Append Structure 追加到表末尾

Append 结构

Append 结构允许在不修改 SAP 标准表的情况下追加字段。

1
2
3
4
5
6
7
8
9
10
11
12
SAP Standard Table: ZEMPLOY##
┌────────────┬──────────┐
│ CLIENT │ S_CLIENT │
│ CARRIER │ S_CARR │
│ EMP_NUM │ own │
│ FIRST_NAME │ S_FNAME │
│ LAST_NAME │ S_LNAME │
├────────────┴──────────┤ ← Append Structure ZZA_EMPLOY
│ ZZAIRPORT │ S_AIRPORT │
│ ZZOFFNR │ S_BUREAUNO│
│ ZZTELNO │ S_TELNO │
└───────────────────────┘

Append 结构特性

Property (特性) Detail (详情)
一对一关系 一个 Append 结构只能分配给一个表
多个 Append 一个表可以有多个 Append 结构
自动激活 Append 结构创建/修改时,父表自动激活
类型可用 Append 结构本身也是一个可用的类型
升级安全 客户命名空间,升级时不会被覆盖

字段命名规则

1
2
客户开发: 字段名以 YY 或 ZZ 开头
合作伙伴: 使用自己的保留命名空间
⚠️命名冲突
不遵循命名规范的字段可能在 SAP 升级时与新字段冲突。

Append 结构的限制

Restriction (限制) Detail (详情)
池表/簇表 不能使用 Append 结构
LCHR/LRAW 字段 含长字段的表不能使用(长字段必须在最后)
转换需求 不需要(ALTER TABLE 添加字段)

附加功能 (4.6C 起)

  • 可为表中已有字段定义外键
  • 可为已有字段附加搜索帮助

Customizing Include

SAP 在标准表/结构中预留位置供客户增强:

1
2
3
4
5
SAP Standard Structure:
├── SAP fields...
├── CI_ZEMPLOY (Customizing Include) ← 预留位置,客户创建后生效
│ ├── (empty until customer creates it)
├── More SAP fields...
  • 使用 Extras → Enhancement Category 管理
  • 客户需要创建 Include 结构来填充这些位置

增强类别 (Enhancement Category)

为了控制结构增强对程序的影响,设置了增强类别:

Level Category (类别) Meaning (含义)
1 Not classified 无类别
2 Not enhanceable 不可增强
3 Enhanceable and character-like 所有组件必须为字符型
4 Enhanceable and character-like or numerical 不能含深层类型
5 Freely enhanceable 任意类型
📌Unicode 环境影响
结构增强在 Unicode 环境下更严格:
  • 改变碎片视图 (Fragment View)
  • 影响赋值检查和比较
  • 数值型/深层组件插入纯字符结构会改变其特性

类别继承规则

  • Include/子结构的增强类别不能大于父结构
  • 例如:父结构含 Level 4 的 Include → 父结构不能是 Level 2 或 3

复制表的注意事项

💡复制时 Append 字段
如果复制一个有 Append 结构的透明表,Append 字段会变成普通字段

创建步骤

1
2
3
4
5
1. SE11 → 显示目标表
2. Goto → Append Structure
3. 输入名称(遵循命名规范)
4. 添加字段(ZZ 前缀 + 数据元素)
5. 激活 → 父表自动调整

考试/测试模式

Scenario/Keyword (场景/关键词) Answer (答案)
“Append 字段命名规范?” YY 或 ZZ 开头
“Append 需要表转换吗?” 不需要(ALTER TABLE)
“哪些表不能用 Append?” 池表、簇表、含 LCHR/LRAW 的表
“Append 结构能用于多个表吗?” 不能,一对一关系
“复制有 Append 的表会怎样?” Append 字段变为普通字段

表转换过程 (★★★★★)

#abap #abap-dictionary #abap-tables

概览表

Change Type (变更类型) Adjustment (调整方式) Data Impact (数据影响)
字段顺序变化(非键) 无需调整
添加字段 ALTER TABLE
缩短字段/键 转换 (Conversion) 可能丢失
更改数据类型 转换 (Conversion) 可能失败

数据库结构调整方式

Method (方式) Data Loss Duration
DROP + CREATE 丢失所有数据
ALTER TABLE
Conversion (转换) 可能丢失
💡自动选择
如果表无数据 → DROP + CREATE
如果有数据 → 先尝试 ALTER TABLE,不行则转换

转换过程 (Conversion Process) — 7 个步骤

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
Step 1: LOCK TABLE (锁定表)
→ 禁止进一步结构变更
→ 停用所有依赖视图

Step 2: RENAME (重命名)
→ TAB → QCMTAB (临时表)
→ 删除所有索引

Step 3: CREATE NEW (创建新表)
→ 用新结构创建 QCM8TAB
→ 创建主索引
→ 此时 QCM8TAB 为空!

Step 4: COPY DATA (回填数据)
→ MOVE-CORRESPONDING: QCMTAB → QCM8TAB
→ 每 16MB 提交一次(释放并重获锁)
→ 缩短字段时多余内容被截断

Step 5: DROP OLD (删除临时表)
→ 删除 QCMTAB

Step 6: RENAME BACK + REBUILD (重命名+重建)
→ QCM8TAB → TAB
→ 重建二级索引
→ 重新激活依赖视图

Step 7: UNLOCK (释放锁)
转换期间表不可用
Step 2-6 期间,表不存在于数据库的原名下。
所有访问该表的程序无法运行
转换必须在非生产时间执行!

转换问题与风险

表空间溢出

1
数据同时存在于 QCMTAB + QCM8TAB → 存储需求翻倍
  • 如果表空间不足,转换终止
  • 解决:扩展表空间,然后在数据库工具中继续

键字段缩短

1
2
缩短前: KEY = 'ABC123' 和 'ABC123' (两条)
缩短后: KEY = 'ABC' (无法区分)
  • 只能加载回一条记录(随机选择)
  • 必须在转换前清理数据

类型不兼容

  • MOVE-CORRESPONDING 不支持的类型变更会导致终止
  • 需手动恢复原状态

处理终止的转换

使用事务 SE14(数据库工具):

Option (选项) When to Use (使用场景)
Continue adjustment 修正错误后继续转换
Unlock table 绝不在 Step 3/4 时使用(数据丢失)
1
2
3
SE14 → Enter Table Name → Edit → Analyze
→ 查看对象日志(Object Log)
→ Continue adjustment 或 Unlock table
⚠️绝对禁止
如果数据只在临时表中(Step 3/4 失败),绝不能选 Unlock table
否则原表为空,数据丢失。必须选 Continue adjustment。

ALTER TABLE 场景

不需要转换的修改(仅 ALTER TABLE):

  • 添加新字段
  • 修改字段顺序(非键字段)
  • Append 结构添加字段

考试/测试模式

Scenario/Keyword (场景/关键词) Answer (答案)
“转换期间原表是否存在?” 不存在(被重命名为 QCMTAB)
“转换失败在 Step 3/4,怎么办?” Continue adjustment(不能 Unlock)
“缩短键字段会怎样?” 无法区分的记录只保留一条
“添加字段需要转换吗?” 不需要(ALTER TABLE)
“数据回填用什么语句?” MOVE-CORRESPONDING
“每多少 MB 提交一次?” 16 MB

单元 5:对象依赖练习(6 道题)

#practice #abap #abap-dictionary #abap-dependency

相关概念

📌关键模式(点击展开)
Keyword (关键词) Answer (答案)
运行时对象存储 系统表(如 DD02L, DD03L)
不一致后果 ABAP 程序可能出错
Where-Used List 用途 评估修改影响范围
保存后状态 非活跃版本 (inactive)

问题 1 - 运行时对象 [recall]

什么是运行时对象 (Runtime Object)?它存储在哪里?

📌显示答案
运行时对象是 Dictionary 中定义被编译后的内部格式,ABAP 程序和 Screen Painter 访问的是运行时对象(而非 Dictionary 定义本身)。
  • 存储在系统表中(如 DD02L for tables, DD03L for fields)
  • 修改 Dictionary 对象后必须激活才能更新运行时对象
  • 如果运行时对象与 Dictionary 定义不一致,ABAP 程序可能出错

问题 2 - Where-Used List [recall]

Where-Used List(使用处清单)的功能是什么?给出两个使用场景。

📌显示答案
Where-Used List 用于查找对象的引用关系,确定哪些程序/表/结构会受变更影响。
使用场景:
  1. 评估修改影响范围:修改一个域前,查看哪些数据元素和表使用了该域
  2. 计划重构或迁移:确定需要同步更新的依赖对象
  • 访问方式:SE11 → 选择对象类型 → Where-Used

问题 3 - 激活过程 [recall]

描述 Dictionary 对象从修改到生效的激活过程。

📌显示答案
1
2
3
4
修改对象 → 保存(非活跃版本 / inactive version)
→ 激活 → 检查依赖 → 更新运行时对象 → 更新数据库(如需要)
↓ 失败
→ 激活日志 (Activation Log)
  • 保存时创建的是非活跃版本,不影响现有程序
  • 激活时系统自动检查依赖并更新运行时对象
  • 失败的激活可通过 Utilities → Activation Log 查看错误信息
  • 依赖的对象可能需要一起重新激活

问题 4 - 依赖关系 [recall]

列出 Dictionary 对象之间的主要依赖关系层次。

📌显示答案
1
2
3
4
5
6
7
8
9
10
11
12
Domain
└── Data Element
├── Structure
│ └── Table
│ ├── View
│ ├── Index
│ ├── Lock Object
│ └── Search Help
└── Table Type

外键 → Check Table
搜索帮助 → Selection Method (Table/View)

修改底层对象(如 Domain)可能级联影响所有上层对象。


问题 5 - 不一致问题 [application]

一个开发者修改了某个结构体(添加了新字段)但忘记激活。另一个开发者在该结构体基础上编写了使用新字段的程序。程序运行时会出现什么问题?如何解决?

📌显示答案
问题:程序运行时会出错,因为运行时对象仍然是旧版本(不包含新字段)。未激活的修改只存在于 Dictionary 的非活跃版本中,ABAP 程序访问的是运行时对象。

解决:激活修改后的结构体定义。激活后系统会:

  1. 检查所有依赖对象
  2. 更新运行时对象(DD02L, DD03L 等系统表)
  3. 新字段才会对程序可见

问题 6 - 依赖修改影响分析 [analysis]

你需要将一个域的数据类型从 CHAR(3) 改为 CHAR(5)。分析这个修改会影响哪些对象?修改前应该做什么准备?

📌显示答案
影响范围(需要用 Where-Used List 确认):
  1. 所有引用该域的数据元素
  2. 使用这些数据元素的所有结构表字段
  3. 使用这些表的所有视图(可能需要调整投影)
  4. 使用这些表的所有索引(键长度变化影响索引)
  5. 使用这些表/结构的所有ABAP 程序(变量长度可能不匹配)
  6. 所有锁对象搜索帮助

修改前准备

  • 使用 Where-Used List 完整列出所有依赖
  • 评估哪些对象需要同步修改
  • 检查是否需要表转换(更改字段长度可能触发转换)
  • 在非生产环境中测试激活
  • 计划在低负载时段执行

📌模式总结(点击展开)
Keyword (关键词) Answer (答案)
运行时对象 Dictionary 定义的编译格式,存储在系统表中
系统表示例 DD02L (tables), DD03L (fields)
保存后状态 非活跃版本 (inactive)
激活作用 更新运行时对象 + 数据库
Where-Used List 查找引用关系,评估修改影响
不一致后果 ABAP 程序可能出错
0%