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.
"-----------------------------@斌将军-----------------------------

结果:

以上就是本篇文档的全部内容,希望对读者有所帮助,如发现其中有误,望不吝赐教,有错必纠。

定期更文,欢迎关注

  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值