abap 内表 条件查找_ABAP 内表 详解

本文详细介绍了ABAP中内表的类型定义,包括标准内表、排序内表和哈希内表。讲解了如何创建内表、设置表头以及条件查找。同时,强调了不同类型内表的访问方式和关键字使用规则,以及内表操作如修改、删除和循环访问的注意事项。此外,还提到了内表的第二索引和字段符号访问等高级特性。
摘要由CSDN通过智能技术生成

内表

老式的内表类型定义

老式内表只有标准内表一种,使用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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值