内表
老式的内表类型定义
老式内表只有标准内表一种,使用OCCURS选项来定义了标准内表,这是ABAP3.0之前的定义内表的做法了,在新版的ABAP不建议使用,因为在新的版本中有三种内表类型(标准、排序、哈希)。
TYPES OCCURS .
内表中行的数据类型在中指定。要指定行的数据类型,可以使用TYPE或LIKE参数。
基于基本类型内表类型
"如果去掉了OCCURS则表示是普通类型而不是内表类型了TYPESvectorTYPE i OCCURS10."如果要带隐藏表头则一定要加上WITH HEADER LINE,否则默认没有,而且只能在声明内表变量时加,而不能在上面定义内表类型时加DATAvectorTYPEvectorWITH HEADER LINE.
vector= 1.APPENDvector.
上面的TYPES与下面语句等效:
TYPESvectorTYPE STANDARD TABLE OF iWITH NON-UNIQUE DEFAULT KEYINITIAL SIZE10.
本示例创建内表数据类型vector,其行包含基本类型I字段。
注:WITH HEADER LINE只能与DATA关键字一起使用,而不能与TYPES一起使用,这也就是说,只有在分配了存储空间时才有隐藏工作区这一说,在定义内表类型时是没有的。
下面这样也可以:
TYPESvectorTYPE i.DATAvectorTYPEvectorOCCURS0WITH HEADER LINE.vector=1.APPENDvector.
基于结构体类型内表类型
"由于没有加occurs选项,所以定义的是一结构类型TYPES:BEGIN OFline,
column1TYPE i,column2TYPE i,column3TYPE i,END OFline."定义一内表类型而不是普通类型TYPESitabTYPElineOCCURS10.
本示例创建内表数据类型itab,其行与字段串line结构相同。
特别注意,上面代码不能简单的写成如下形式,否则编译出错:
TYPES:BEGIN OFitabOCCURS10,column1TYPE i,column2TYPE i,column3TYPE i,END OFitab.
即使用TYPES关键字定义内表类型时,不允许直接在结构类型(在简单的类型后面又可以,如最上面的示例所示)后面加上OCCURS选项来将原来为结构类型转换成内表类型,需要像前面一样间接定义,但DATA关键字是可以的,这种语法规则非常特别。
老式的内表对象创建
参照现有内表类型或内表对象来创建
DATA [WITH HEADER LINE].
注:必须是已存在的内表数据类型或内表数据对象(内表类型时使用TYPE、内表对象使用LIKE)
TYPES type TYPE i OCCURS10.DATAvectorTYPE type WITH HEADER LINE.
参照现有结构类型或结构对象来创建
DATA OCCURS [WITH HEADER LINE].
注:可以是已存在的结构类型或结构对象(结构类型时使用TYPE、结构对象使用LIKE),当然也可以不是结构类型,而是内表类型或基本类型都可以:
TYPEStypeTYPE i.DATAvectorTYPE type OCCURS0WITH HEADER LINE.
两种内表对象等效创建
本示例介绍如何采用两种不同的步骤创建同一内表。
TYPESvector_typeTYPEiOCCURS10.DATAvectorTYPEvector_typeWITHHEADERLINE.
通过直接在DATA语句中使用OCCURS选项创建与上面完全一样的数据类型VECTOR:
DATAvectorTYPEiOCCURS10WITHHEADERLINE."DATA vector TYPE i OCCURS 10表示vector是一个内表而不是类型I的变量
OCCURS的作用就是将普通类型转换为内表类型
l要创建既不引用现有对象,也不引用现有行结构的内表数据对象
DATA:BEGIN OFOCCURS,,...end of.
该语句会默认创建一个表头。相当于:
DATAitabTYPESTANDARDTABLEOFlineTypeWITHNON-UNIQUEDEFAULTKEYINITIALSIZEnWITHHEADERLINE.
本示例会自动创建默认表格工作区域ITAB:
DATA:BEGINOFitabOCCURS10,
column1TYPEi,
column2TYPEi,
column3TYPEi,ENDOFitab.
但下面这种方式不会自动创建隐式工作区,除非在OCCURS 10后面加上选项“WITH HEADER LINE”(使用DATA...LIKE/TYPE...OCCURS时不会创建默认工作区,只有DATA: BEGIN OF ... OCCURS ...才会):
DATA:BEGINOFline,
col1TYPEi,
col2TYPEi,ENDOFline.DATAitabLIKElineOCCURS10."itab是一个内表而不是一个结构,与DATAitabLIKE standard table ofline等效
类似的还有语句:
TYPEStabTYPE|LIKElinetypeOCCURSn.
DATAitabTYPE|LIKElinetypeOCCURSn[WITHHEADERLINE].
相当于:
TYPES|DATAitabTYPE|LIKESTANDARDTABLEOFlinetypeWITHNON-UNIQUEDEFAULTKEYINITIALSIZEn
[withheaderline]."该选项只适用于DATA关键字,不能与TYPES一起使用
上述两种形式均只适用于创建标准表,因为在旧的SAP版本中,标准表是唯一的内表类型。
带默认表头的内表的行类型不能是内表
如果想创建带表头行的内表,行类型不能直接是内表,但可以用内表作为组件的结构:
TYPESt1TYPEiOCCURS10.TYPESt2TYPEt1OCCURS10.
TYPESt3TYPEt2."由于t2的行类型还是内表,所以会报错:with header lne不能用于类型为内表类型时
*DATA d1 TYPE t3 WITH HEADER LINE.*DATA d1 TYPE t2 WITH HEADER LINE.
"下面这种实质上与上面DATA d1 TYPE t2 WITH HEADER LINE.语句是一样效果,所以也会报错*DATA d2 TYPE t1 OCCURS 10 WITH HEADER LINE.
"下面去掉WITH HEADER LINE就可以了DATAd2TYPEt1OCCURS10."与上面语句等效*DATA d2 TYPE t2 .
"现向内表d2中加数据时,要经过以下步骤DATAw_d1LIKELINEOFd2."d2内表的行类型,还是一个内表,以下还需进一步定义DATAw_d1_2LIKELINEOFw_d1."现在w_d1_2是一个结构对象了,该结构没有字段w_d1_2 =1.
APPENDw_d1_2tow_d1 .APPENDw_d1tod2 .
"但作为内表内部组件是没有问题的(因为此时的表头的类型是一个结构,而不是一个内表)TYPES:BEGINOFt3,
t1sTYPEt2,ENDOFt3.
"这里一定要加上occurs关键字后,才表示定义的变量是一个内表对象,否则表示一个结构对象,原因是TYPE引用的类型本身是一个结构类型,则不是一个内表类型,除非TYPE引用的类型本身是一个内表类型,则就不再需要。DATAd2TYPEt3OCCURS10WITH HEADER LINE.
DATA与WITH HEADER LINE
是否带表头需要在使用DATA定义内表对象时明确指定,如果不指定默认不会带表头的:
TYPES:BEGINOFline,
column1TYPEi,
column2TYPEi,
column3TYPEi,ENDOFline.TYPESitabTYPElineOCCURS10."定义内表对象,但不带表头DATAtab1TYPEitab."定义内表对象,带表头DATAtab2LIKEtab1WITHHEADERLINE.
新式内表的定义
TYPESdtype { {TYPEtabkindOF[REF TO] type}
| {LIKEtabkindOFdobj} }
[tabkeys]
[INITIALSIZEn].
tabkind:
...{ {[STANDARD]TABLE}
| {SORTEDTABLE}
| {HASHED TABLE}
| {ANY TABLE}
| {INDEX TABLE} }...
ANY TABLE与INDEX TABLE通用类型只用用在只能用在字段特号与形式参数中:
tabkeys:
...[WITH[UNIQUE|NON-UNIQUE]{ {KEY[primary_key[ALIASkey_name]COMPONENTS] comp1 comp2...}|{DEFAULT KEY}}]"主键索引[WITH{UNIQUE HASHED}|{UNIQUE SORTED}|{NON-UNIQUE SORTED}KEYkey_nameCOMPONENTScomp1 comp2...]..."第二索引,最多支持15个第二索引
[{WITH|WITHOUT}FURTHERSECONDARYKEYS]...
定义内表数据对象还可以直接采用ABAP字典中的内表类型,或采用字典中的结构体或透明表类型作为内表的行类型
DATAitab { {TYPE[STANDARD]|SORTED|HASHEDTABLE OF[REF TO]type}
| {LIKE[STANDARD]|SORTED|HASHEDTABLE OFdobj} }[
[WITH[UNIQUE|NON-UNIQUE]
{ {KEY[primary_key [ALIASkey_name]COMPONENTS] comp1 comp2...}
| {DEFAULT KEY} }]"主键索引
[WITH{UNIQUE HASHED}|{UNIQUE SORTED}|{NON-UNIQUE SORTED}"secondary_key1,第二索引KEYkey_nameCOMPONENTScomp1 comp2 ... ]
[WITHsecondary_key2]…"第二索引,最多支持15个第二索引
]
[INITIALSIZEn]
[WITHHEADER LINE]
[VALUE IS INITIAL]
type:可以是基本类型,如DATA:itabTYPE TABLE OF i.
REF TO:表示内表类型为引用类型(该类型内表是用来存储引用的,可指向某个内表)
INITIAL SIZE n:为内表指定初始行数。如果n为0,则会自动分配合适的行数。修改初始内存要求仅用于嵌套表,对于最外层内表没有必要,指定后反可能影响性能,所以一般不用指定。另外,该值对有特殊的作用
tabkind取值如下:
2标准表(STANDARD TABLE),系统为该表的每一行数据生成一个逻辑索引,自己内部维护着行号(Index)的编码。表的键值不唯一,且没有按照表键自动进行排序,支持通过索引访问和键访问两种方式。填充标准表时可以插入到指定位置或现在有行之后,程序对内表的寻址操作可以通过关键字或索引进行。在对表进行插入删除等操作时,各数据行在内存中的物理位置不变,系统仅重新排列各数据行的索引值。当经常用索引访问表的时候就选择标准表。
2排序表(SORTED TABLE),也有一个逻辑索引,不同之处是排序表总是按其表关键字升序排序后现进行存储,排序内表自己内部也维护着行号的编号,表的键值可以唯一或者不唯一,支持通过索引访问和键访问两种方式。如果经常使用键来访问数据,或者希望数据能够自动排序时,就用排序表。
2哈希表(HASHED TABLE),哈希表通过哈希函数生成的表键来标识和快速访问表行,哈希表中的表键没有顺序,其值在表中必须唯一,只允许通过表键来访问哈希表。寻址一个数据行的所需时间与表行数无关。如果内表非常大而且希望用主键访问,就用哈希表。
各种类型内表充许的访问方式(索引访问、关键字访问):标准内表主要是索引访问,排序内表主要是Key访问,而哈希内表只能通过Key来访问:
对于索引类型的内表,当一个行操作语句执行结束后,SY-TABIX将返回该行的索引,成功SY-SUBRC返回0。
虽然索引比使用关键字定位行要快,但在大多数情况下,我们通过关键字定位一行数据,因数据来自数据库,我们不知道数据在哪行。
使用关键字定位一行数据不同内表的效率比较如下:
2标准表,取决于表的行数,随行数线性增加。(但也可以先进行排序,再明确使用二分搜索查找)
2排序表,取决于表的行数,随行数对数级增长(系统默认就会使用二分搜索方式来查找)。
2哈希表,与行数无关,在大数据量的情况下根据关键字查询是最快的
tabkeys表主键:
如果不指定关键字(注:只有标准表可以不用指定索引类型与关键字,因为系统会给一个默认的关键字,即DEFAULTL KEY),则系统会使用默认(标准)关键字,如果指定,则有下列形式:
l如果内表行结构是结构体,则可以指定结构体中的某几个字段作为内表关键字:
...WITH[UNIQUE|NON-UNIQUE]KEYcomp1 comp2...
请注意:多个关键字的排序顺序很重要,会影响到表的排序方式
l如果内表的整个行都是由基本类型字段组成,或是由基本类型组成的结构类型字段:
...WITH[UNIQUE|NON-UNIQUE]KEYTABLE LINE|TABLE_LINE
TABLE LINE、TABLE_LINE:将表的整行作为Key,则可以使用TABLE_LINE
l如果不指定任何关键字,则可以使用默认的标准关键字,该项为默认选项:
...WITH[UNIQUE|NON-UNIQUE]DEFAULTKEY...
排序表在指定Key的类型时,可以是UNIQUE也可以是NON-UNIQUE,所以排序内表是否可以存储重复的,则就是看定义时指定的Key类型是UNIQUE还是NON-UNIQUE
标准表只能使用NON-UNIQUE(但可以省略);排序表可以用NON-UNIQUE或UNIQUE(不能省略);哈希表只能使用UNIQUE(不能省略)。
在定义内表时,可以不指关键字,此时使用默认(标准)关键字,即相当于WITH KEY DEFAULT KEY。如果定义的是STANDARD TABLE,则连WITH KEY DEFAULT KEY选项都可以省略;但如果是SORTED TABLE与HASHED TABLE,如是需要指定为DEFAULT KEY时,不能省略WITH KEY DEFAULT KEY,并且需要确保该内表里有可有作为默认Key的字段——如字符类型字段,否则不能通过编译。
在定义排序表与哈希表时,一定要指定索引类型与关键字(可以指定为WITH KEY DEFAULT KEY),否则编译通过不过。
DEFAULT KEY:默认标准Key为行结构中所有byte-type(x ,xstring, xsequence)类型与character-type(c, d, n, t, string, clike)类型的所有字段,其他一切类型都会被忽略;如果行结构中还有子结构,则该子结构中的所有前面提到的类型字段也会被抽取出来作为Key的一部分;内表类型的字段不会成为默认Key的一部分;如果没有byte-type、character-type类型字段,则默认是不会有Key,:
DATA:BEGIN OFline0OCCURS0,i TYPE i,c(1),END OFline0.DATA:BEGIN OFline1,i TYPE i,c(1),itabLIKEline0[],END OFline1.DATA:BEGIN OFline2OCCURS0,i TYPE i,c TYPEstring,line LIKEline1,END OFline2.line0-i=1.line0-c='a'.APPENDline0.line0-i=2.line0-c='b'.APPENDline0.line1-i=3.line1-c='c'.line1-itab=line0[].line2-i=4.line2-c='d'.line2-line=line1.APPENDline2.LOOP ATline2.WRITE:/ line2-i,line2-c.ENDLOOP.CLEAR:line1.line1-i=32.line1-c='c'.CLEAR:line2.line2-i=5.line2-c='d'.line2-line=line1."未设置line1-itab,但也能更新,这说明内表字段默认不会作为KeyMODIFY TABLEline2."根据关键字来修改内表WRITE:/ sy-subrc.LOOP ATline2.WRITE:/ line2-i,line2-c.ENDLOOP.
虽然数字类型字段默认(DEFUALT KEY)不作为关键字段,但可以使用KEY明确指定;在使用KEY明确指定关键字段时,如果内表行包含结构组件,还可以指定到该结构组件的某个元素作为关键字段:
TYPES:BEGIN OFline0,i TYPE i,c(1),END OFline0.TYPES:BEGIN OFline1,i TYPE i,c(1),itabTYPEline0,END OFline1.DATAitab1TYPE TABLE OFline1WITH KEY iitab.DATAitab2TYPE TABLE OFline1WITH KEY iitab-i.
使用第二索引
像数据库表一样,内表也可以创建多个索引,内表有三种类型第二索引:
2UNIQUE HASHED:哈希算法第二索引
2UNIQUE SORTED:唯一升序第二索引
2NON-UNIQUE SORTED:非唯一升序第二索引
TYPESsbook_tabTYPE STANDARD TABLEOFsbook"主索引:如果要为主索引指定名称,则只能使用预置的primary_key,"但可以通过后面的ALIAS选项来修改(注:ALIAS选项只能用于排序与哈希表)WITH NON-UNIQUE KEYprimary_key"ALIAS my_primary_keyCOMPONENTScarrid connid fldate bookid"第一个第二索引:唯一哈希算法WITHUNIQUE HASHEDKEYhash_keyCOMPONENTScarrid connid fldate bookid"第二第二索引:非唯一升序排序索引WITHNON-UNIQUE SORTEDKEYsort_keyCOMPONENTScustomid.
第二索引会影响哪些行将被处理,以及处理顺序:
2可以在READ TABLE itab, LOOP AT itab, MODIFY itab, DELETE itab内表操作语句中通过WITH [TABLE] KEY ... COMPONENTS或者USING KEY选项指定key_name来使用第二索引
2可以在INSERT itab与APPEND语句中通过USING KEY选项来使用源内表的第二索引
DATAitabTYPE HASHED TABLE OFdbtabWITH UNIQUE KEYcol1 col2..."向内表itab中添加大量的数据...READ TABLEitab"使用非主键进行搜索,搜索速度将会很慢WITH KEYcol3= ...col4= ...ASSIGNING...上面程序中定义了一个哈希内表,在读取时未使用主键,在大数据量的情况下速度会很慢,所以在搜索字段上创建第二索引:DATAitabTYPEHASHED TABLE OFdbtabWITH UNIQUE KEYcol1 col2..."为非主键创建第二索引WITHNON-UNIQUE SORTED KEYsecond_keyCOMPONENTScol3 col4..."向内表itab中添加大量的数据...READ TABLEitab"根据第二索引进行搜索,会比上面程序快WITH TABLE KEYsecond_keyCOMPONENTScol3= ...col4= ...ASSIGNING......"在循环内表的Where条件中,如果内表不是排序内表,则不会使用二分搜索,如果使用SORTED KEY,则循环时,是否会用到二分搜索?LOOP ATitabUSING KEYsecond_keywherecol3=... col4=.......ENDLOOP.
INDEX/ANY TABLE通用型内表
除上面三种标准类型外,还有,即索引表(INDEX TABLE)和任意表(ANY TABLE),一般性类型可以用于类型定义中,但不能用于声明一个内表对象,因为它并没有指明任何明确的表类型,因而系统无法确定对其操作方式。一般性类型还可以用于指明字段符号和接口参数的类型,其实际类型可能在运行期内才能够确定。
内表整体操作
内表间赋值
两个内表添加使用批量增加代替逐行
不推荐:
LOOP ATint_fligh1.APPENDint_fligh1TOint_fligh2.ENDLOOP.
推荐:
Append lines ofint_fligh1toint_fligh2.
APPEND LINES OF [FROM] [TO]TO.
APPEND LINES OF A TO B.
行类型兼容的内表可以使用“=”直接进行赋值,前提是要求行结构可转换,规则参考这里Unicode fragment view of structures。
比较内表
EQ, =, NE, <>, >=, LE, <=, GT, >, LT, <
比较标准:
先比较两个内表的行数行,如果行数多的内表就大;如果两个内表的行数相等,将会一行一行、一个字段一个字段的比较,如果字段本身是一个内表类型,则会递归比较;如果不是相等比较时,只要某行某个字段不等就会停止继续向后比较。
排序内表SORT…
可以通过内表的KEY对标准表与哈希表(按理说哈希表是不能进行排序的,但ABAP里是可以的,与Java不同)进行排序:
SORT [ASCENDING|DESCENDING] [AS TEXT] [STABLE].
SORTitab [STABLE]
{ {[ASCENDING|DESCENDING]
[AS TEXT]
[BY{comp1 [ASCENDING|DESCENDING] [AS TEXT]}
{comp2 [ASCENDING|DESCENDING] [AS TEXT]}...]}
| {[BY(otab)]} }.
该语句默认会按照内表所定义的所有关键字段(即primary table key)来进行排序(在没有使用BY(otab)的情况下),关键字段排序的先后顺序依赖于标准键在内表中的Key定义的顺序。
默认是升序。
由于排序内表具有自动排序功能,因此用SORT关键字对排序内表进行排序没有任何意义,也将会导致程序的编译错误
DATA:itabTYPEHASHED TABLEOF c WITH UNIQUE DEFAULT KEY WITH HEADER LINE.INSERT'3'INTO TABLEitab.INSERT'2'INTO TABLEitab.INSERT'1'INTO TABLEitab.LOOP ATitab.WRITE:/ itab.ENDLOOP.SORTitab.SKIP.LOOP ATitab.WRITE:/ itab.ENDL