ABAP基础-内表

作者: 常威爆打来福 | 来源:发表于2018-10-22 18:45 被阅读20次

    1 内表概述

    内表是一种十分灵活的大批量数据管理形式,用于在程序运行期间存储多行结构先相同的数据。内表的行结构可以是一个简单类型数据,也可以是复杂的结构体甚至内表。而内表的行数是动态的,添加数据后可以循环读取每行数据或者整体操作。

    2 内表定义

    其类型定义和数据对象的声明语法 tabkind(表种类),linetype(行类型),key(表关键字)

    TYPES|DATA itab {TYPE|LIKE} tabkind
                     OF {linetype|lineobj}
                     [WITH key]
                   [INITIAL SIZE n].
    

    1.内表种类
    内表种类决定了系统内部对内表的处理已经ABAP对内表行的访问方式

    • 标准表,表类型关键字为STANDARD TABLE,系统为每一行数据生成一个逻辑索引。填充标准表时,可以将数据附加在现有行之后,也可以插入到指定的位置,程序对内表行的寻址操作可通过关键字或索引进行。对表的插入。删除等操作时,各行在内存中的位置不变,系统仅重新排列各数据行的索引值。
    • 排序表,表类型关键字为SORTED TABLE,也具有一个逻辑索引,不同的时排序表总是按其表关键字升序排序后再进行存储,其访问方式与标准表相同。
    • 哈希表,表类型关键字为HASHED TABLE,没有索引,只能通过关键字来访问。系统用哈希算法管理表中的数据,因而其寻址一个数据行的时间与表的行数无关。
    如果将内表定义或直接声明为标准表,也可以省略STANDARD关键字。除上述三种类型之外,还有一般性类型,即索引表INDEX TABLE和任意表ANY TABLE。一般类型可以用于类型定义中,但不能用于声明一个内表对象,因为它并没有指明任何明确的表类型,因而系统无法确定对其操作方式。一般类型还可以用于指明字段符号和接口参数类型,以增加这些元素的适用性,其类型实际可能在运行期内才能够确定。

    2.行结构

    内表的行可以是由任意类型ABAP数据类型组成。

    3.表关键字
    内表的表关键字在访问内表和内表排序和过程中起着相当重要的作用,在内表定义语句中使用WITH key指定表关键字,该项为可选项,如不指定,则系统会使用默认(标准)关键字;如果指定关键字,则有以下形式:

    • 如果内表行结构是结构体,则可以指定结构体中的某几个字段作为内表关键字,该字段不能是内表或者引用类型,但可以是嵌套结构体。
      ... WITH [UNIQUE | NON-UNIQUE] KEY comp1 ... compn
    • 如果内表的整行都是由基本类型字段组成,则可以把内表整行指定为表关关键字。如果内表字段本身是结构化类型,则不宜指定整行作为关键字段。
      ... WITH [UNIQUE | NON-UNIQUE] KEY TABLE LINE
    • 如果不指定任何关键字,则可以使用默认的标准关键字,该选项为默认选项
      ... WITH [UNIQUE | NON-UNIQUE] DEFAULT KEY
      扁平结构内表的默认(标准)表关键字是非数字和非内表的组件字段。例如,一个表有字段姓名(C),年龄(N),工资(P)组成,则姓名是该内表的标准关键字段。如果内表的行是单个基本类型组成,则默认关键字为整个行;如果内表行中包含有内表类型字段,则没有默认关键字。
      选项NON-UNIQUE | UNIQUE决定了内表中具有相同关键字的数据行是否可以重复出现(如果指明为UNIQUE KEY,则通过表关键字能够唯一确定内表的行,在程序中不能插入具有相同表关键字的多行数据条目),其中标准表不能用UNIQUE关键字,且无需特别指定NON-UNIQUE关键字;排序表可以用NON-UNIQUE | UNIQUE 关键字;哈希表不能用NON-UNIQUE 关键字,且必须指定UNIQUE关键字。

    4.初始化内存大小
    在内表数据定义和声明过程中,可以为内表分配初始内存大小。
    ... INITIAL SIZE n ...

    n值可以为0或者任何正数如果初始值n小于所需,系统会根据需求自动增加内存大小;如果内存过大,则会造成内存浪费;如果不指定或n值为0,程序会为内表对象分配8KB大小的内存。

    REPORT z_simple_itab.
    
    TYPES: BEGIN OF address,
             street(20) TYPE c,
             city(20)   TYPE c,
           END OF address.
    
    DATA: BEGIN OF company,
            name(20) TYPE c,
            address  TYPE address,
          END OF company.
    
    DATA itab_company  LIKE HASHED TABLE OF company WITH UNIQUE KEY name.
    
    DATA itab_company_sorted LIKE SORTED TABLE OF company WITH UNIQUE KEY name.
    

    3 内表操作

    对内表的操作分为数据行和整个内表操作两大类,行操作可以通过关键字或索引两种途径进行,但哈希表不能通过索引操作。

    1.操作内表行

    1.行访问方式

    通过关键字访问行是所有类型内表的通用操作形式;而索引操作则是通过内表内部系统索引进行的,因而不适用于哈希表,当一个操作语句执行结束后,系统变量SY-TABIX将返回该行的索引。对于所有行操作,如果访问成功,系统变量SY-SUBRC将返回0值,否则返回非0值。

    标准表 排序表 哈希表
    索引访问 允许 允许 不允许
    关键字访问 允许 允许 允许
    相同值关键字行 可重复 可重复或不可重复 不可重复
    推荐访问方式 主要通过索引 主要通过关键字 只能通过关键字
    2.工作区

    程序对内表的行操作不能直接进行,必须通过一种接口来传输,这个接口就是工作区(Work Area)。比如某程序需要从关系数据库中提取到内表各行中,必须先将数据读入工作区,然后把工作区中的数据赋给内表行。工作区必须具有和内表行一致或者可相互转化的数据结构(一般是与内表行类型相同的结构体)。
    因此在定义内表对象的同时,还需要定义一个与该内表行结构相同的工作区供程序使用,将数据写入内表时,必须首先给工作区赋值,然后在工作区添加或者插入内表。从内表中读取内容时,需要用已定位的内表行内容覆盖工作区内容,然后再从程序中使用工作区的内容。
    工作区对内表的行必须是可转换的。为了避免不一致,工作区最好与内表行有相同的数据类型,这是一种安全程序设计的原则。

    3.表头行

    ABAP为程序提供了一种简单的方法:在创建内表对象的同时可以隐式的定义一个同名工作区,这个工作区就叫做表头行或标题行,也称内表工作区。
    DATA itab ... WITH HEADER LINK ...
    创建内表时,可以通过该附加项决定内表是否带表头
    DATA itab_company LIKE TABLE OF company WITH UNIQUE KEY name WITH HEADER LINK.
    创建了带表头的内表之后,可以认为程序中存在两个数据对象,一个是内表,另一个是与内表类型相同的结构体。在所有用于操作内表的ABAP语句中,均需指定工作区。但对于带有表头行的内表,则可以忽略这一指定,系统隐式使用表头行作为工作区;不带表头行的内表没有隐式的工作区,所以要访问没有表头行的内表,必须在相应的ABAP语句中显式指定工作区。
    对于既可以操作内表,又可以操作工作区的语句来说,有时不能单独从语法上判断操作对象,需要进行逻辑分析。如果一个语句中,该名称同时可能代表内表或者同名表工作区,则需要在内表名称后加“[ ]”指明当前操作的是内表对象。itab []

    4.插入行-INSERT语句

    对于索引表,可以指定某行的索引,则新行将插入该索引所代表的行之前;对于哈希表而言,不能指定索引,系统会按照关键字将新行插入其特定位置。给内表插入行可以是单行,也可以是多行。甚至可以把整个内表的数据插入其他内表中。
    一般性插入单行的语法如下:INSERT [line INTO | INITIAL LINE INTO] TABLE itab
    但语句中增加了TABLE关键字,对于不同类型的内表,其意义和用法是有区别的:

    • 对于标准表,该形式不指定索引值,附加至表最后一行,与APPEND语句效果完全一致
    • 对于排序表,插入行不可以打乱按照关键字排序的顺序,否则插入不成功
    • 对于哈希表,插入过程中系统按照关键字对行进行定位

    可以使用INITIAL LINE INTO选项代替工作区,其效果是用行结构中各类型的初始值组成数据行添加到内表中。
    还可以将内表中部分或全部的数据行整体插入到另一个内表中
    INSERT LINES OF itab1 [FROM n1] [TO n2] INTO [TABLE] itab2 [INDEX idx]
    该语句要求两内表对象具有可以相互转换的行结构。如果不指定行数,则整个内表itab1被插入itab2中。不指定行数时,itab1可以为任意内表,itab2必须为索引表,但是如果需要指定起始行n1和终止行n2中任意一个,则两表必须都是索引表。如果itab2前TABLE指定附加项,则itab2可以是任意类型内表。

    REPORT z_simple_itab.
    DATA: BEGIN OF address,
            street(20) TYPE c,
            city(20)   TYPE c,
          END OF address.
    
    
    DATA itab_address LIKE STANDARD TABLE OF address WITH NON-UNIQUE KEY city.
    
    address-street = 'XuanWu'.
    address-city = 'Xian'.
    INSERT address INTO TABLE itab_address.
    
    address-street = 'ChangCheng'.
    address-city = 'Beijing'.
    INSERT address INTO TABLE itab_address.
    
    READ TABLE itab_address WITH TABLE KEY city = 'Xian' INTO address.
    WRITE: / address-street, address-city.
    READ TABLE itab_address INTO address INDEX 1.
    WRITE: / address-street, address-city.
    
    LOOP AT itab_address INTO address.
      WRITE: / sy-tabix, address-street, address-city.
    ENDLOOP.
    
    INSERT
    5.附加行-APPEND语句

    附加行是在已经存在的索引表中使用APPEND语句增添新行,该语句只能操作索引表。APPEND语句有两种形式,可以分别附加一或多行
    APPEND [line TO | INITIAL LINE TO] itab.
    APPEND LINES OF itab1 [FROM n1] [TO n2] TO itab2.
    附加操作不考虑是否存在标准关键字相同的行,因而可能会出现相同关键字条目。附加行之后系统字段SY-TABIX返回该附加行的索引值。

    REPORT z_simple_itab.
    DATA: BEGIN OF address,
            street(20) TYPE c,
            city(20)   TYPE c,
          END OF address.
    
    
    DATA itab_address LIKE STANDARD TABLE OF address WITH NON-UNIQUE KEY city.
    
    address-street = 'XuanWu'.
    address-city = 'Xian'.
    INSERT address INTO TABLE itab_address.
    
    address-street = 'ChangCheng'.
    address-city = 'Beijing'.
    INSERT address INTO TABLE itab_address.
    
    address-street = 'ChangJiang'.
    address-city = 'Wuhan'.
    append address to itab_address.
    
    
    READ TABLE itab_address WITH TABLE KEY city = 'Xian' INTO address.
    WRITE: / address-street, address-city.
    READ TABLE itab_address INTO address INDEX 1.
    WRITE: / address-street, address-city.
    
    LOOP AT itab_address INTO address.
      WRITE: / sy-tabix, address-street, address-city.
    ENDLOOP.
    
    append
    6.聚集附加-COLLECT语句

    由于在索引表中行与行之间数据具有可重复性,如果使用APPEND语句附加,则多个具有相同表关键字段值的数据行可以同时出现在同一个内表中。如果期望相同关键字段值的数据行不能重复出现,应该使用COLLECT语句根据表关键字附加行。
    COLLECT line INTO itab.
    使用COLLECT语句的前提条件是所附加的内表必须具有扁平结构(组件中不可包含内表),语句中指定的工作区必须与内表的行类型兼容,而且所有的非表关键字段必须是数字类型。
    操作时,系统将检查工作区的标准字段值与已经存在于内表的数据行是否相同。如果不同,COLLECT语句与APPEND语句类型;如已经存在相同表关键字值的行,COLLECT语句不附加新行,而是将工作区数字字段的内容累加到已有数据行中数字字段内容之上。操作成功之后,系统字段SY-TABIX包含处理过的行索引。

    REPORT z_simple_itab.
    DATA: BEGIN OF address,
            street(20) TYPE c,
            city(20)   TYPE c,
          END OF address.
    
    
    DATA itab_address LIKE STANDARD TABLE OF address.
    
    address-street = 'XuanWu'.
    address-city = 'Xian'.
    INSERT address INTO TABLE itab_address.
    
    address-street = 'ChangCheng'.
    address-city = 'Beijing'.
    INSERT address INTO TABLE itab_address.
    
    address-street = 'ChangJiang'.
    address-city = 'Wuhan'.
    APPEND address TO itab_address.
    
    address-street = 'ChangJiang'.
    address-city = 'Wuhan'.
    COLLECT address INTO itab_address.
    
    LOOP AT itab_address INTO address.
      WRITE: / sy-tabix, address-street, address-city.
    ENDLOOP.
    
    COLLECT
    7.读取行-READ语句

    如果只需要读取内表中的某一行,而不是循环读取内表,可以使用READ语句。该语句有多种用法,对索引表利用索引读取单行,语法如下:
    READ TABLE itab [INTO wa | ASSIGNING <fs>] INDEX idx.
    如果找到有指定索引的条目,则视为成功读取,SY-TABIX返回该行的索引。一般来说,用READ语句对内表进行读取后,在访问目标工作区之前,要先用SY-SUBRC字段查看一下读取成功与否,否则可能得到错误的结果(例如使用工作区尚未清空的前次操作内容)。
    使用READ语句通过关键字读取内表行可以用于任何类的内表,且需要在内表名称前指定TABLE关键字。
    READ TABLE itab FROM key [INTO wa | ASSIGNING <fs>].
    在下述格式中,语句指定内表中所有表关键字段的值,目标结构在操作前可以为任何值,内表数据行整体读入目标区域。
    READ TABLE itab WITH TABLE KEY k1 = f1 ... kn = fn [INTO wa|ASSIGNING <fs>].
    此外,还可以在语句中自行指定读取关键字
    READ TABLE itab WITH KEY k1 = f1 ... kn = fn [ INTO wa | ASSIGNING <fs>].
    语句中的KEY列表可以为任意表字段,不一定时表关键字。

    8.修改行-MODIFY语句

    使用索引更改内表的语法
    MODIFY itab [FROM wa] [INDEX idx] [TRANSPORTING f1 f2...]
    使用关键字更改内表可用于所有类型的内表
    MODIFY TABLE itab FROM wa [TRANSPORTING f1 f2...]
    工作区wa。如果只希望更新部分字段的值,可以使用TRANSPORTING选项。
    使用MODIFY语句的WHERE选项,还可以同时修改多行数据,修改之后,所有满足条件的行都被工作区的内容替换。
    MODIFY itab FROM wa TRANSPORTING f1 f2 ... WHERE cond.
    只有关键字段才可以出现在fn中。

    REPORT z_simple_itab.
    DATA: BEGIN OF address,
            street(20) TYPE c,
            city(20)   TYPE c,
          END OF address.
    
    
    DATA itab_address LIKE STANDARD TABLE OF address.
    
    address-street = 'XuanWu'.
    address-city = 'Xian'.
    INSERT address INTO TABLE itab_address.
    
    address-street = 'ChangCheng'.
    address-city = 'Beijing'.
    INSERT address INTO TABLE itab_address.
    
    address-street = 'ChangJiang'.
    address-city = 'Wuhan'.
    COLLECT address INTO itab_address.
    
    address-street = 'HUANGHE'.
    address-city = 'lanzhou'.
    modify itab_address from address index 1.
    
    
    LOOP AT itab_address INTO address.
      WRITE: / sy-tabix, address-street, address-city.
    ENDLOOP.
    
    MODIFY
    9.删除行-DELETE语句

    对于索引表,语法如下DELETE itab INDEX idx.
    该语句删除成功后,下面所有行的索引减1,并将SY-SUBRC 返回0;如果不存在索引为idx的行,则SY-SUBRC返回4。
    使用关键字删除,语法如下:
    DELETE TABLE itab FROM wa.
    DELETE TABLE itab WITH TABLE KEY k1 = f1 ... kn = fn.
    按照条件或者索引值删除一组选定行的语法如下
    DELETE itab [FROM n1] [TO n2] [WHERE <condition>].

    10.循环处理-LOOP语句

    LOOP语句可以逐行读取表内容,其循环顺序为内表中数据行的排列次序。

    LOOP AT itab <result> [FROM n1] [TO n2]
                        [WHERE <condition>]
            <statement block>
    ENDLOOP
    

    在循环结束之后,如果至少读取了一行,则系统字段SY-SUBRC返回0,否则返回4。
    其中<result>选项有下列几种形式

    • INTO wa 指定目标工作区wa,但如果内表有表头行,则可以忽略INTO选项
    • ASSIGNING <fs> 指定字段符号<fs> ,可以将该内表数据行分配给<fs>
    • TRANSPORTING NO FIELDS 循环时不进行任何数据读取操作。

    2.操作整个内表

    1.数据行排列

    内表排序使用SORT语句

    SORT itab [ASCENDING | DESCENDING] [AS TEXT] [STABLE]
              [ BY f1 [ASCENDING | DESCENDING]  [AS TEXT]
               ...
              fn [ASCENDING | DESCENDING ] [AS TEXT]. ]
    

    如果不使用BY选项,则根据表关键字对内表itab进行排序。如果自行定义排序关键字,需要使用by选项指定组件字段对数据进行排序。
    ASCENDING | DESCENDING选择用来指定升/降序,如不指定,默认为所有字段升序排列。
    AS TEXT将影响字符字段的排序方式。如果没有AS TEXT选项,则系统按字符平台相关内部编码进行排序。
    STABLE可以保持前后不需要改变的数据行的相对顺序。

    2.控制级操作

    ABAP为内表提供了各种循环过程中的控制级操作,以实现一组数据的总计,缩进,颜色改变和格式控制。控制级操作语句关键字为AT,该关键字后面接自定义的语句块,用ENDAT结束该块。

    AT level
      <statement block>
    ENDAT.
    

    该语句只能在LOOP语句内部使用,其中行条件level有下列选项

    • FIRST 当前循环内表的第一行
    • LAST 当前循环内表的最后一行
    • NEW f 行组的开头,行组指的是字段f和f前面(即左边)的全部字段,如果行组中的任何字段内容不同于上一行,执行语句块中内容
    • END Of f 行组的结尾,如果下一行行组中的任何字段内容不同于上一行,执行语句块中的内容。
    3.初始化内表

    初始化内表的作用的清空内表所有的数据行,将内表恢复到填充或赋值之前的状态。
    对内表进行初始化,可以使用CLEAR语句CLEAR itab.该语句将内表重置为填充前的状态,这意味着该内表将不包含任何行。然后如果内表有表头行,会同时清空表数据行和表头行的内容。如果只希望初始化内表本身,保留表头行的内容,应使用如下形式CLEAR itab[].
    还可以使用REFRESH语句确保只初始化内表本身REFRESH itab
    使用REFRESH和CLEAR初始化内表后,系统仍旧保持在内存中为内表预留空间。可以用FREE语句释放该内存FREE itab.
    使用FREE语句可以重置内表同时释放其内存,而不必先使用REFRESH和CLEAR语句。与REFRESH一样,FREE语句不重置内表工作区。
    可以先使用... itab IS INITIAL ... 检查内表是否为空。

    4.整体复制内表

    使用MOVE语句或"="

    5.比较内表大小

    ... itab1 <operator> itab2 ...
    其中<operator>可以视为操作符EQ, = 等。

    REPORT z_itab_example.
    *defining internal tables
    DATA: BEGIN OF address,
            street(20) TYPE c,
            city(20)   TYPE c,
          END OF address.
    
    TYPES address_tab LIKE STANDARD TABLE OF address WITH NON-UNIQUE KEY city.
    
    DATA: BEGIN OF company,
            name(25)  TYPE c,
            addresses TYPE address_tab,
          END OF company.
    
    DATA company_tab LIKE HASHED TABLE OF company WITH UNIQUE KEY name.
    
    DATA company_sorted_tab LIKE SORTED TABLE OF company WITH UNIQUE KEY name.
    
    DATA idx TYPE sy-tabix.
    * filling internal tables
    company-name = 'Jack Computer Pte Ltd'.
    
    address-street = 'Alexandra Street'.
    address-city = 'Sinagpore'.
    APPEND address TO company-addresses.
    
    address-street = 'Havelock Avenue'.
    address-city = 'New York'.
    APPEND address TO company-addresses.
    
    INSERT company INTO TABLE company_tab.
    
    CLEAR company.
    
    company-name = 'Beijing CaoYa Co. Ltd'.
    
    address-street = 'Tian An Men Square'.
    address-city = 'Beijing'.
    APPEND address TO company-addresses.
    
    address-street = 'Nanjing Road'.
    address-city = 'Shang Hai'.
    APPEND address TO company-addresses.
    
    address-street = 'Wangfujing Street'.
    address-city = 'Beijing'.
    APPEND address TO company-addresses.
    
    INSERT company INTO TABLE company_tab.
    
    *reading internal tables
    READ TABLE company_tab WITH TABLE KEY name = 'Jack Computer Pte Ltd' INTO company.
    WRITE: / company-name.
    LOOP AT company-addresses INTO address.
      WRITE: / sy-tabix, address-street, address-city.
    ENDLOOP.
    
    *modifying Internal tables
    
    address-street = 'Tian He Road'.
    address-city = 'Beijing'.
    
    READ TABLE company_tab WITH TABLE KEY name = 'Beijing CaoYa Co. Ltd' INTO company.
    
    READ TABLE company-addresses TRANSPORTING NO FIELDS WITH TABLE KEY city = address-city.
    
    idx = sy-tabix.
    
    MODIFY company-addresses FROM address INDEX idx.
    MODIFY TABLE company_tab FROM company.
    
    *moving and sorting internal tables
    
    company_sorted_tab = company_tab.
    
    LOOP AT company_sorted_tab INTO company.
      WRITE / company-name.
      SORT company-addresses.
      LOOP AT company-addresses INTO address.
        WRITE: / sy-tabix, address-street, address-city.
      ENDLOOP.
    ENDLOOP.
    
    内表操作
    6.Extract Datasets

    Extrat是sap中除内表之外的另一种大量内存处理方式,允许用户动态的存储并排序结构化数据,同时通过循环处理。在每一个ABAP程序中,最多只能创建一个未命名的ABAP Extract。
    与内表类型,Extract的数据行数可以是动态的,但较之内表固定行结构不同,Extract中的列数目也是可变的。
    Extract的行结构分配语法如下FIELD-GROUPS fg.字段组fg的具体结构则通过下述语句在程序中动态生成INSERT f1 f2 ... INTO fg.其中f1,f2是程序中定义的内部全局对象,其类型需为扁平结构。
    填充Extract的语法格式为EXTRACT fg.Extract可以使用SORT语句进行排序。

    REPORT z_extract.
    DATA: f1 TYPE i,
          f2 TYPE i.
    
    FIELD-GROUPS header.
    INSERT f1 f2 INTO header.
    
    DO 10 TIMES.
      f1 = sy-index.
      f2 = sy-index ** 2.
      EXTRACT header.
    ENDDO.
    
    SORT DESCENDING.
    LOOP.
      WRITE: / f1, f2.
    ENDLOOP.
    
    Extract

    相关文章

      网友评论

        本文标题:ABAP基础-内表

        本文链接:https://www.haomeiwen.com/subject/ceswzftx.html