核心内容摘要
零基础玩转VibeVoice:25种音色一键切换教程
内表基本概念
1 什么是内表内表是ABAP程序运行时在内存中创建的临时表用于存储和处理多行数据作为程序间数据传递的容器与数据库表进行批量数据交换进行复杂的数据计算和处理
2 内表的物理结构内存中的内表结构 ┌─────────────────────────────────┐ │ 内表控制块 (Table Control Block) │ ├─────────────────────────────────┤ │ 表头信息 (Header Information) │ │ - 行数 │ │ - 行宽度 │ │ - 表类型 │ │ - 键信息 │ ├─────────────────────────────────┤ │ 数据行指针数组 │ │ ┌─┬─┬─┬─┬─┬─┐ │ │ │0│1│2│3│4│5│ → 指向实际数据行 │ │ └─┴─┴─┴─┴─┴─┘ │ ├─────────────────────────────────┤ │ 实际数据存储区 │ │ ┌─────────────────┐ │ │ │ 行1数据 │ │ │ ├─────────────────┤ │ │ │ 行2数据 │ │ │ ├─────────────────┤ │ │ │ ... │ │ │ └─────────────────┘ │ └─────────────────────────────────┘
3 内表与数据库表的区别特性内表数据库表存储位置程序内存数据库生命周期程序运行期间永久访问速度极快相对较慢存储容量受内存限制受磁盘空间限制事务控制不支持支持并发访问单程序独占多程序共享
内表类型深度解析
1 标准表STANDARD TABLE 标准表的完整声明语法 DATA: gt_std TYPE STANDARD TABLE OF sflight WITH NON-UNIQUE KEY carrid connid WITH HEADER LINE INITIAL SIZE 100 WITH UNIQUE SORTED KEY sec_key COMPONENTS fldate WITH NON-UNIQUE SORTED KEY sec_key2 COMPONENTS price currency.特点默认表类型支持索引访问INDEX和键访问WITH KEY使用线性查找算法插入行效率高查找效率低O(n)
2 排序表SORTED TABLE 排序表的声明 DATA: gt_sorted TYPE SORTED TABLE OF sflight WITH UNIQUE KEY carrid connid fldate WITH NON-UNIQUE SORTED KEY price_key COMPONENTS price INITIAL SIZE
特点数据始终按键排序存储使用二分查找算法O(log n)插入/删除需要维护排序可定义唯一或非唯一主键
3 哈希表HASHED TABLE 哈希表的声明 DATA: gt_hashed TYPE HASHED TABLE OF sflight WITH UNIQUE KEY mandt carrid connid fldate WITH NON-UNIQUE HASHED KEY carrier_key COMPONENTS carrid INITIAL SIZE
特点键访问最快O(
不支持索引访问内存消耗较大键必须是唯一的
4 索引表INDEX TABLE- 已弃用但需了解 传统索引表声明 DATA: gt_index TYPE INDEX TABLE OF sflight WITH UNIQUE KEY carrid OCCURS
OCCURS子句已弃用用STANDARD TABLE替代
内表声明方式大全
1 基于ABAP字典对象
基于透明表 DATA: gt_sflight TYPE TABLE OF sflight. DATA: gt_sflight TYPE STANDARD TABLE OF sflight.
基于结构 DATA: gt_mara TYPE TABLE OF mara. DATA: gt_ekpo TYPE TABLE OF ekpo.
基于类型池已弃用了解即可 TYPE-POOLS: slis. DATA: gt_fieldcat TYPE slis_t_fieldcat_alv.
2 基于本地类型
先定义类型再声明变量 TYPES: BEGIN OF ty_employee, pernr TYPE persno, name TYPE string, dept TYPE orgeh, salary TYPE betrg, END OF ty_employee. TYPES: tt_employees TYPE STANDARD TABLE OF ty_employee WITH NON-UNIQUE KEY pernr. DATA: gt_employees TYPE tt_employees.
直接声明 DATA: gt_employees TYPE TABLE OF ty_employee.
3 使用TYPE REF TO声明内表引用 内表对象引用 DATA: go_table TYPE REF TO data. DATA: gt_data TYPE REF TO data. FIELD-SYMBOLS: fs_table TYPE ANY TABLE. 动态创建内表 CREATE DATA go_table TYPE TABLE OF (dyn_table_name). ASSIGN go_table-* TO fs_table.
4 带表头行 vs 不带表头行 带表头行旧式不推荐 DATA: gt_itab TYPE TABLE OF sflight WITH HEADER LINE. gt_itab-carrid LH. 访问表头行 APPEND gt_itab. 将表头行添加到表体 不带表头行推荐 DATA: gt_itab TYPE TABLE OF sflight. DATA: gs_wa TYPE sflight. gs_wa-carrid LH. APPEND gs_wa TO gt_itab.
内表操作全解
1 填充操作APPEND 基本APPEND APPEND gs_line TO gt_table. APPEND INITIAL LINE - 添加初始行 APPEND INITIAL LINE TO gt_table ASSIGNING FIELD-SYMBOL(fs). fs-field value. APPEND LINES OF - 批量添加 DATA: gt_source TYPE TABLE OF sflight, gt_target TYPE TABLE OF sflight. SELECT * FROM sflight INTO TABLE gt_source. APPEND LINES OF gt_source TO gt_target. APPEND 使用排序键仅排序表 DATA: gt_sorted TYPE SORTED TABLE OF sflight WITH UNIQUE KEY carrid connid. gs_line-carrid AA. gs_line-connid
APPEND gs_line TO gt_sorted. 自动插入到正确位置INSERT INSERT INTO TABLE - 智能插入 INSERT gs_line INTO TABLE gt_table. INSERT INTO INDEX - 指定位置插入 INSERT gs_line INTO gt_table INDEX
INSERT LINES OF - 批量插入 INSERT LINES OF gt_source FROM 1 TO 10 INTO gt_target INDEX
使用字段符号插入 INSERT VALUE #( carrid LH connid 0400 ) INTO TABLE gt_table.COLLECTTYPES: BEGIN OF ty_sum, matnr TYPE matnr, menge TYPE menge_d, meins TYPE meins, END OF ty_sum. DATA: gt_sum TYPE TABLE OF ty_sum WITH NON-UNIQUE KEY matnr. gs_sum-matnr MAT
gs_sum-menge
gs_sum-meins PC. COLLECT gs_sum INTO gt_sum. gs_sum-matnr MAT
gs_sum-menge
COLLECT gs_sum INTO gt_sum. MAT001的menge变为
1
2 读取操作READ TABLE的各种形式
通过索引读取 READ TABLE gt_table INTO gs_line INDEX
5.
通过键读取 READ TABLE gt_table INTO gs_line WITH KEY carrid LH. READ TABLE gt_table INTO gs_line WITH KEY carrid LH connid
0400.
通过表键读取排序表和哈希表 READ TABLE gt_sorted INTO gs_line WITH TABLE KEY carrid LH connid
0400.
使用BINARY SEARCH必须排序 SORT gt_table BY carrid connid. READ TABLE gt_table INTO gs_line WITH KEY carrid LH connid 0400 BINARY SEARCH.
读取到字段符号高效 READ TABLE gt_table ASSIGNING FIELD-SYMBOL(fs_line) INDEX
IF sy-subrc
fs_line-field new value. ENDIF.
读取到数据引用 DATA: lr_line TYPE REF TO data. READ TABLE gt_table REFERENCE INTO lr_line INDEX
IF sy-subrc
ASSIGN lr_line-* TO FIELD-SYMBOL(fs). ENDIF.
读取并传输字段 READ TABLE gt_table INDEX 1 TRANSPORTING carrid connid.
读取时忽略缓存 READ TABLE gt_table INTO gs_line WITH KEY carrid LH BYPASSING BUFFER. 忽略表缓冲内表表达式读取
4
直接读取 DATA(ls_line) gt_table[ 1 ]. 索引读取 DATA(ls_line
gt_table[ carrid LH ]. 键读取
安全读取避免异常 DATA(ls_line
VALUE #( gt_table[ 99 ] OPTIONAL ). 索引 DATA(ls_line
VALUE #( gt_table[ carrid XXX ] OPTIONAL ). 键
使用辅助键读取 DATA(ls_line
gt_table[ KEY sec_key price 1000 ].
读取并修改 gt_table[ 1 ]-field new value.
3 修改操作MODIFY
通过索引修改 MODIFY gt_table FROM gs_line INDEX
3.
通过表键修改 MODIFY TABLE gt_table FROM gs_line. 使用主键
通过键修改修改所有匹配行 MODIFY gt_table FROM gs_line TRANSPORTING price WHERE carrid LH. 危险修改所有LH的行
在循环中修改 LOOP AT gt_table ASSIGNING FIELD-SYMBOL(fs_line) WHERE carrid LH. fs_line-price fs_line-price *
1.
ENDLOOP.UPDATE UPDATE仅用于数据库表内表用MODIFY UPDATE sflight FROM TABLE gt_sflight. 更新数据库表
4 删除操作DELETE
通过索引删除 DELETE gt_table INDEX
5.
通过表键删除 DELETE TABLE gt_table WITH TABLE KEY carrid LH connid
0400.
通过键删除 DELETE gt_table WHERE carrid LH. 删除所有匹配行
删除相邻重复行 SORT gt_table BY carrid connid fldate. DELETE ADJACENT DUPLICATES FROM gt_table COMPARING carrid connid.
删除重复行但保留第一行 DELETE ADJACENT DUPLICATES FROM gt_table COMPARING ALL FIELDS.
批量删除 DELETE gt_table FROM 10 TO
删除索引
的行
5 循环遍历LOOP AT
基本循环 LOOP AT gt_table INTO gs_line. 处理数据 ENDLOOP.
使用字段符号推荐 LOOP AT gt_table ASSIGNING FIELD-SYMBOL(fs_line). fs_line-field value. ENDLOOP.
使用WHERE条件 LOOP AT gt_table INTO gs_line WHERE carrid LH. WRITE: / gs_line-carrid, gs_line-connid. ENDLOOP.
使用FROM/TO限定范围 LOOP AT gt_table INTO gs_line FROM 5 TO
ENDLOOP.
循环并删除需使用索引 LOOP AT gt_table ASSIGNING FIELD-SYMBOL(fs_line). IF fs_line-carrid XX. DELETE gt_table INDEX sy-tabix. ENDIF. ENDLOOP.
循环使用TRANSPORTING LOOP AT gt_table INTO gs_line TRANSPORTING carrid connid. ENDLOOP.内表表达式循环
4
使用FOR表达式 DATA(lt_filtered) VALUE tt_sflight( FOR wa IN gt_sflight WHERE ( carrid LH ) ( wa ) ).
在构造函数中使用循环 DATA(lt_names) VALUE string_table( FOR wa IN gt_sflight ( |{ wa-carrid }-{ wa-connid }| ) ).
6 排序与分组SORT
基本排序 SORT gt_table BY carrid ASCENDING connid DESCENDING.
按数字字段排序 SORT gt_table BY price AS TEXT. 文本排序 SORT gt_table BY price AS NUMBER. 数字排序
稳定排序 SORT gt_table STABLE BY carrid. 保持相等元素的相对顺序
自定义排序顺序 TYPES: BEGIN OF ty_sort_order, field TYPE string, order TYPE c LENGTH 1, END OF ty_sort_order. DATA: gt_sort TYPE TABLE OF ty_sort_order. APPEND VALUE #( field CARRID order A ) TO gt_sort. APPEND VALUE #( field CONNID order D ) TO gt_sort. 动态排序复杂需使用动态SQL或字段符号分组处理
AT NEW / AT END OF SORT gt_data BY carrid connid. LOOP AT gt_data INTO gs_data. AT NEW carrid. WRITE: / New Carrier:, gs_data-carrid. ENDAT. AT END OF connid. SUM. 对数字字段求和 WRITE: / Sum for connection:, gs_data-connid. ENDAT. ENDLOOP.
使用REDUCE分组 DATA(lt_grouped) REDUCE tt_sflight( INIT groups VALUE tt_sflight( ) FOR GROUPS group OF wa IN gt_sflight GROUP BY ( carrier wa-carrid ) ( VALUE #( BASE groups FOR g IN GROUP group ( g ) ) ) ).
内表函数与方法
1 DESCRIBE TABLEDATA: lv_lines TYPE i, lv_kind TYPE abap_tablekind, lv_occurs TYPE i, lv_initial TYPE abap_bool. 获取行数 DESCRIBE TABLE gt_table LINES lv_lines. 获取表类型 DESCRIBE TABLE gt_table KIND lv_kind. 获取初始大小 DESCRIBE TABLE gt_table OCCURS lv_occurs. 是否为空 DESCRIBE TABLE gt_table LINES lv_lines. IF lv_lines
空表 ENDIF. 获取所有属性 DESCRIBE TABLE gt_table LINES lv_lines KIND lv_kind OCCURS lv_occurs.
2 LINES函数 获取行数
4推荐 DATA(lv_count) lines( gt_table ). 在条件中使用 IF lines( gt_table )
表非空 ENDIF.
3 内表表达式函数REDUCE
求和 DATA(lv_total) REDUCE i( INIT sum 0 FOR wa IN gt_sflight NEXT sum sum wa-price ).
复杂聚合 TYPES: BEGIN OF ty_stats, carrier TYPE s_carr_id, count TYPE i, total TYPE s_price, avg TYPE s_price, END OF ty_stats. DATA(lt_stats) REDUCE TABLE OF ty_stats( INIT result VALUE tt_stats( ) FOR GROUPS group OF wa IN gt_sflight GROUP BY ( carrier wa-carrid ) LET count REDUCE i( INIT cnt 0 FOR g IN GROUP group NEXT cnt cnt 1 ) total REDUCE s_price( INIT t 0 FOR g IN GROUP group NEXT t t g-price ) IN NEXT result VALUE #( BASE result ( carrier group-carrier count count total total avg total / count ) ) ).FILTER 过滤内表 DATA(lt_filtered) FILTER #( gt_sflight WHERE carrid LH AND price 1000 ). 使用辅助键过滤 DATA(lt_by_price) FILTER #( gt_sflight USING KEY price_key WHERE price 500 ).FOR表达式 生成新内表 DATA(lt_doubled) VALUE tt_sflight( FOR wa IN gt_sflight ( CORRESPONDING #( BASE ( wa ) price wa-price * 2 ) ) ). 条件构造 DATA(lt_discounted) VALUE tt_sflight( FOR wa IN gt_sflight LET discount COND #( WHEN wa-price 1000 THEN
9 WHEN wa-price 500 THEN
95 ELSE 1 ) IN ( CORRESPONDING #( BASE ( wa ) price wa-price * discount ) ) ).
性能优化深度指南
1 表类型选择策略场景推荐表类型原因频繁遍历标准表索引访问快按键查找为主哈希表O(
查找需要排序输出排序表自动排序数据频繁插入删除标准表维护成本低数据量巨大且键唯一哈希表查找效率最高范围查询多排序表二分查找效率高
2 高效读取策略
使用正确的查找方式 标准表先SORT再用BINARY SEARCH SORT gt_std BY carrid connid. READ TABLE gt_std INTO gs_line WITH KEY carrid LH connid 0400 BINARY SEARCH. 排序表直接使用TABLE KEY READ TABLE gt_sorted INTO gs_line WITH TABLE KEY carrid LH connid
哈希表直接使用TABLE KEY READ TABLE gt_hashed INTO gs_line WITH TABLE KEY carrid LH connid
0400.
使用辅助键 声明时定义辅助键 DATA: gt_sorted TYPE SORTED TABLE OF sflight WITH NON-UNIQUE KEY primary_key COMPONENTS carrid connid WITH NON-UNIQUE SORTED KEY price_key COMPONENTS price. 使用辅助键读取 READ TABLE gt_sorted INTO gs_line USING KEY price_key WITH KEY price
1000.
避免全表扫描 错误性能差 LOOP AT gt_table INTO gs_line. IF gs_line-carrid LH. 处理 ENDIF. ENDLOOP. 正确使用WHERE或先过滤 LOOP AT gt_table INTO gs_line WHERE carrid LH. ENDLOOP. 或使用FILTER DATA(lt_lh) FILTER #( gt_table WHERE carrid LH ).
3 内存优化技巧
设置合适的初始大小 DATA: gt_large TYPE TABLE OF sflight INITIAL SIZE
10000.
及时释放内存 FREE: gt_table. 释放内存 CLEAR: gt_table. 清空内容但保留结构
使用PACKAGE SIZE分批处理 SELECT * FROM sflight INTO TABLE gt_buffer PACKAGE SIZE
处理数据 CLEAR: gt_buffer. ENDSELECT.
避免深层结构 深层结构占用更多内存 TYPES: BEGIN OF ty_deep, header TYPE string, items TYPE TABLE OF ty_item, 嵌套表 END OF ty_deep.
使用字段符号避免复制 FIELD-SYMBOLS: fs_line TYPE any. ASSIGN gt_table[ 1 ] TO fs_line.
删除不必要字段 读取时只取需要字段 SELECT carrid, connid, price FROM sflight INTO CORRESPONDING FIELDS OF TABLE gt_table WHERE carrid LH.
4 批量操作优化
使用数组操作而非单行操作 差逐行插入 LOOP AT gt_source INTO gs_source. INSERT gs_source INTO TABLE gt_target. ENDLOOP. 好批量插入 INSERT LINES OF gt_source INTO TABLE gt_target.
批量修改数据库 单行更新 LOOP AT gt_sflight INTO gs_sflight. UPDATE sflight FROM gs_sflight. ENDLOOP. 批量更新 UPDATE sflight FROM TABLE gt_sflight.
使用FOR ALL ENTRIES优化 IF gt_keys IS NOT INITIAL. SELECT * FROM sflight INTO TABLE gt_data FOR ALL ENTRIES IN gt_keys WHERE carrid gt_keys-carrid AND connid gt_keys-connid. ENDIF.
高级主题
1 动态内表操作
动态创建内表 DATA: lr_table TYPE REF TO data, lt_comp TYPE cl_abap_structdescrcomponent_table. APPEND VALUE #( name CARRID type CAST #( cl_abap_elemdescrget_c( p_length 3 ) ) ) TO lt_comp. APPEND VALUE #( name CONNID type CAST #( cl_abap_elemdescrget_n( p_length 4 ) ) ) TO lt_comp. DATA(lo_struct) cl_abap_structdescrcreate( lt_comp ). DATA(lo_table) cl_abap_tabledescrcreate( lo_struct ). CREATE DATA lr_table TYPE HANDLE lo_table. ASSIGN lr_table-* TO FIELD-SYMBOL(fs_dyn_table).
动态读取 READ TABLE fs_dyn_table ASSIGNING FIELD-SYMBOL(fs_dyn_line) INDEX
1.
动态赋值 ASSIGN COMPONENT CARRID OF STRUCTURE fs_dyn_line TO FIELD-SYMBOL(fs_field). fs_field LH.
2 内表与ALV集成
准备内表数据 DATA: gt_sflight TYPE TABLE OF sflight, go_alv TYPE REF TO cl_salv_table. SELECT * FROM sflight INTO TABLE gt_sflight.
显示ALV cl_salv_tablefactory( IMPORTING r_salv_table go_alv CHANGING t_table gt_sflight ). go_alv-display( ).
设置ALV属性 DATA: lo_columns TYPE REF TO cl_salv_columns, lo_column TYPE REF TO cl_salv_column. lo_columns go_alv-get_columns( ). lo_column lo_columns-get_column( PRICE ). lo_column-set_currency_column( CURRENCY ).
3 内表序列化
内表转XML DATA: lv_xml TYPE string. CALL TRANSFORMATION id SOURCE data gt_sflight RESULT XML lv_xml.
XML转内表 CALL TRANSFORMATION id SOURCE XML lv_xml RESULT data gt_sflight.
内表转JSON
5 DATA(lv_json) /ui2/cl_jsonserialize( gt_sflight ).
JSON转内表 /ui2/cl_jsondeserialize( EXPORTING json lv_json CHANGING data gt_sflight ).
4 内表调试技巧
快速查看内表内容 在调试器中使用 - 双击内表变量 - 右键 → 显示为表 - 使用内表查看器
程序内输出内表 cl_demo_outputdisplay_data( gt_sflight ).
性能分析 使用事务码SAT或SE30 分析内表操作性能
内存分析 使用事务码S_MEMORY_INSPECTOR
最佳实践与常见陷阱
1 最佳实践
始终指定表类型和键 DATA: gt_table TYPE SORTED TABLE OF ty_structure WITH UNIQUE KEY field1 field
2.
使用字段符号进行循环 LOOP AT gt_table ASSIGNING FIELD-SYMBOL(fs_line). fs_line-field value. ENDLOOP.
使用现代语法
4 DATA(lt_filtered) FILTER #( gt_table WHERE field X ). DATA(ls_line) VALUE #( gt_table[ 1 ] OPTIONAL ).
批量操作数据库 UPDATE dbtable FROM TABLE gt_itab.
及时释放内存 FREE: gt_large_table.
2 常见陷阱
忘记检查SY-SUBRC READ TABLE gt_table INTO gs_line WITH KEY field X. 错误未检查是否找到 gs_line-other_field Y. 可能使用初始值
MODIFY WHERE修改多行 MODIFY gt_table FROM gs_line TRANSPORTING field WHERE key X. 修改所有keyX的行
内表复制错误 错误浅拷贝 MOVE gt_table1 TO gt_table
仅复制表头 正确深拷贝 gt_table2 gt_table
1.