Mark的技术博客

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

吴让宇(Mark)

吴让宇(Mark)

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

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

SAP Fiori ABAP CDS OData Dify Docker AI LLM

最新文章

单元 1:字典概述练习(8 道题)

#practice #abap #abap-dictionary #abap-dictionary-overview

相关概念

📌关键模式(点击展开)
Keyword (关键词) Answer (答案)
字典事务码 SE11
类型定义三大类 Data Element, Structure, Table Type
域能否在程序中直接使用 不能,必须通过数据元素
激活后的效果 自动反映到数据库

问题 1 - 字典核心功能 [recall]

ABAP 字典的三大核心功能区域是什么?每个区域举两个例子。

📌显示答案
  1. 类型定义 (Type Definitions): Data Element(数据元素)、Structure(结构)、Table Type(表类型)
  2. 数据库对象 (Database Objects): Table(表)、View(视图)、Index(索引)
  3. 服务 (Services): Search Help(F4 帮助)、Lock Object(锁)、Buffering(缓冲)、Logging(日志)

问题 2 - 类型层次关系 [recall]

画出域、数据元素、结构和表类型之间的层次依赖关系,并解释每一层的作用。

📌显示答案
1
2
3
4
5
6
Domain (域) — 技术属性(类型、长度、值域)
└── Data Element (数据元素) — 语义属性(标签、文档)
├── Structure (结构) — 组件集合
│ ├── 嵌套结构
│ └── 深层结构(含内表)
└── Table Type (表类型) — 内表描述

定义技术属性,不能在程序中直接引用;数据元素连接域和使用场景,包含语义信息;结构是组件的集合;表类型描述内表的行结构和访问方式。


问题 3 - 字典服务功能 [recall]

ABAP 字典提供了哪些服务(Services)?列出至少四个。

📌显示答案
  1. Search Helps (F4 输入帮助) — 候选值列表
  2. Field Documentation (F1 字段帮助) — 字段说明文档
  3. Foreign Keys (输入一致性检查) — 引用完整性验证
  4. Lock Objects (锁管理) — 并发访问控制
  5. Buffering (缓冲) — 性能优化
  6. Logging (变更日志记录) — 数据变更追踪

问题 4 - 激活与自动反映 [recall]

在 ABAP 字典中激活一个表定义时,系统会做什么?修改表定义后又会怎样?

📌显示答案
激活透明表定义时,系统会自动在底层数据库中创建对应的数据库表。修改表定义后,数据库结构也会自动调整。字典中定义的对象在激活时自动反映到数据库层。

问题 5 - 与开发环境集成 [recall]

ABAP 字典与哪些开发/运行环境组件集成?列出至少三个集成点。

📌显示答案
集成点 说明
ABAP 解释器 程序生成时访问类型定义
Screen Painter “Get from Dictionary” 功能直接使用字段定义
数据库接口 使用存储的表/视图信息访问数据库
即时生效 字典中的每次变更立即影响所有相关程序和屏幕

问题 6 - 字典事务码 [application]

你需要创建一个新的透明表。应该使用哪个事务码?在创建后,用户如何验证表已经在数据库中创建?

📌显示答案
使用事务 SE11 创建透明表。创建并激活后,可以通过 SE11 中的 Utilities → Database Object → Display 来查看数据库中是否已成功创建对应的数据库表。也可以通过事务 SE16 测试数据访问。

问题 7 - 服务选择决策 [analysis]

一家公司需要为新开发的客户表同时实现:(1) 输入时验证航空公司代码;(2) 多用户同时编辑时的数据保护;(3) 每月统计表的修改记录。应该分别使用字典的哪些服务?

📌显示答案
  1. 输入验证 → 使用 Foreign Keys(外键),将航空公司代码字段定义为引用 SCARR 表的外键
  2. 并发保护 → 使用 Lock Objects(锁对象),创建基于该表的锁对象
  3. 变更记录 → 使用 Logging(日志),在表的技术设置中启用日志记录,同时确保 Profile 参数 rec/client 已配置

问题 8 - 即时生效的影响 [application]

一个开发者在字典中修改了某个数据元素的字段标签(从 “Name” 改为 “Full Name”)并激活。这对现有程序和屏幕有什么影响?

📌显示答案
字典中的每次变更立即影响所有相关程序和屏幕。激活后,所有使用该数据元素的屏幕字段标签都会自动更新为 “Full Name”。Screen Painter 中 “Get from Dictionary” 功能获取的字段定义也会反映新标签。这体现了字典作为集中类型管理的核心优势——一处修改,全局生效。

📌模式总结(点击展开)
Keyword (关键词) Answer (答案)
字典事务码 SE11
三大功能区域 类型定义、数据库对象、服务
域的作用 技术属性(不能直接引用)
数据元素的作用 语义属性,连接域和使用场景
激活效果 自动反映到数据库
即时生效 变更立即影响所有相关程序和屏幕
输入验证服务 Foreign Keys
并发保护服务 Lock Objects
变更追踪服务 Logging

单元 2:透明表练习(8 道题)

#practice #abap #abap-dictionary #abap-tables

相关概念

📌关键模式(点击展开)
Keyword (关键词) Answer (答案)
透明表激活后 自动在数据库中创建同名表
两级域概念 域(技术) → 数据元素(语义) → 字段
Include 链中的数据库表 只能有一个(表本身)
CURR/QUAN 引用 运行时关联引用字段
日志生效条件 技术设置勾选 + rec/client 配置

问题 1 - 透明表与数据库对应 [recall]

透明表在激活后与数据库之间的对应关系是什么?

📌显示答案
透明表激活时自动在数据库中创建对应的数据库表:
  • 同名:Dictionary 中的表名 = 数据库中的表名
  • 同字段名:字段名一一对应
  • 类型转换:Dictionary 数据类型自动转换为对应 DB 数据类型
  • 字段顺序可以不同(允许插入新字段而不转换表)

问题 2 - 两级域概念 [recall]

解释两级域概念 (Two-Level Domain Concept),并举一个例子说明同一个域如何为不同字段提供不同语义。

📌显示答案
两级域概念将字段的属性分为技术语义两层:
  • 域 (Domain):定义技术属性(数据类型、长度、值域)
  • 数据元素 (Data Element):定义语义属性(字段标签、含义)

示例:域 S_AIRPID 定义机场 ID 的技术属性,通过数据元素 S_FROMAIRP(出发机场)和 S_TOAIRP(到达机场)分别赋予不同语义。同一个域被不同数据元素复用,不同数据元素赋予不同的语义含义。


问题 3 - Include 结构规则 [recall]

在透明表中使用 Include 结构时,有哪些规则和限制?

📌显示答案
规则 详情
用途 避免冗余结构定义
Include 链中的数据库表 只能有一个(表本身)
嵌套 Include Include 中可以包含 Include
外键传递 Include 中的外键定义会传递到父表
整表 Include 必须包含整个表
插入方式 菜单 Edit → Include → Insert 或手动输入 .INCLUDE

问题 4 - 货币/数量字段引用 [recall]

CURR 和 QUAN 类型的字段在定义时有什么特殊要求?

📌显示答案
  • CURR(货币)字段:必须指定引用表中的 CUKY 字段
  • QUAN(数量)字段:必须指定引用表中的 UNIT 字段
  • 引用字段在运行时才关联,不是定义时
  • 系统使用引用字段来确定小数位数(如 JPY 无小数,USD 两位小数)

问题 5 - 技术设置要素 [recall]

透明表的技术设置包含哪些主要配置项?

📌显示答案
设置 目的
Data Class(数据类) 决定物理存储区域(APPL0 主数据/APPL1 事务数据/APPL2 组织数据)
Size Category(大小类别) 决定扩展(Extent)大小(0-4 级)
Buffering(缓冲) 读性能优化
Logging(日志) 变更记录

问题 6 - 日志生效条件 [application]

一个开发者在透明表的技术设置中勾选了 Logging,但发现日志并未记录。可能的原因是什么?如何解决?

📌显示答案
日志生效需要两个条件缺一不可
  1. 技术设置中勾选 Logging
  2. Profile 参数 rec/client 必须正确设置:
    • rec/client = ALL → 记录所有客户端
    • rec/client = 000[...] → 记录指定客户端
    • rec/client = OFF不记录

最可能的原因是 rec/client 设置为 OFF 或未包含当前客户端。需要系统管理员修改 Profile 参数。查看日志使用事务 SCU3


问题 7 - 池表与簇表对比 [application]

你需要判断一个 SAP 标准表是透明表、池表还是簇表。如果该表不能用于 JOIN、不能用 Append 结构、且与同组的其他表共享相同的簇键,这是什么类型的表?有什么特点?

📌显示答案
这是簇表 (Cluster Table)。特点:
  • 与其他簇表共享簇键(功能相关)
  • 数据压缩存储在表簇 (Table Cluster) 中
  • 不能用于 JOIN / View / Append 结构
  • 仅支持 Open SQL
  • WHERE 条件仅簇键字段传递到数据库
  • 优点:功能相关数据联合读取,减少数据库访问;压缩存储节省空间

问题 8 - 池表与簇表区别分析 [analysis]

比较池表 (Pooled Table) 和簇表 (Cluster Table) 的本质区别。在什么情况下 SAP 会选择使用簇表而不是池表?

📌显示答案
对比项 池表 簇表
表间关系 无功能依赖 有功能依赖(共享簇键)
合并基础 只是合并小表 功能相关的数据合并
键字段 必须是 C 类型 共享簇键的交集
数据压缩 仅非键字段 全部数据

SAP 选择簇表的场景:多个表之间有功能依赖关系(如主数据+明细数据),经常需要联合读取,且共享相同的键字段。池表仅用于将多个不相关的小逻辑表合并存储到一个物理表中。


📌模式总结(点击展开)
Keyword (关键词) Answer (答案)
透明表激活 自动创建同名数据库表
两级域概念 域(技术) → 数据元素(语义)
Include 链中数据库表 只能有一个
CURR/QUAN 引用 运行时关联
日志两条件 技术设置 + rec/client
池表特点 无功能依赖,键字段须 C 类型
簇表特点 有功能依赖,共享簇键
池表/簇表限制 不能 JOIN、Append,仅 Open SQL

单元 2:数据对象练习(10 道题)

#practice #abap #abap-dictionary #abap-data-types

相关概念

📌关键模式(点击展开)
Keyword (关键词) Answer (答案)
域能否直接引用 不能,必须通过数据元素
CHAR 在表中的上限 255
数据元素字段标签类型 Short, Medium, Long, Heading
深层结构定义条件 包含至少一个内表组件
SET/GET 参数何时失效 用户注销后

问题 1 - 域与技术属性 [recall]

域(Domain)包含哪些技术属性?列举四项。

📌显示答案
  1. Format — 数据类型 + 字符数 + 小数位
  2. Output Properties — 输出长度、+/- 符号、小写允许
  3. Value Range — 固定值或区间(用于输入检查)
  4. Conversion Routine — 显示格式与 SAP 内部格式之间的转换

问题 2 - 转换例程 [recall]

什么是转换例程(Conversion Routine)?它的工作方式是什么?

📌显示答案
转换例程用于在显示格式SAP 内部格式之间自动转换。
  • CONVERSION_EXIT_XXXXX_OUTPUT:SAP 内部格式 → 显示格式
  • CONVERSION_EXIT_XXXXX_INPUT:显示格式 → SAP 内部格式
  • 典型应用:前导零补齐(1230000000123
  • 也影响 WRITE 语句的输出

问题 3 - 数据元素语义属性 [recall]

数据元素包含哪些语义属性?

📌显示答案
数据元素包含的语义属性:
  • 字段标签 (Field Labels):Short、Medium、Long、Heading 四种长度
  • F1 帮助文档
  • 搜索帮助(可附加 F4 搜索帮助)
  • SET/GET Parameter(跨屏幕自动传递值)
  • Default Component Name(BAPI 结构中使用)

问题 4 - SET/GET 参数 [recall]

SET/GET Parameter 的作用是什么?它的生命周期是怎样的?

📌显示答案
SET/GET Parameter 用于跨屏幕自动传递值。用户在 SAP GUI 会话中输入的值通过 SET/GET 参数自动填充到使用同一参数 ID 的其他屏幕字段中。生命周期为当前登录会话——用户注销后清除

问题 5 - 结构类型对比 [recall]

比较扁平结构(Flat)、嵌套结构(Nested)和深层结构(Deep)的定义和区别。

📌显示答案
类型 定义 访问方式
扁平结构 组件全部是数据元素 wa-field
嵌套结构 包含子结构作为组件 wa-sub-field(层级访问)
深层结构 包含至少一个内表组件 LOOP AT wa-table...

数据库表只能包含扁平结构,不能有深层结构中的内表组件。


问题 6 - Include 与嵌套的区别 [recall]

在结构中,Include 结构和嵌套结构有什么区别?

📌显示答案
  • Include 结构.INCLUDE):子结构的字段直接展开到父结构中,扁平访问(wa-street),无嵌套层级
  • 嵌套结构:子结构作为独立组件,层级访问wa-name-firstname
  • Include 实际上把子结构的字段拷贝到父结构中,不增加嵌套层级
  • Include 中的外键定义会传递到父表

问题 7 - 表类型定义要素 [recall]

在 ABAP 字典中定义表类型(Table Type)时需要指定哪些要素?

📌显示答案
定义表类型需要指定四项要素:
  1. Line Type(行类型):数据元素、结构、DB 表、视图、其他表类型
  2. Access Type(访问方式):Standard / Sorted / Hashed
  3. Key Type(键类型):Unique / Non-unique
  4. Key Definition(键定义):Standard Key / Key Components

问题 8 - 数据类型长度限制 [application]

你需要在表中定义一个长度为 500 的文本字段。应该使用哪个内置数据类型?CHAR 类型合适吗?

📌显示答案
CHAR 不合适,因为 CHAR 在表中最大长度为 255。应该使用 LCHR(长字符串类型),但需要注意:LCHR 字段必须是表的最后一个字段,且含 LCHR/LRAW 字段的表不能使用 Append 结构

问题 9 - 类型组 [recall]

什么是类型组(Type Group)?现代开发中应该使用什么替代?

📌显示答案
类型组是 Release 4.5a 之前的旧技术,用于定义全局常量。名称最多 5 个字符,所有名称必须以 typegroup_ 为前缀,使用 TYPE-POOLS 语句引入。
现代替代:新开发应使用 Dictionary 结构代替类型组。全局常量可用类的常量属性

问题 10 - 结构选择分析 [analysis]

你需要定义一个包含员工基本信息(姓名、地址)和多个电话号码的类型。你会选择哪种结构类型?为什么?数据库表中能直接使用这种结构吗?

📌显示答案
应选择深层结构 (Deep Structure)
  • 姓名和地址用数据元素或子结构定义
  • 多个电话号码使用表类型组件(内表)来存储
  • 访问方式:LOOP AT wa_employee-phone INTO wa_phone.

数据库表不能直接使用深层结构(因为不能包含内表组件)。需要在数据库表中存储扁平的员工数据,电话号码存储在单独的子表中,通过外键关联。


📌模式总结(点击展开)
Keyword (关键词) Answer (答案)
域包含的属性 Format、Output Properties、Value Range、Conversion Routine
转换例程 CONVERSION_EXIT_XXXXX_INPUT/OUTPUT
数据元素标签 Short, Medium, Long, Heading
SET/GET 参数 跨屏幕传值,注销后清除
深层结构 至少一个内表组件
Include vs 嵌套 Include 扁平展开,嵌套层级访问
CHAR 上限 表中 255
LCHR 限制 必须是最后字段,不能用 Append
类型组 旧技术,用 Dictionary 结构替代
表类型四要素 行类型、访问方式、键类型、键定义

代码检查器 (★★)

#debugging #analysis-tools #best-practices

用途

方面 详情
事务 SCI
目标 检查程序的性能、安全性、语义错误
范围 静态分析(无需执行)

架构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
+------------------+     +-----------------+     +--------------+
| 检查变体 | | 对象集 | | 检查任务 |
| (检查什么) | | (检查哪些对象) | | (命名运行) |
+--------+---------+ +--------+--------+ +------+-------+
| | |
+-----------+------------+ |
| |
+------v------+) |
| SCI 引擎 |<--------------------------+
+------+-------+
|
+------v------+
| 结果 |
+-------------+
组件 用途 创建位置
检查变体 定义执行哪些检查 SCI
对象集 定义检查哪些对象 SCI
检查任务 变体 + 对象集的命名组合 SCI

检查类别

类别 检查内容
通用 通用编程问题
性能 低效代码模式
安全 安全漏洞
语法 语法错误和警告
编程规范 命名规范、格式
搜索 查找特定代码模式

按类别的示例检查

类别 示例检查
性能 SELECT * 使用、嵌套 SELECT
性能 循环中的类型转换
安全 缺少授权检查
安全 硬编码密码或值
语法 不可达代码
规范 命名前缀违规

使用代码检查器

从 ABAP 编辑器(快速检查)

1
ABAP 编辑器 → 程序 → 检查 → 代码检查器 (Ctrl+F2)
💡ABAP 编辑器的快速检查使用默认变体。自定义检查请在 SCI 中创建自己的变体。

###从事务 SCI(完整)

  1. 创建检查变体:定义要包含的检查
  2. 创建对象集:指定程序、类、包
  3. 创建检查任务:组合变体 + 对象集
  4. 运行检查任务:执行并查看结果

检查变体创建

1
2
3
4
5
6
7
8
9
SCI → 检查变体 → 创建
+-- 性能
| [x] SELECT * 使用
| [x] 嵌套 SELECT
| [x] 类型转换
+-- 安全
| [x] 授权检查
+-- 规范
[x] 命名前缀

结果

结果类型 图标 含义
错误 红色 必须修复
警告 黄色 应该修复
信息 蓝色 需要注意
📌首先关注错误,然后处理警告。信息项仅供参考。

标准检查 vs 自定义检查任务

特性 标准(编辑器) 自定义(SCI)
触发方式 ABAP 编辑器 (Ctrl+F2) 事务 SCI
检查变体 默认系统变体 用户定义
对象范围 仅当前程序 任意对象集
持久性 不保存 保存且可复用
调度 仅手动 可调度

考试/测试模式

关键词 / 短语 答案
“代码检查器事务” SCI
“三个 SCI 组件” 检查变体、对象集、检查任务
“检查类别” 通用、性能、安全、语法、规范、搜索
“从编辑器快速检查” 程序 → 检查 → 代码检查器 (Ctrl+F2)
“检查变体用途” 定义执行哪些检查
“对象集用途” 定义检查哪些对象
“检查任务组合了” 检查变体 + 对象集

相关笔记

技术设置与日志 (★★★)

#abap #abap-dictionary #abap-tables #abap-performance

概览表

Setting (设置) Purpose (目的)
Data Class (数据类) 物理存储区域选择
Size Category (大小类别) 扩展(Extent)大小
Buffering (缓冲) 读性能优化
Logging (日志) 变更记录

Data Class(数据类)

数据类决定表存储在数据库的哪个物理区域(Oracle 中为 Tablespace)。

Data Class Description Example (示例)
APPL0 主数据(很少修改) 地址文件
APPL1 事务数据(频繁修改) 库存数据
APPL2 组织数据(Customizing) 国家代码
APPL3 系统数据 程序源码
USER/USER1 客户自定义类 客户开发
💡正确选择数据类
正确选择数据类可确保表存储在正确的物理区域,避免碎片化问题。

Size Category(大小类别)

Category Description
0 ~0 到 4,300 条记录
1 ~4,300 到 34,000 条记录
2 ~34,000 到 150,000 条记录
3 ~150,000 到 700,000 条记录
4 ~700,000 条以上
  • 初始扩展(Initial Extent)大小对所有类别相同
  • 额外扩展的大小由类别决定
  • 正确选择可避免:过多小扩展 或 浪费空间的大扩展

Logging(日志)

记录表条目的修改(插入/更新/删除)。

两个条件缺一不可:

1
2
3
4
5
6
日志生效条件:
1. 技术设置中勾选 Logging ✓
2. Profile 参数 rec/client 设置:
- rec/client = ALL → 记录所有客户端
- rec/client = 000[...] → 记录指定客户端
- rec/client = OFF → 不记录
⚠️日志性能影响
日志会造成系统瓶颈:
  • 每次修改产生额外的写操作
  • 可能导致锁竞争(即使访问不同的应用表)
  • 查看日志:事务 SCU3

数据库碎片化

1
频繁插入/删除 → 数据碎片化 → 性能下降
解决方案 适用场景
删除并重建索引 索引碎片化(表仍可用)
转换表 (Conversion) 表碎片化(表不可用!)
📌转换注意事项
  • 转换期间表不可读写
  • 大表转换可能持续数分钟到数小时
  • 应在低负载时段执行

ABAP 字典功能概述 (★★★)

#abap #abap-dictionary

概览表

Function Area (功能区域) Key Point (要点)
类型定义 数据元素、结构、表类型
数据库对象 表、视图、索引
服务 F4 帮助、F1 帮助、锁、日志、缓冲

核心功能

ABAP 字典(Transaction SE11)是 SAP 系统中集中管理所有类型定义的工具:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
ABAP Dictionary
├── 类型定义 (Type Definitions)
│ ├── Data Elements (数据元素) — 描述基本类型
│ ├── Structures (结构) — 组件集合
│ └── Table Types (表类型) — 内表结构描述
├── 数据库对象 (Database Objects)
│ ├── Tables (表) — 自动创建到数据库
│ ├── Views (视图) — 多表联合
│ └── Indexes (索引) — 加速数据访问
└── 服务 (Services)
├── Search Helps (F4 输入帮助)
├── Field Documentation (F1 字段帮助)
├── Foreign Keys (输入一致性检查)
├── Lock Objects (锁管理)
├── Buffering (缓冲提升性能)
└── Logging (变更日志记录)
💡核心概念
ABAP 字典中定义的对象在激活时自动反映到数据库。修改表定义后,数据库结构也会自动调整。

与开发/运行环境的关系

Integration Point (集成点) 说明
ABAP 解释器 程序生成时访问类型定义
Screen Painter “Get from Dictionary” 功能直接使用字段定义
数据库接口 使用存储的表/视图信息访问数据库
即时生效 字典中的每次变更立即影响所有相关程序和屏幕

类型层次关系

1
2
3
4
5
6
Domain (域)
└── Data Element (数据元素)
├── Structure (结构)
│ ├── 嵌套结构
│ └── 深层结构 (含内表)
└── Table Type (表类型/内表)
  • : 定义技术属性(数据类型、长度),不能在程序中直接引用
  • 数据元素: 连接域和使用场景,包含语义信息(字段标签、F1 帮助)
  • 结构: 组件组成,可以是数据元素、内表或子结构
  • 表类型: 描述内表的行结构和访问方式

域与数据元素 (★★★★)

#abap #abap-dictionary #abap-data-types

概览表

Object (对象) Role (角色) Contains (包含)
Domain (域) 技术属性 数据类型、长度、小数位、值域、转换例程
Data Element (数据元素) 语义属性 字段标签、F1 文档、搜索帮助、SET/GET 参数

Domain(域)

域用于集中管理数据对象的技术属性。域不能在程序/表中直接使用,必须通过数据元素。

技术属性

Attribute (属性) Description (描述)
Format 数据类型 + 字符数 + 小数位
Output Properties 输出长度、+/- 符号、小写允许
Value Range 固定值或区间(用于输入检查)
Conversion Routine 显示格式 ↔ SAP 内部格式转换

常用内置数据类型

Type Description 限制
CHAR 字符串 表中 ≤255,结构中无限制
DATS 日期 固定 8 字符
DEC 金额/计算字段 ≤31 字符
NUMC 数字字符串 ≤255 字符
CURR 货币 需引用表中的 CUKY 字段
QUAN 数量 需引用表中的 UNIT 字段
LCHR 长字符串 必须是表的最后一个字段
⚠️LCHR 限制
含 LCHR/LRAW 字段的表不能使用 Append 结构,因为长字段必须在字段列表的最后位置。

转换例程 (Conversion Routine)

1
2
显示格式 ──CONVERSION_EXIT_XXXXX_OUTPUT──→ SAP 内部格式
SAP 内部格式 ──CONVERSION_EXIT_XXXXX_INPUT──→ 显示格式
  • 例:前导零补齐(1230000000123
  • 也影响 WRITE 语句的输出

Data Element(数据元素)

数据元素是域与数据对象之间的桥梁,包含语义信息。

字段标签 (Field Labels)

Label Type (标签类型) Length (长度) Usage (用途)
Short 最短 紧凑布局
Medium 中等 一般使用
Long 最长 PARAMETERS 的选择屏幕
Heading 列标题 ALV 列标题
💡多语言
字段标签可通过 Goto → Translation 或事务 SE63 翻译。其他语言可能需要更多字符。

数据元素的附加属性

Property (属性) Description (描述)
Search Help 可附加 F4 搜索帮助
SET/GET Parameter 跨屏幕自动传递值(按会话保持,注销后清除)
Default Component Name BAPI 结构中使用(英文统一命名)
Reference Type 可定义为引用类型(REF TO data / ANY / OBJECT)

技术类型来源

数据元素的技术属性有两种来源:

  1. 引用域(推荐)— 使用预定义的域
  2. 内置类型 — 直接指定数据类型和长度(不经过域)
1
2
推荐: Domain → Data Element → 使用
备用: Built-in Type → Data Element → 使用

Type Group(类型组)

  • 旧技术(Release 4.5a 之前),用于定义全局常量
  • 名称最多 5 个字符
  • 所有名称必须以 typegroup_ 为前缀
  • 使用: TYPE-POOLS zmytp.
📌现代替代
新开发应使用 Dictionary 结构代替类型组。全局常量可用类的常量属性。

考试/测试模式

Scenario/Keyword (场景/关键词) Answer (答案)
“程序能直接引用域吗?” 不能,必须通过数据元素
“CHAR 在表中的最大长度?” 255(超过用 LCHR)
“SET/GET 参数何时失效?” 用户注销后(仅按会话保持)
“类型组名称长度限制?” 最多 5 字符

结构与表类型 (★★★★)

#abap #abap-dictionary #abap-data-types

概览表

Type (类型) Dimension (维度) Description (描述)
Flat Structure (扁平结构) 一维 组件均为数据元素
Nested Structure (嵌套结构) 一维 包含子结构作为组件
Deep Structure (深层结构) 混合 至少包含一个内表组件
Table Type (表类型) 二维 描述内表结构

Structure(结构)

结构由**组件(Components)**组成,组件可以是:

1
2
3
4
5
6
7
Structure
├── Data Elements (数据元素) — 基本字段
├── Built-in Types (内置类型) — 直接类型定义
├── Other Structures (其他结构) — 子结构
├── Internal Tables (内表/表类型) — 深层组件
├── DB Tables / Views (数据库表/视图) — 仅取扁平字段
└── Table Types (表类型) — 内表组件
📌扁平化规则
即使 Include 了数据库表或视图(二维对象),生成的数据对象仍是一维的

扁平结构 (Flat Structure)

最简单的结构形式——组件全部是数据元素:

1
2
3
4
ZPERSON
├── FIRSTNAME (data element)
├── LASTNAME (data element)
└── BIRTHDAY (data element)
  • 地址方式: wa_person-firstname

嵌套结构 (Nested Structure)

包含子结构作为组件:

1
2
3
4
5
6
ZPERSON
├── NAME (ZNAME 结构) ← 嵌套
│ ├── FIRSTNAME
│ └── LASTNAME
├── STREET (data element)
└── CITY (data element)
  • 地址方式: wa_person-name-firstname

Include 结构

使用 .INCLUDE 关键字将一个结构的字段直接展开到父结构中:

1
2
3
4
5
6
7
ZPERSON
├── .INCLUDE ZADDRESS ← 字段直接展开(无嵌套层级)
│ ├── STREET
│ ├── NR
│ ├── ZIP
│ └── CITY
├── NAME (ZNAME 结构) ← 嵌套(有层级)
💡Include vs 嵌套的区别
  • Include: wa_person-street(扁平访问,无前缀)
  • 嵌套: wa_person-name-firstname(层级访问)
  • Include 实际上把子结构的字段拷贝到父结构中

深层结构 (Deep Structure)

包含至少一个内表组件的结构:

1
2
3
4
5
6
ZPERSON (Deep Structure)
├── NAME (ZNAME 结构)
├── .INCLUDE ZADDRESS
└── PHONE (ZIT_PHONE_NUMBER 表类型) ← 内表组件
├── P_TYPE
└── P_NUMBER
  • 访问内表: LOOP AT wa_person-phone INTO wa_phone.
  • 可以多层嵌套:内表的行类型本身也可以是深层结构
⚠️数据库表限制
数据库表只能包含扁平结构,不能有深层结构中的内表组件。

Table Type(表类型)

表类型描述**内表(Internal Table)**的结构,在 ABAP 程序中创建二维数组。

定义要素

Element (要素) Options (选项)
Line Type (行类型) 数据元素、结构、DB 表、视图、其他表类型
Access Type (访问方式) Standard / Sorted / Hashed
Key Type (键类型) Unique / Non-unique
Key Definition (键定义) Standard Key / Key Components

访问方式对比

Access Type 特点 适用场景
Standard Table 线性搜索,无序 小数据量,不需排序
Sorted Table 按 key 排序,二分搜索 需要排序访问
Hashed Table 哈希索引 大数据量按键查找

创建示例

1
2
3
4
5
6
SE11 → Data Type → Create → Table Type
├── Short Description: "Sorted table for SFLIGHT"
├── Line Type: SFLIGHT (数据库表)
├── Access Type: Sorted Table
├── Key Type: Non-unique
└── Key Components: FLDATE

在 ABAP 中使用:

1
2
3
4
5
6
DATA it_flight TYPE zit_sflight##.
DATA wa_sflight TYPE sflight.
SELECT * FROM sflight INTO TABLE it_flight WHERE carrid = 'JL'.
LOOP AT it_flight INTO wa_sflight.
WRITE: / wa_sflight-carrid, wa_sflight-fldate.
ENDLOOP.

考试/测试模式

Scenario/Keyword (场景/关键词) Answer (答案)
“深层结构的定义条件?” 包含至少一个内表组件
“数据库表能用深层结构吗?” 不能,只能用扁平结构
“Include 和嵌套的区别?” Include 扁平展开,嵌套增加层级
“Include 链中的数据库表?” 只能有一个(就是表本身)

单元 3:表访问性能练习(8 道题)

#practice #abap #abap-dictionary #abap-performance

相关概念

📌关键模式(点击展开)
Keyword (关键词) Answer (答案)
主索引 键字段上自动创建,ID 为 0
二级索引命名 客户创建以 Y 或 Z 开头
索引使用范围 只到最后一个在 WHERE 中指定的字段
完全缓冲触发 访问任一记录时加载全表
缓冲性能提升 10 到 100 倍
/$TAB 重置表缓冲(仅修复不一致)

问题 1 - 主索引与二级索引 [recall]

主索引和二级索引有什么区别?

📌显示答案
对比项 主索引 二级索引
创建方式 自动创建 手动创建
索引 ID 0 客户创建以 Y 或 Z 开头
基于字段 键字段 WHERE 中频繁使用的非键字段
唯一性 始终唯一 可设为 Unique 或 Non-unique

问题 2 - 索引使用规则 [recall]

当 WHERE 子句中使用了索引字段,但跳过了中间某个字段时,索引还能被完全利用吗?解释原因。

📌显示答案
不能。索引只能使用到最后一个在 WHERE 中指定的字段。跳过中间字段后,后续字段无法使用索引。因此:
  • WHERE 中出现频率高的字段应放在索引前面
  • 跳过索引中间字段会导致后续字段查找退化为全表扫描
  • 只有显著减少数据量的字段才有意义加入索引

问题 3 - 缓冲类型 [recall]

ABAP 字典提供哪三种表缓冲类型?分别适用于什么场景?

📌显示答案
缓冲类型 触发条件 加载内容 适用场景
完全缓冲 (Full) 访问任一记录 全表所有记录 ≤10,000 条,读频繁,很少修改
通用缓冲 (Generic) 访问某记录 同一左键前缀的所有记录 按键前缀分组访问
单记录缓冲 (Single-record) 访问某记录 该条记录 大表、随机访问

问题 4 - 缓冲同步机制 [recall]

当某个应用服务器修改了被缓冲的表数据时,其他应用服务器的缓冲如何处理?

📌显示答案
数据修改时,所有应用服务器的缓冲被标记失效。失效后的第一次访问需要从数据库重新加载。同步是异步执行的。这意味着在短暂时间窗口内,其他服务器可能读取到旧数据。

问题 5 - 索引设计建议 [recall]

创建二级索引时,有哪些关键考虑因素?

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

问题 6 - 缓冲选择决策 [application]

一个自定义表 ZCONFIG 有 500 条配置数据,每天被读取数千次,每月只修改 1-2 次。应该选择哪种缓冲类型?为什么?

📌显示答案
应选择完全缓冲 (Full Buffering)
  • 数据量小(500 条,远低于 10,000 条阈值)
  • 读取频率高(每天数千次)
  • 修改频率极低(每月 1-2 次)
  • 完全缓冲在首次访问时加载全表到内存,后续读取直接从内存获取,性能提升 10-100 倍
  • 修改频率低意味着缓冲失效很少发生

问题 7 - 索引使用分析 [application]

表 SPFLI 有二级索引 A11,字段顺序为 (CITYFROM, CITYTO)。以下哪个 WHERE 子句能充分利用该索引?

  • (a) WHERE cityto = 'TOKYO'
  • (b) WHERE cityfrom = 'NEW YORK' AND cityto = 'TOKYO'
  • (c) WHERE cityfrom = 'NEW YORK' AND carrid = 'AA' AND cityto = 'TOKYO'
📌显示答案
  • (a) 不能使用索引 — 跳过了第一个字段 CITYFROM,直接使用 CITYTO 无法利用索引
  • (b) 可以完全利用索引 — 两个字段都按顺序指定
  • (c) 只能使用索引的 CITYFROM 部分 — 因为中间出现了非索引字段 carrid,CITYTO 无法利用索引(索引只能使用到最后一个连续指定的字段)

问题 8 - 性能优化综合分析 [analysis]

一个大型事务表(100 万+行)被多用户频繁按 (CARRID, CONNID, FLDATE) 查询,同时也经常按 CARRID 单独统计。表的数据每天批量更新一次。请设计索引和缓冲策略。

📌显示答案
索引策略:
  • 主索引(已有):键字段上自动创建
  • 二级索引 1:(CARRID, CONNID, FLDATE) — 用于频繁的组合查询
  • 二级索引 2:(CARRID) — 用于按 CARRID 的统计查询
  • 由于是事务表且每天更新,索引数量应控制在 2-3 个以内

缓冲策略:

  • 不建议缓冲 — 因为是大表(100 万+行)且频繁修改
  • 完全缓冲不适合(数据量太大)
  • 单记录缓冲也不适合(频繁批量更新会导致缓冲不断失效)
  • 应通过合理的索引来优化查询性能

📌模式总结(点击展开)
Keyword (关键词) Answer (答案)
主索引 自动创建,ID 为 0,基于键字段
二级索引 手动创建,Y/Z 开头
索引使用规则 只到最后一个连续 WHERE 字段
完全缓冲 访问任一记录加载全表,≤10,000 条
通用缓冲 按键前缀加载
单记录缓冲 仅加载访问的记录
缓冲同步 修改时所有服务器标记失效,异步执行
/$TAB 重置缓冲,仅修复不一致

特殊 SAP 表 — 池表与簇表 (★★★)

#abap #abap-dictionary #abap-tables

概览表

Feature (特性) Transparent (透明表) Pooled (池表) Cluster (簇表)
DB 中独立存在
存储方式 独立表 多表合并到表池 多表合并到表簇
数据压缩 是(非键字段) 是(全部数据)
可建索引 主键+二级索引 仅键字段 仅簇键
JOIN / View 支持 不支持 不支持
Table Append 支持 不支持 不支持
SQL 限制 仅 Open SQL 仅 Open SQL

池表 (Pooled Tables)

多个逻辑表存储在一个表池 (Table Pool) 中。

1
2
3
4
5
6
7
8
9
Dictionary:           Database:
┌─────┐ ┌─────────────────────────────────────┐
│TABA │──┐ │ TABAB (Table Pool) │
│ │ │ │─────────────────────────────────────│
├─────┤ ├──→ │ TABNAME │ VARKEY │ VARDATA │ DATALN │
│TABB │──┘ │─────────────────────────────────────│
└─────┘ │ TABA │ key1 │ data... │ len │
│ TABB │ key2 │ data... │ len │
└─────────────────────────────────────┘
  • TABNAME: 池表名称
  • VARKEY: 池表键字段的拼接(所以键字段必须是 C 类型)
  • VARDATA: 非键字段的压缩数据
  • DATALN: VARDATA 的长度
📌池表特点
  • 各池表之间无功能依赖(只是合并小表)
  • 键字段的交集可能为空
  • 键字段必须是 C 类型(字符型)

簇表 (Cluster Tables)

功能相关的数据存储在一个表簇 (Table Cluster) 中。

1
2
3
4
5
6
7
8
Dictionary:           Database:
┌─────┐ ┌───────────────────────────────────────────────┐
│TAB1 │──┐ │ Table Cluster │
│ │ │ │───────────────────────────────────────────────│
├─────┤ ├──→ │ Cluster Key │ PAGNO │ VARDATA │ TIMEST │ PAGELG│
│TAB2 │──┘ │───────────────────────────────────────────────│
└─────┘ │ key_value │ 0 │ compressed│ │ │
└───────────────────────────────────────────────┘
  • Cluster Key: 各簇表键字段的交集
  • VARDATA: 所有依赖数据的压缩存储
  • PAGNO: 页号(溢出记录时使用)
  • 数据库接口负责压缩/解压
📌簇表特点
  • 簇表之间有功能依赖(共享簇键)
  • VARDATA 包含解压描述信息
  • 溢出时创建新页(PAGNO 递增)

优缺点

优点

  • 压缩存储:减少磁盘空间和网络负载
  • 减少表数量:合并到物理表中
  • 更少 SQL 语句:减少不同 SQL 的种类
  • 簇表的联合读取:功能相关数据一起读取,减少数据库访问

缺点

  • 索引受限:非键字段不能建索引
  • 无 JOIN/View:不能用于数据库视图或 ABAP JOIN
  • 无 Table Append:不能用 Append 结构
  • 仅 Open SQL:不能用 Native SQL
  • WHERE 限制:池表仅键字段,簇表仅簇键字段的 WHERE 传递到 DB
  • ORDER BY/GROUP BY 限制:非键字段不支持

考试/测试模式

Scenario/Keyword (场景/关键词) Answer (答案)
“池表和簇表的主要区别?” 池表无功能依赖,簇表有功能依赖(共享簇键)
“池表键字段类型限制?” 必须是 C 类型
“池表/簇表能用 JOIN 吗?” 不能
“池表/簇表能用 Append 结构吗?” 不能
0%