ABAP READ内表新老语法对比
1、读取内表行新语法
740新语法中,对标READ,提出了新的语法,如下:
1.1、根据字段值查找
"-----------------------------@斌将军----------------------------- "老语法 READ TABLE lt_acd INTO ls_acd WITH KEY rbukrs = gs_acd-rbukrs. IF sy-subrc EQ 0. ENDIF. "新语法 ls_acd = lt_acd[ rbukrs = gs_acd-rbukrs ]. "-----------------------------@斌将军-----------------------------
1.2、按索引查找
"-----------------------------@斌将军----------------------------- "老语法 READ TABLE lt_acd INTO ls_acd INDEX 1. IF sy-subrc EQ 0. ENDIF. "新语法 ls_acd = lt_acd[ 1 ]. "-----------------------------@斌将军-----------------------------
1.3、判断记录是否存在
"-----------------------------@斌将军----------------------------- "老语法 READ TABLE lt_acd WITH KEY rbukrs = gs_acd-rbukrs TRANSPORTING NO FIELDS. IF sy-subrc EQ 0. ENDIF. "新语法 IF LINE_EXISTS( lt_acd[ rbukrs = gs_acd-rbukrs ] ). ENDIF. "-----------------------------@斌将军-----------------------------
1.4、获取行索引
"-----------------------------@斌将军----------------------------- "老语法 READ TABLE lt_acd WITH KEY rbukrs = gs_acd-rbukrs TRANSPORTING NO FIELDS. IF sy-subrc EQ 0. WRITE:SY-TABIX. ENDIF. "新语法 LV_INDEX = LINE_INDEX( lt_acd[ rbukrs = gs_acd-rbukrs ] ). "-----------------------------@斌将军-----------------------------
需要特别注意的是,新语法必须用TRY CATCH,或在查询前,用LINE_EXISTS()判断是否存在,否则将会导致DUMP
TRY . ls_acd = lt_acd[ rbukrs = '333' ]. CATCH cx_sy_itab_line_not_found . MESSAGE '未找到数据' TYPE 'E' . ENDTRY. "或 IF line_exists( lt_acd[ rbukrs = '333' ] ). ls_acd = lt_acd[ rbukrs = '333' ]. ELSE. MESSAGE '未找到数据' TYPE 'E' . ENDIF.
2、效率对比
由于老语法可以使用二分法查找,因此在效率上将会有差异。
现编写一个实例,循环2万条数据GT_ACD,并循环查询有14万条数据的LT_ACD中对应的值。下边测试各种情况下的查询速度
2.1、新语法
"-----------------------------@斌将军----------------------------- "1.测试新语法------------------------------------ GET TIME STAMP FIELD lv_current1. CLEAR:lv_index. LOOP AT gt_acd INTO gs_acd. lv_index = lv_index + 1. TRY . ls_acd = lt_acd[ rbukrs = gs_acd-rbukrs gjahr = gs_acd-gjahr belnr = gs_acd-belnr docln = gs_acd-docln ]. CATCH cx_sy_itab_line_not_found . MESSAGE '未找到数据' TYPE 'E' . ENDTRY. ENDLOOP. GET TIME STAMP FIELD lv_current2. "-----------------------------@斌将军-----------------------------
结果:
2.2、老语法READ
"-----------------------------@斌将军----------------------------- "2.测试老语法------------------------------------ GET TIME STAMP FIELD lv_current1. CLEAR:lv_index. LOOP AT gt_acd INTO gs_acd. lv_index = lv_index + 1. READ TABLE lt_acd INTO ls_acd WITH KEY rbukrs = gs_acd-rbukrs gjahr = gs_acd-gjahr belnr = gs_acd-belnr docln = gs_acd-docln. IF sy-subrc EQ 0. ENDIF. ENDLOOP. GET TIME STAMP FIELD lv_current2. "-----------------------------@斌将军-----------------------------
结果:
2.3、老语法READ二分查找
"-----------------------------@斌将军----------------------------- GET TIME STAMP FIELD lv_current1. CLEAR:lv_index. SORT lt_acd BY rbukrs gjahr belnr docln. LOOP AT gt_acd INTO gs_acd. READ TABLE lt_acd INTO ls_acd WITH KEY rbukrs = gs_acd-rbukrs gjahr = gs_acd-gjahr belnr = gs_acd-belnr docln = gs_acd-docln BINARY SEARCH. IF sy-subrc EQ 0. lv_index = lv_index + 1. ENDIF. ENDLOOP. GET TIME STAMP FIELD lv_current2. "-----------------------------@斌将军-----------------------------
结果:< 1S
2.4、新语法+排序表
"-----------------------------@斌将军----------------------------- "4.测试新语法+排序表------------------------------------ lt_acd_sort = lt_acd. GET TIME STAMP FIELD lv_current1. CLEAR:lv_index. LOOP AT gt_acd INTO gs_acd. lv_index = lv_index + 1. TRY . ls_acd = lt_acd_sort[ rbukrs = gs_acd-rbukrs gjahr = gs_acd-gjahr belnr = gs_acd-belnr docln = gs_acd-docln ]. CATCH cx_sy_itab_line_not_found . MESSAGE '未找到数据' TYPE 'E' . ENDTRY. ENDLOOP. GET TIME STAMP FIELD lv_current2. "-----------------------------@斌将军-----------------------------
结果:< 1S
综上所述:不使用二分查找,则新老语法都很慢。使用二分查找或新语法搭配排序表,则速度都有非常明显的提升
2.5、READ+排序表
如果不用二分法直接READ排序表将会怎样呢,是不是和单独使用READ一个效果呢?
"-----------------------------@斌将军----------------------------- "5.测试老语法+排序表------------------------------------ DATA:lt_acd_sort TYPE SORTED TABLE OF acdoca WITH NON-UNIQUE KEY rbukrs gjahr belnr docln. lt_acd_sort = lt_acd. GET TIME STAMP FIELD lv_current1. CLEAR:lv_index. LOOP AT gt_acd INTO gs_acd. READ TABLE lt_acd_sort INTO ls_acd WITH KEY rbukrs = gs_acd-rbukrs gjahr = gs_acd-gjahr belnr = gs_acd-belnr docln = gs_acd-docln. IF sy-subrc EQ 0. lv_index = lv_index + 1. ENDIF. ENDLOOP. GET TIME STAMP FIELD lv_current2. "-----------------------------@斌将军-----------------------------
结果:< 1s
READ+排序表竟然和使用二分法查找标准表几乎一样的时间
在SAP文档中有如下介绍:
当不加BINARY SEARCH,
- 标准表将会线性搜索
- 如果搜索的关键字是排序表定义的关键字或包含这些关键字,则排序表会自动进行二进制搜索;否则进行线性搜索
- 如果搜索的关键字是哈希表定义的关键字或包含这些关键字,则哈希表使用哈希算法搜索;否则进行线性搜索
所以READ在查询排序表时,如果查询的关键字段等于或包含排序表关键字段,则使用二分查找。
当排序表的关键字段,在READ查询中未使用,则会进行线性搜索,比如:
"-----------------------------@斌将军----------------------------- DATA:lt_acd_sort TYPE SORTED TABLE OF acdoca WITH NON-UNIQUE KEY rbukrs gjahr belnr docln. lt_acd_sort = lt_acd. GET TIME STAMP FIELD lv_current1. CLEAR:lv_index. LOOP AT gt_acd INTO gs_acd. READ TABLE lt_acd_sort INTO ls_acd WITH KEY gjahr = gs_acd-gjahr "此处去掉了rbukrs作为搜索条件 belnr = gs_acd-belnr docln = gs_acd-docln. IF sy-subrc EQ 0. lv_index = lv_index + 1. ENDIF. ENDLOOP. GET TIME STAMP FIELD lv_current2. "-----------------------------@斌将军-----------------------------
结果:
当然,如果READ中未使用的关键字在整个排序表关键字的尾部,则效率仍然不受影响,毕竟READ查询的时候,用到的关键字段已经在前几列完成了排序,至于后几列如何排序,反正READ也不搜索,所以不受影响,比如:
"-----------------------------@斌将军----------------------------- DATA:lt_acd_sort TYPE SORTED TABLE OF acdoca WITH NON-UNIQUE KEY rbukrs gjahr belnr docln rldnr rrcty docnr_ld rmvct vorgn."此处在docln后添加了多个字段作为关键字 lt_acd_sort = lt_acd. GET TIME STAMP FIELD lv_current1. CLEAR:lv_index. LOOP AT gt_acd INTO gs_acd. READ TABLE lt_acd_sort INTO ls_acd WITH KEY rbukrs = gs_acd-rbukrs gjahr = gs_acd-gjahr belnr = gs_acd-belnr docln = gs_acd-docln."搜索关键字只到docln IF sy-subrc EQ 0. lv_index = lv_index + 1. ENDIF. ENDLOOP. GET TIME STAMP FIELD lv_current2. "-----------------------------@斌将军-----------------------------
结果:
以上就是本篇文档的全部内容,希望对读者有所帮助,如发现其中有误,望不吝赐教,有错必纠。
定期更文,欢迎关注
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· 葡萄城 AI 搜索升级:DeepSeek 加持,客户体验更智能
· 什么是nginx的强缓存和协商缓存
· 一文读懂知识蒸馏