特殊表技术

内表特殊技术 (★★★)

#internal-tables

二分搜索(BINARY SEARCH)

  • 要求读取前数据按读取键排序
  • 在标准表上:必须先 SORT,再使用 BINARY SEARCH 读取
  • 在排序表上:自动(WITH TABLE KEY 内置二分搜索)
  • 如果表未按读取键排序,结果不可预测(不报错)
1
2
3
4
5
6
" 标准表:必须先排序
SORT lt_standard BY name.
READ TABLE lt_standard INTO ls_wa WITH KEY name = 'Smith' BINARY SEARCH.

" 排序表:自动
READ TABLE lt_sorted INTO ls_wa WITH TABLE KEY name = 'Smith'.
⚠️在未排序的表上使用 BINARY SEARCH 不会报错。它只会返回不正确或不可预测的结果。务必确保排序顺序与读取键匹配。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
标准表使用 BINARY SEARCH:
+--------------------+
| 1. SORT 按读取键 | <-- 二分搜索前必需
+--------------------+
|
+--------------------+
| 2. READ TABLE ... | <-- BINARY SEARCH 附加项
| WITH KEY ... |
| BINARY SEARCH |
+--------------------+

排序表:
+--------------------+
| READ TABLE ... | <-- 二分搜索自动执行
| WITH TABLE KEY ... | (不需要 BINARY SEARCH)
+--------------------+

DELETE ADJACENT DUPLICATES(删除相邻重复项)

  • 仅删除相邻的重复行
  • 必须先排序(按比较字段)
  • COMPARING 附加项指定比较哪些字段
1
2
3
4
5
6
7
8
" 先排序!
SORT lt_data BY id.

" 按指定字段比较删除相邻重复项
DELETE ADJACENT DUPLICATES FROM lt_data COMPARING id.

" 比较所有字段删除相邻重复项(默认)
DELETE ADJACENT DUPLICATES FROM lt_data.
附加项 行为
(无 COMPARING) 比较字符型和数值型的所有字段
COMPARING f1 f2 ... 仅比较指定字段
COMPARING ALL FIELDS 显式比较所有字段
📌DELETE ADJACENT DUPLICATES 仅删除相邻的重复项。如果表未先排序,不相邻的重复项会保留。

COLLECT(收集)

  • 将数值字段添加到匹配键的已有行
  • 如果没有匹配行,插入新行
  • 键比较基于所有非数值字段
  • 仅适用于平坦行类型(不含深层结构)
1
2
3
4
5
6
7
8
9
10
11
12
13
DATA: BEGIN OF ls_totals,
category TYPE string,
amount TYPE i,
END OF ls_totals.
DATA: lt_totals LIKE TABLE OF ls_totals.

" 首次出现:插入新行
ls_totals-category = 'A'. ls_totals-amount = 10.
COLLECT ls_totals INTO lt_totals.

" 找到匹配键:累加金额(10 + 20 = 30)
ls_totals-category = 'A'. ls_totals-amount = 20.
COLLECT ls_totals INTO lt_totals.
1
2
3
4
5
6
7
COLLECT 处理过程:
+--------------------------------------------+
| 1. 提取非数值字段作为键 |
| 2. 搜索具有相同键的已有行 |
| +--> 找到:将数值字段加到该行 |
| +--> 未找到:插入新行 |
+--------------------------------------------+
⚠️COLLECT 仅适用于平坦行类型。深层结构(包含内表、字符串、引用)会导致运行时错误。
特性 行为
键字段 所有非数值字段
数值字段 求和(累加)
行类型 仅平坦
表类型 任意(但带唯一键的哈希表最理想)

次键(NW 7.0 EhP2)

用途

  • 在主键之外为表定义额外的键
  • 通过不同字段组合实现优化访问
  • 避免对不同访问模式反复排序标准表

次键类型

类型 语法 唯一性 访问
NON-UNIQUE SORTED WITH NON-UNIQUE SORTED KEY 非唯一 二分搜索 O(log n)
UNIQUE HASHED WITH UNIQUE HASHED KEY 唯一 哈希搜索 O(1)

语法

1
2
3
4
5
6
7
8
9
10
TYPES: BEGIN OF ty_struc,
id TYPE i,
name TYPE string,
dept TYPE string,
END OF ty_struc.

TYPES: ty_employees TYPE STANDARD TABLE OF ty_struc
WITH NON-UNIQUE KEY id
WITH NON-UNIQUE SORTED KEY sec_name COMPONENTS name
WITH UNIQUE HASHED KEY sec_dept COMPONENTS dept.

使用

1
2
3
4
5
6
7
8
9
10
DATA: lt_emp TYPE ty_employees.

" 使用次键读取
READ TABLE lt_emp INTO ls_wa USING KEY sec_name
WITH KEY name = 'Smith'.

" 使用次键循环
LOOP AT lt_emp INTO ls_wa USING KEY sec_name.
" 按 name 顺序处理
ENDLOOP.

何时使用次键

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
+------------------------------------------------------+
| 何时需要次键? |
+------------------------------------------------------+
| |
| 1. 同一表需要通过不同键字段访问 |
| (例如,按 ID 和按 name) |
| |
| 2. 标准表需要按非主键字段排序访问 |
| |
| 3. 避免每次不同读取模式前显式 SORT |
| |
| 不应使用的情况: |
| - 仅有一种访问模式 |
| - 表很小(< 100 行) |
| - 填充比率远高于读取比率 |
+------------------------------------------------------+
💡次键有代价:填充/修改表时,所有次键索引必须更新。仅在读取优化收益超过填充代价时使用。

INSERT INTO TABLE vs APPEND

语句 行为 表类型兼容性
APPEND wa TO itab 在末尾添加行 仅标准表
INSERT wa INTO TABLE itab 根据表类型插入 所有表类型
INSERT wa INTO itab INDEX n 在位置 n 插入 仅标准表
1
2
3
4
5
6
7
" APPEND:总是在末尾(标准表)
APPEND ls_wa TO lt_standard.

" INSERT INTO TABLE:根据类型行为不同
INSERT ls_wa INTO TABLE lt_standard. " 在末尾追加
INSERT ls_wa INTO TABLE lt_sorted. " 插入到正确排序位置
INSERT ls_wa INTO TABLE lt_hashed. " 插入到哈希桶
💡使用 INSERT INTO TABLE 进行泛型编程。它能正确适用于所有表类型。

表表达式(新语法)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
" 使用表表达式读取行
DATA(ls_row) = lt_itab[ id = '123' ].

" 使用次键
DATA(ls_row2) = lt_itab[ USING KEY sec_name name = 'Smith' ].

" 安全访问使用 OPTIONAL(防止 CX_SY_ITAB_LINE_NOT_FOUND)
DATA(ls_safe) = VALUE #( lt_itab[ id = '999' ] OPTIONAL ).

" 检查存在性
IF line_exists( lt_itab[ id = '123' ] ).
" 行存在
ENDIF.

" 获取匹配行的索引
DATA(lv_idx) = line_index( lt_itab[ name = 'Smith' ] ).
表达式/函数 返回值 未找到时异常?
itab[ key = val ] 行(副本) 是:CX_SY_ITAB_LINE_NOT_FOUND
... OPTIONAL 默认值 否(返回初始值)
line_exists( ... ) 布尔值
line_index( ... ) 索引或 0
⚠️表表达式 itab[ ... ] 在没有行匹配时抛出 CX_SY_ITAB_LINE_NOT_FOUND。使用 OPTIONALline_exists() 进行安全访问。

考试/测试模式

关键词/模式 答案
“BINARY SEARCH 未排序表” 返回不可预测的结果;不报错
“DELETE ADJACENT DUPLICATES” 仅删除相邻重复项;需先排序
“COMPARING 附加项” 指定重复比较的字段
“COLLECT 仅限平坦类型” 深层结构导致运行时错误
“COLLECT 键字段” 所有非数值字段组成键
“次键类型” NON-UNIQUE SORTED 或 UNIQUE HASHED
“USING KEY” 指定用于访问的次键
“INSERT INTO TABLE” 泛型插入;适用于所有表类型
“APPEND” 仅标准表;在末尾添加
“表表达式异常” 未找到行时抛出 CX_SY_ITAB_LINE_NOT_FOUND
“line_exists()” 返回布尔值;无异常
“何时使用次键” 同一表有多种访问模式

相关笔记