• ABAP学习笔记之——第五章:内表


    内表:

    内表是可以在程序内部定义且使用的表,属于本地表。

    与C语言比较:

    C语言的数组和内表比较:

    内表是动态数组(Dynamic Data Object)

    INITIALSIZE 语句并非实际占用内存空间,而只是预约(RESERVE)内存空间。

     创建内表:

    参照局部表类型创建内表

            首先定义结构体类型,然后参照此结构体类型定义内表类型,最后再参照此内表的类型定义内表。

    参照全局表类型创建内表:

    例:

    1. *参照局部表类型创建内表
    2. TYPES: BEGIN OF s_type,"定义结构体参数类型
    3. no(6) TYPE c,
    4. name(10) TYPE c,
    5. part(16) TYPE c,
    6. END OF s_type.
    7. DATA gt_itab TYPE STANDARD TABLE OF s_type
    8. WITH NON-UNIQUE KEY no " 指定no字段唯一
    9. WITH HEADER LINE. " 用了该语法以后,itab即是一个内表,又是一个与该内表结构相同的工作区
    10. gt_itab-no = '0001'.
    11. gt_itab-name = 'enjoy abap'.
    12. gt_itab-part = 'sap team'.
    13. APPEND gt_itab.
    14. LOOP AT gt_itab.
    15. WRITE : gt_itab-no,gt_itab-name,gt_itab-part.
    16. ENDLOOP.
    17. *参照全局表定义内表
    18. DATA gt_itab TYPE SORTED TABLE OF scarr WITH UNIQUE KEY carrid.
    19. DATA gs_itab LIKE LINE OF gt_itab.
    20. SELECT * INTO TABLE gt_itab FROM scarr.
    21. LOOP AT gt_itab INTO gs_itab.
    22. WRITE: / gs_itab-carrid,gs_itab-carrname.
    23. ENDLOOP.

     内表与表头

            比较内表循环语句中带表头的内表与不带表头的内表的使用方法。使用不带表头的内表时,需通过工作区 (Work Area)编辑内表中的数据,而使用带表头的内表时,则可以直接用表的名字编辑内表值。 

    使用modify时:

     使用read时:

    汇总:

    例:

    1. *带表头和不带表头的用法区别
    2. *带表头
    3. TYPES:BEGIN OF t_str,
    4. col1 TYPE i,
    5. col2 TYPE i,
    6. END OF t_str.
    7. DATA gt_itab TYPE TABLE OF t_str WITH HEADER LINE."代表头的gt_itab内表
    8. DO 3 TIMES.
    9. gt_itab-col1 = sy-index.
    10. gt_itab-col2 = sy-index ** 2.
    11. APPEND gt_itab.
    12. ENDDO.
    13. LOOP AT gt_itab.
    14. WRITE: / gt_itab-col1,gt_itab-col2.
    15. ENDLOOP.
    16. *不带表头
    17. TYPES:BEGIN OF t_str,
    18. col1 TYPE i,
    19. col2 TYPE i,
    20. END OF t_str.
    21. DATA gt_itab TYPE TABLE OF t_str. "定义无表头的内表gt_itab
    22. DATA gs_str LIKE LINE OF gt_itab. "根据内表定义结构体作为工作区输出数据
    23. DO 3 TIMES.
    24. gs_str-col1 = sy-index.
    25. gs_str-col2 = sy-index ** 2.
    26. APPEND gs_str TO gt_itab. "向内表追加数据
    27. ENDDO.
    28. LOOP AT gt_itab INTO gs_str. "需要借助gs_str结构体输出内表
    29. WRITE : / gs_str-col1,gs_str-col2.
    30. ENDLOOP.

    内表的类型:

    标准表

            标准表是有顺次索引的树型结构内表,是利用索引查找内表行数据时易于使用的内表类型。使用 READ、MODIFY 及DELETE 语句时也会使用索引。标准表的关键字并非唯一,即标准表中不能使用 WITHUNIOUE 语句。

    例:

    1. *标准表
    2. *1定义结构体类型
    3. TYPES:BEGIN OF t_line,
    4. field1 TYPE c LENGTH 5,
    5. field2 TYPE c LENGTH 4,
    6. field3 TYPE i,
    7. END OF t_line.
    8. **2定义标准表类型
    9. TYPES t_tab TYPE STANDARD TABLE OF t_line WITH NON-UNIQUE DEFAULT KEY. "default key将内表中以char类型定义的前几个字段设为关键字
    10. **3定义内表
    11. DATA gt_itab TYPE t_tab WITH HEADER LINE.
    12. gt_itab-field1 = 'enjoy'.
    13. gt_itab-field2 = 'abap'.
    14. gt_itab-field3 = 1.
    15. APPEND gt_itab. "因为定义了表头,所以这里不添加到内表也行,应为上面就是直接赋值给内表。
    16. READ TABLE gt_itab INDEX 1.
    17. WRITE : / gt_itab-field1,gt_itab-field2,gt_itab-field3.

    排序表

            标准表与排序表是索引表。其中排序表是已经按关键字排序好的内表类型。即当程序员需要保存一直以关键字排序好的结果时使用此类型。与标准表相同,其拥有索引,可以用索引或关键字查询对应的行。排序表与标准表的另一个不同点为 Uniqueness。排序表定义关键字时,可使用 WITHUNIQUE 语句,而标准表只能使用 WITH NON-UNIQUE 语句。排序表自带 BINARYSEARCH功能,因此表行数据与检索速度成反比。定义排序表时,务必明确指定 Unique/Non-unique。表已经排序,因此使用 Sort 命令会发生错误。

    例:

    1. *排序表
    2. *1定义结构体类型
    3. TYPES:BEGIN OF t_line,
    4. col TYPE c,
    5. seq TYPE i,
    6. END OF t_line.
    7. **2定义排序表类型
    8. TYPES t_tab TYPE SORTED TABLE OF t_line WITH UNIQUE KEY col.
    9. **3定义内表类型
    10. DATA gt_itab TYPE t_tab WITH HEADER LINE.
    11. gt_itab-col = 'B'.
    12. gt_itab-seq = 1.
    13. INSERT TABLE gt_itab. "若使用append会发生排序问题‘“Dump Error”
    14. gt_itab-col = 'A'.
    15. gt_itab-seq = 2.
    16. INSERT TABLE gt_itab.
    17. CLEAR gt_itab. "清空的是表头的数据
    18. READ TABLE gt_itab INDEX 2.
    19. WRITE : / gt_itab-col,gt_itab-seq.

    哈希表

            哈希表没有顺次索引,只能用哈希值计算出的 Key 值进行检索。检索速度与内表的数据无关,始终是相同的。哈希值用于直接读取哈希算法算出的内存地址中存储的数据。哈希表定要设定为 Unique 形式。

            哈希表的内表不存在索引,因此不能使用 READ TABLE~INDEX 语句。需使用 READ TABLE~WITHTABLE KEY或WITH KEY 语,才能访问内表数据。

    例:

    1. *哈希表(一定要设成UNIQUE形式)
    2. **1定义结构体
    3. TYPES:BEGIN OF t_line,
    4. col TYPE c,
    5. seq TYPE i,
    6. END OF t_line.
    7. **2定义哈希表类型
    8. TYPES t_tab TYPE HASHED TABLE OF t_line WITH UNIQUE KEY col.
    9. **3定义内表
    10. DATA gt_itab TYPE t_tab WITH HEADER LINE.
    11. gt_itab-col = 'B'.
    12. gt_itab-seq = 1.
    13. INSERT TABLE gt_itab.
    14. gt_itab-col = 'A'.
    15. gt_itab-seq = 2.
    16. INSERT TABLE gt_itab.
    17. CLEAR gt_itab.
    18. READ TABLE gt_itab WITH TABLE KEY col ='A'.
    19. WRITE : / gt_itab-col,gt_itab-seq.

     比较内表执行速度

     二分查找:

    二分查找再不同类型的内表的查询速度:

     测试哈希表速度:

    内表命令:

    内表赋值:

    内表与其他变量一样,也可用 MOVE 语句进行赋值。要注意的是带表头的内表以下面的的方法赋值时只会复制表头中的数据。

    带表头的内表表头与内表的名字相同。使用符号“D”区分表头与表体。中括号“[]”指的是带表头内表的表体。即带表头的内表名字指表头,不带表头的内表名字指表体。因此,在例题中根据是否带表头的情况,分别使用了 MOVE gt_itabll TO gt_itab2 语句。

    例:

    1. *内表赋值
    2. TYPES:BEGIN OF t_line,
    3. col1 TYPE i,
    4. col2 TYPE i,
    5. END OF t_line.
    6. DATA: gt_itab1 TYPE STANDARD TABLE OF t_line WITH HEADER LINE,
    7. gt_itab2 TYPE STANDARD TABLE OF t_line,
    8. gs_wa like LINE OF gt_itab2.
    9. DO 5 TIMES.
    10. gt_itab1-col1 = sy-index.
    11. gt_itab1-col2 = sy-index ** 2.
    12. insert TABLE gt_itab1.
    13. ENDDO.
    14. move gt_itab1[] to gt_itab2."[]指的是代表头内表的表体
    15. LOOP AT gt_itab2 into gs_wa.
    16. WRITE : / gs_wa-col1,gs_wa-col2.
    17. ENDLOOP.

    内表初始化:

    带表头和不带表头的区别:

    例:

    1. *内表初始化
    2. DATA:BEGIN OF gs_line,
    3. col1 TYPE i,
    4. col2 TYPE c,
    5. END OF gs_line.
    6. DATA: gt_itab like STANDARD TABLE OF gs_line.
    7. gs_line-col1 = 1.
    8. gs_line-col2 = 'A'.
    9. insert gs_line into TABLE gt_itab.
    10. REFRESH gt_itab. "情况表内数据,但无法释放空间
    11. *free gt_itab. "释放空间
    12. *clear gt_itab. "清空表体
    13. IF gt_itab is INITIAL. "如果gt_itab被初始化了,就执行下面的语句
    14. WRITE : 'Internal table have no data.'.
    15. free gt_itab. "初始化后删除内存空间
    16. ENDIF.

    Clear:

    返回(Release)内存空间。但不删除刚开始要求的内存容量信息。如果是带表头的内表,则下面语句只删除内表的表头。而不带表头的内表删除的是表体。

    REFRESH :

    语句只删除表内数据,无法删除内存空间,若想释放内存空间需使用FREE 语句。

    综上所述,CLEAR 语句删除内表数据的同时释放了内存空间,相反 REFRESH 语句只能删除内表数据。若使用了 REFRESH 语句,则有必要使用 FREE 语句释放内存。

    内表排序

    作用在标准表和哈希表上:

    例:

    1. *内表排序
    2. DATA:BEGIN OF gs_line,
    3. col1 TYPE c,
    4. col2 TYPE i,
    5. END OF gs_line.
    6. DATA gt_itab LIKE STANDARD TABLE OF gs_line WITH NON-UNIQUE KEY col1.
    7. gs_line-col1 = 'B'.
    8. gs_line-col2 = 3.
    9. APPEND gs_line TO gt_itab.
    10. gs_line-col1 = 'C'.
    11. gs_line-col2 = 4.
    12. APPEND gs_line TO gt_itab.
    13. gs_line-col1 = 'A'.
    14. gs_line-col2 = 2.
    15. APPEND gs_line TO gt_itab.
    16. gs_line-col1 = 'A'.
    17. gs_line-col2 = 1.
    18. APPEND gs_line TO gt_itab.
    19. SORT gt_itab.
    20. PERFORM write_data.
    21. SORT gt_itab BY col1 col2.
    22. PERFORM write_data.
    23. SORT gt_itab BY col1 DESCENDING col2 ASCENDING.
    24. PERFORM write_data.
    25. FORM write_data.
    26. LOOP AT gt_itab INTO gs_line.
    27. WRITE: / gs_line-col1,gs_line-col2.
    28. ENDLOOP.
    29. ULINE.
    30. ENDFORM.

    指定字段:

    内表属性:

    LINES 返回内表包含的数据件数,OCCURS 返回内表的初始大小。另外,KIND 返回内表的类型,其中 T代表标准表,S 代表排序表, 代表哈希表。在这几种内表属性选项中最常用的是 LINES。

    例:

    1. *内表属性
    2. DATA:BEGIN OF gs_line,
    3. col1 TYPE c,
    4. col2 TYPE i,
    5. END OF gs_line.
    6. DATA gt_itab LIKE STANDARD TABLE OF gs_line INITIAL SIZE 10.
    7. DATA: gv_line TYPE i.
    8. DO 20 TIMES.
    9. gs_line-col1 = sy-index.
    10. gs_line-col2 = sy-index * 2.
    11. INSERT gs_line INTO TABLE gt_itab.
    12. ENDDO.
    13. DESCRIBE TABLE gt_itab LINES gv_line. "lines返回内表包含的数据件数
    14. WRITE: / 'internal table line is :',gv_line.

     追加数据

    利用insert

    可利用 INSERT 语追加多条数据,但是 Itab1 与Itab2 表类型要相同。

    例:

    1. *利用insert追加数据
    2. data:begin of gs_line,
    3. col1 type c,
    4. col2 type i,
    5. end of gs_line.
    6. DATA gt_itab1 LIKE STANDARD TABLE OF gs_line
    7. WITH NON-UNIQUE KEY col1.
    8. DATA gt_itab2 LIKE SORTED TABLE OF gs_line
    9. WITH NON-UNIQUE KEY col1.
    10. gs_line-col1 = 'B'.
    11. gs_line-col2 = 1.
    12. INSERT gs_line INTO TABLE gt_itab1.
    13. gs_line-col1 = 'A'.
    14. gs_line-col2 = 2.
    15. INSERT gs_line INTO TABLE gt_itab1.
    16. gs_line-col1 = 'C'.
    17. gs_line-col2 = 3.
    18. INSERT gs_line INTO TABLE gt_itab1.
    19. *INSERT LINES OF gt_itab1 INTO TABLE gt_itab2.
    20. INSERT LINES OF gt_itab1 FROM 1 TO 2 INTO TABLE gt_itab2. "下标从一开始
    21. LOOP AT gt_itab2 INTO gs_line.
    22. WRITE: / gs_line-col1,gs_line-col2.
    23. ENDLOOP.
    24. ********************************************************************************
    25. *利用append追加数据
    26. data:begin of gs_line,
    27. col1 type c,
    28. col2 type i,
    29. end of gs_line.
    30. DATA gt_itab LIKE STANDARD TABLE OF gs_line
    31. WITH NON-UNIQUE KEY col1.
    32. DATA gt_temp LIKE STANDARD TABLE OF gs_line WITH NON-UNIQUE KEY col1.
    33. gs_line-col1 = 'B'.
    34. gs_line-col2 = 1.
    35. APPEND gs_line TO gt_itab.
    36. gs_line-col1 = 'A'.
    37. gs_line-col2 = 2.
    38. APPEND gs_line TO gt_itab.
    39. gs_line-col1 = 'A'.
    40. gs_line-col2 = 3.
    41. APPEND gs_line TO gt_itab.
    42. gs_line-col1 = 'C'.
    43. gs_line-col2 = 4.
    44. APPEND gs_line TO gt_itab.
    45. APPEND LINES OF gt_itab TO gt_temp.
    46. APPEND LINES OF gt_itab FROM 1 TO 2 TO gt_temp.
    47. LOOP AT gt_temp INTO gs_line.
    48. WRITE : / gs_line-col1,gs_line-col2.
    49. ENDLOOP.
    50. **********************************************************
    51. *append initial line 创建一个空表后追加数据
    52. DATA:BEGIN OF gs_line,
    53. col1 TYPE c,
    54. col2 TYPE i,
    55. END OF gs_line.
    56. DATA gt_itab LIKE TABLE OF gs_line INITIAL SIZE 2.
    57. gs_line-col1 = 'C'.
    58. gs_line-col2 = 1.
    59. APPEND gs_line to gt_itab SORTED BY col1.
    60. gs_line-col1 = 'A'.
    61. gs_line-col2 = 2.
    62. APPEND gs_line to gt_itab SORTED BY col1.
    63. gs_line-col1 = 'B'.
    64. gs_line-col2 = 3.
    65. APPEND gs_line to gt_itab SORTED BY col1.
    66. LOOP AT gt_itab into gs_line.
    67. WRITE: / gs_line-col1,gs_line-col2.
    68. ENDLOOP.

    利用索引追加

    利用Index 语句可以在 Index 指定的位置追加一条数据。此方法不适用于哈希表。语句执行成功,系统变量 SY-SUBRC 返回0,同时系统变量 SY-TABIX 返回索引值。

    不同内表追加数据:

    标准表

    -追加数据到内表最后一行。

    与APPEND语句有相同的效果

    排序表

    按照内表排序好的顺序追加数据。

    若是关键字并非唯一(Non-UNIOUE KEY)的类型,重复的数据会追加到相同数据的上行中。

    -哈希表

    按照表关键字的哈希索引顺序追加数据

    Append:

    语法与insert一致

    不同内表追加数据:

    标准表

    将数据追加到内表最后一行

    可以利用 SORTED BY 选项,以关键字为基准按照降序(DESCENDING)进行排序

    排序表

    排序表是有序表,需按照排好的顺序追加数据,否则会发生 Dump Error。

    哈希表

    -不能使用 APPEND 语句。

    APPEND INITIAL LINE

    使用SORTED BY 语,会自动以字段f为基准降序(DESCENDING)排序后追加数据此语句只适用于标准表,另外还需用 INITIAL SIZE 语指定大小。

    Collect:

    使用 COLLECT 语句可以合计内表中数字类型的字段。

    除了关键字以外的数据都需要是数字类型(f、i、p)。执行 COLLECT 语句,当存在相同关键字的数据时,合计数字类型的字段,不存在相同关键字的数据时,直接追加数据。不存在关键字的内表,则会把 CHAR 类型的字段作为关键字执行相同的操作。内表中若存在以CHAR 类型的 carrid 与 connid为基准的相同数据,则会以关键字作为基准合计数字类型的字段 seatsmax 值。

    例:

    1. *COLLECT语句
    2. DATA:BEGIN OF gs_line,
    3. col1(3) TYPE c,
    4. col2(2) TYPE n,
    5. col3 TYPE i,
    6. END OF gs_line.
    7. DATA gt_itab LIKE STANDARD TABLE OF gs_line
    8. WITH NON-UNIQUE KEY col1 col2.
    9. gs_line-col1 = 'AA'.
    10. gs_line-col2 = '17'.
    11. gs_line-col3 = 660.
    12. COLLECT gs_line INTO gt_itab.
    13. gs_line-col1 = 'AL'.
    14. gs_line-col2 = '34'.
    15. gs_line-col3 = 220.
    16. COLLECT gs_line INTO gt_itab.
    17. gs_line-col1 = 'AA'.
    18. gs_line-col2 = '17'.
    19. gs_line-col3 = 280.
    20. COLLECT gs_line INTO gt_itab.
    21. LOOP AT gt_itab INTO gs_line.
    22. WRITE: / gs_line-col1,gs_line-col2,gs_line-col3.
    23. ENDLOOP.

     修改内表数据:

    Modify

    利用如下语句,即以关键字为基准修改内表行数据。内表关键字并非唯一,即存在重复数据时,执行 MODIFY 语句会修改第一条数据。

    例:

    1. *修改内表数据MODIFY
    2. DATA:BEGIN OF gs_line,
    3. carrid TYPE sflight-carrid,
    4. carrname TYPE scarr-carrname,
    5. fldate TYPE sflight-fldate,
    6. END OF gs_line.
    7. DATA gt_itab LIKE TABLE OF gs_line.
    8. SELECT carrid connid INTO CORRESPONDING FIELDS OF TABLE gt_itab
    9. FROM sflight.
    10. LOOP AT gt_itab INTO gs_line.
    11. AT NEW carrid.
    12. SELECT SINGLE carrname INTO gs_line-carrname
    13. FROM scarr WHERE carrid = gs_line-carrid.
    14. MODIFY gt_itab FROM gs_line INDEX sy-tabix TRANSPORTING carrname.
    15. ENDAT.
    16. WRITE: / gs_line-carrid,gs_line-carrname.
    17. ENDLOOP.

    Where:

     

    索引:

    利用索引可以修改对应行的值。因为使用索引,所以只能用于标准表与排序表。在 LOOP语句中可以省略INDEX 选项,此时会修改内表当前索引行数据。

    删除数据(与修改数据类似,不再演示)

  • 相关阅读:
    【ARM 安全系列介绍 1 -- 奇偶校验与海明码校验详细介绍】
    出差学小白知识No6:LD_PRELOAD变量路径不对找不到库文件
    贝锐蒲公英客户端6.0发布,异地组网更快、更简单
    Java Object类简介说明
    强化学习(DQN)
    LeetCode·701.二叉搜索树中的插入操作·递归
    【Python零基础入门篇 · 40】:内置模块的使用二:pyinstaller模块(打包py文件以及更换图标)、hashlib模块(加密)
    stable diffusion实践操作-大模型介绍-SDXL1大模型
    私募基金CRM客户关系管理系统软件开发应该具备的功能清单
    玩转SpringBoot:动态排除Starter配置,轻松部署
  • 原文地址:https://blog.csdn.net/yishangbing/article/details/128055249