ABAP 内表 详解

老式的内表类型定义... 214

基于基本类型内表类型... 214

基于结构体类型内表类型... 215

老式的内表对象创建... 215

参照现有内表类型或内表对象来创建... 215

参照现有结构类型或结构对象来创建... 215

两种内表对象等效创建... 215

带默认表头的内表的行类型不能是内表... 216

DATAWITH HEADER LINE. 217

新式内表的定义... 217

使用第二索引... 221

INDEX/ANY TABLE通用型内表... 222

内表整体操作... 222

内表间赋值... 222

比较内表... 222

排序内表SORT….. 223

根据指定的字段进行排序 BY. 223

接字母顺序(字符语义)进行排序AS TEXT. 224

稳定排序STABLE. 227

DESCRIBETABLE获取内表属性... 227

获取内表数据行数 Lines()227

内表行操作... 227

单行操作... 227

多行操作... 228

适用所有类型内表的行操作... 228

INSERT向表中插入行... 228

插入一行... 228

插入多行FROM…TO.. 229

COLLECT合并... 229

READ 读取行... 230

指定搜索关键字段... 231

使用表关键字段进行读取... 231

使用其他关键字段进行读取... 232

以行首字段搜索... 233

USING KEY.. 233

<result>指定额外处理选项... 233

指定工作区... 233

COMPARING比较读取的单行内容... 234

TRANSPORTING读取一行的部分字段... 234

使用字段符号... 235

MODIFY 修改行... 236

修改单条记录(TABLE KEY... 236

修改多条记录(WHERE... 237

DELETE 删除行... 237

循环中插入或删除行... 237

删除单行(TABLE KEY... 238

删除多行(WHERE... 238

删除邻近重复行(ADJACENT DUPLICATE... 239

LOOP在循环中处理行... 240

SUM.. 240

AT. 241

适用索引表的行操作... 246

APPEND 附加行... 246

附加单行... 246

附加多行FROM… TO.. 247

以排序方式附加... 248

APPEND …SORTED BY….. 248

USING KEY. 249

INSERT插入到指定的索引位置... 250

插入单行... 250

插入多行FROM…TO.. 251

READ读取指定索引位置上的行... 251

在索引表中进行二分搜索... 252

在内表中搜索字符串... 253

MODIFY修改指定索引位置上的行... 254

修改单行... 254

修改当前循环行…USING KEY loop_key….. 254

使用WRITE TO进行修改... 255

DELETE删除指定索引位置上的行... 256

删除单行... 256

循环中删除行…USING KEY loop_key….. 256

删除多行... 258

在循环使用FROM…TO限制行的读取范围... 259

使用字段符号进行访问... 259

使用表头替换工作区... 260

实用的Ranges内表

内表

老式的内表类型定义

老式内表只有标准内表一种,使用OCCURS选项来定义了标准内表,这是ABAP3.0之前的定义内表的做法了,在新版的ABAP不建议使用,因为在新的版本中有三种内表类型(标准、排序、哈希)。

 

TYPES <t><type> OCCURS <n>.

内表中行的数据类型在<type>中指定。要指定行的数据类型可以使用 TYPE  LIKE 参数。

基于基本类型内表类型

"如果去掉了 OCCURS 则表示是普通类型而不是内表类型
TYPES vector TYPE i OCCURS 10.
"如果要带隐藏表头则一定要加上WITH HEADER LINE否则默认没有而且只能在声明内表变量时加而不能在上面定义内表类型时加
DATA vector TYPE vector WITH HEADER LINE.

vector = 1.
APPEND vector.

 

上面的TYPES与下面语句等效

TYPES vector TYPE STANDARD TABLE OF i
       
WITH NON-UNIQUE DEFAULT KEY
       
INITIAL SIZE 10.

 

本示例创建内表数据类型 vector其行包含基本类型 I 字段。

 

WITH HEADER LINE只能与DATA关键字一起使用而不能与TYPES一起使用这也就是说只有在分配了存储空间时才有隐藏工作区这一说在定义内表类型时是没有的。

 

下面这样也可以

TYPES vector TYPE i.
DATA vector TYPE vector OCCURS 0 WITH HEADER LINE.
vector
= 1.
APPEND vector.

基于结构体类型内表类型

"由于没有加 occurs 选项所以定义的是一结构类型
TYPES: BEGIN OF line,
         column1
TYPE i,

         column2
TYPE i,
         column3
TYPE i,
      
END OF line.
"
定义一内表类型而不是普通类型
TYPES itab TYPE line OCCURS 10.

本示例创建内表数据类型itab,其行与字段串line结构相同。

 

特别注意,上面代码不能简单的写成如下形式,否则编译出错

TYPES: BEGIN OF itab OCCURS 10,
         column1
TYPE i,
         column2
TYPE i,
         column3
TYPE i,
      
END OF itab.

即使用TYPES关键字定义内表类型时,不允许直接在结构类型(在简单的类型后面又可以,如最上面的示例所示)后面加上 OCCURS 选项来将原来为结构类型转换成内表类型,需要像前面一样间接定义,但DATA关键字是可以的,这种语法规则非常特别。

老式的内表对象创建

参照现有内表类型或内表对象来创建

DATA <f><type> [WITH HEADER LINE].

注:<type>必须是已存在的内表数据类型或内表数据对象(内表类型时使用TYPE 、内表对象使用 LIKE

 

TYPES type TYPE i OCCURS 10.
DATA vector TYPE type WITH HEADER LINE.

参照现有结构类型或结构对象来创建

DATA <f><type> OCCURS <n> [WITH HEADER LINE].

注:<type>可以是已存在的结构类型或结构对象(结构类型时使用TYPE 、结构对象使用 LIKE),当然也可以不是结构类型,而是内表类型或基本类型都可以:

TYPES type TYPE i.
DATA vector TYPE type OCCURS 0 WITH HEADER LINE.

两种内表对象等效创建

本示例介绍如何采用两种不同的步骤创建同一内表。

TYPES vector_type TYPE i OCCURS 10.
DATA vector TYPE vector_type WITH HEADER LINE
.

通过直接在 DATA 语句中使用 OCCURS 选项创建与上面完全一样的数据类型 VECTOR

DATA vector TYPE i OCCURS 10 WITH HEADER LINE."DATA vector TYPE i OCCURS 10表示vector是一个内表而不是类型I的变量

OCCURS的作用就是将普通类型转换为内表类型

 

l  要创建既不引用现有对象,也不引用现有行结构的内表数据对象

DATA: BEGIN OF <f> OCCURS <n>,
  <component declaration>
,
 
...
end of <f>.

该语句会默认创建一个表头。相当于:

DATA itab TYPE STANDARD TABLE OF lineType
     
WITH NON-UNIQUE DEFAULT KEY

     
INITIAL SIZE n
     
WITH HEADER LINE.

 

本示例会自动创建默认表格工作区域 ITAB

DATA: BEGIN OF itab OCCURS 10,
         column1
TYPE i
,
         column2
TYPE i
,
         column3
TYPE i
,
      
END OF
itab.

 

下面这种方式不会自动创建隐式工作区除非在OCCURS 10后面加上选项WITH HEADER LINE(使用DATA...LIKE/TYPE...OCCURS时不会创建默认工作区,只有DATA: BEGIN OF ... OCCURS ...才会):

  DATA: BEGIN OF line,
          col1
TYPE i
,
          col2
TYPE i
,
       
END OF
line.
 
DATA itab LIKE line OCCURS 10 ."itab
是一个内表而不是一个结构DATA itab LIKE standard table of line
等效

 

类似的还有语句

TYPES tab TYPE|LIKE linetype OCCURS n.

DATA itab TYPE|LIKE linetype OCCURS n[WITH HEADER LINE].

相当于

TYPES|DATA itab TYPE|LIKE STANDARD TABLE OF linetype
       
WITH NON-UNIQUE DEFAULT KEY

       
INITIAL SIZE
n
[
with header line].
"
该选项只适用于DATA关键字不能与TYPES一起使用

上述两种形式均只适用于创建标准表,因为在旧的SAP版本中,标准表是唯一的内表类型。

带默认表头的内表的行类型不能是内表

如果想创建带表头行的内表,行类型不能直接是内表,但可以用内表作为组件的结构:

TYPES t1  TYPE i  OCCURS 10 .
TYPES t2 TYPE  t1  OCCURS 10
.

TYPES t3 TYPE t2.
"
由于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就可以了
DATA d2 TYPE  t1  OCCURS 10 .
"
与上面语句等效
*DATA d2 TYPE  t2 .

"现向内表d2中加数据时,要经过以下步骤
DATA w_d1 LIKE LINE OF d2."d2内表的行类型,还是一个内表,以下还需进一步定义
DATA w_d1_2 LIKE LINE OF w_d1."现在w_d1_2是一个结构对象了,该结构没有字段
w_d1_2 =
1.

APPEND w_d1_2 to w_d1 .
APPEND w_d1 to
d2 .

 

"但作为内表内部组件是没有问题的(因为此时的表头的类型是一个结构,而不是一个内表)
TYPES:BEGIN OF  t3,
  t1s
TYPE
  t2,
 
END OF
t3.

"这里一定要加上 occurs 关键字后,才表示定义的变量是一个内表对象,否则表示一个结构对象,原因是TYPE引用的类型本身是一个结构类型,则不是一个内表类型,除非TYPE引用的类型本身是一个内表类型,则就不再需要。
DATA d2 TYPE  t3  OCCURS 10  WITH HEADER LINE.

DATAWITH HEADER LINE

是否带表头需要在使用DATA定义内表对象时明确指定,如果不指定默认不会带表头的:

TYPES: BEGIN OF line,
         column1
TYPE i
,
         column2
TYPE i
,
         column3
TYPE i
,
      
END OF line
.
TYPES itab TYPE line OCCURS 10
.
"
定义内表对象,但不带表头
DATA tab1 TYPE itab.
"
定义内表对象,带表头
DATA tab2 LIKE tab1 WITH HEADER LINE.

新式内表的定义

TYPES dtype { {TYPE tabkind OF [REF TO] type}
              | {
LIKE tabkind OF
dobj} }
          [tabkeys]
            [
INITIAL SIZE n]
.

tabkind

... { {[STANDARD] TABLE}

| {SORTED TABLE}
    | {
HASHED TABLE
}
    | {
ANY TABLE
}
    | {
INDEX TABLE} }
...

ANY TABLE 与 INDEX TABLE 通用类型只用用在只能用在字段特号与形式参数中

image173

tabkeys

...[WITH[UNIQUE|NON-UNIQUE]{{KEY[primary_key[ALIAS key_name]COMPONENTS] comp1 comp2 ...}|{DEFAULT KEY}}]  "主键索引
[
WITH{UNIQUE HASHED}|{UNIQUE SORTED}|{NON-UNIQUE SORTED} KEY key_name COMPONENTS comp1 comp2 ... ] ... "第二索引,最多支持15个第二索引

[{WITH|WITHOUT} FURTHER SECONDARY KEYS ] ...

 

定义内表数据对象还可以直接采用ABAP字典中的内表类型,或采用字典中的结构体或透明表类型作为内表的行类型

DATA itab { {TYPE [STANDARD]|SORTED|HASHED TABLE OF [REF TO] type}
          | {
LIKE [STANDARD]|SORTED|HASHED TABLE OF
dobj} }
         
[

[ WITH [UNIQUE | NON-UNIQUE]
{{
KEY [primary_key [ALIAS key_name] COMPONENTS] comp1 comp2 ...
}
| {
DEFAULT KEY
} }
 ]"主键索引

[ WITH {UNIQUE HASHED}|{UNIQUE SORTED}|{NON-UNIQUE SORTED}"secondary_key1,第二索引
KEY key_name COMPONENTS comp1 comp2 ...  ]

[ WITHsecondary_key2 ]…"第二索引,最多支持15个第二索引

] 

[INITIAL SIZE n]
[
WITH HEADER LINE
]
[
VALUE IS INITIAL
]

 

 

type:可以是基本类型,如DATA: itab TYPE TABLE OF i.

REF TO:表示内表类型为引用类型(该类型内表是用来存储引用的,可指向某个内表)

INITIAL SIZE n:为内表指定初始行数。如果n0,则会自动分配合适的行数。修改初始内存要求仅用于嵌套表,对于最外层内表没有必要,指定后反可能影响性能,所以一般不用指定。另外,该值对 APPEND…SORTED BY…有特殊的作用

 

tabkind取值如下

2  标准表(STANDARD TABLE,系统为该表的每一行数据生成一个逻辑索引,自己内部维护着行号(Index)的编码。表的键值不唯一,且没有按照表键自动进行排序,支持通过索引访问和键访问两种方式。填充标准表时可以插入到指定位置或现在有行之后,程序对内表的寻址操作可以通过关键字或索引进行。在对表进行插入删除等操作时,各数据行在内存中的物理位置不变,系统仅重新排列各数据行的索引值。当经常用索引访问表的时候就选择标准表。

2  排序表(SORTED TABLE,也有一个逻辑索引,不同之处是排序表总是按其表关键字升序排序后现进行存储,排序内表自己内部也维护着行号的编号,表的键值可以唯一或者不唯一,支持通过索引访问和键访问两种方式。如果经常使用键来访问数据,或者希望数据能够自动排序时,就用排序表。

2  哈希表(HASHED TABLE,哈希表通过哈希函数生成的表键来标识和快速访问表行,哈希表中的表键没有顺序,其值在表中必须唯一,只允许通过表键来访问哈希表。寻址一个数据行的所需时间与表行数无关。如果内表非常大而且希望用主键访问,就用哈希表。

 

各种类型内表充许的访问方式(索引访问、关键字访问):标准内表主要是索引访问,排序内表主要是Key访问,而哈希内表只能通过Key来访问:

image174

image175

对于索引类型的内表,当一个行操作语句执行结束后,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 LINETABLE_LINE:将表的整行作为Key,则可以使用TABLE_LINE

l  如果不指定任何关键字,则可以使用默认的标准关键字,该项为默认选项:

...WITH[UNIQUE|NON-UNIQUE]DEFAULTKEY...

 

排序表在指定Key的类型时,可以是UNIQUE也可以是NON-UNIQUE,所以排序内表是否可以存储重复的,则就是看定义时指定的Key类型是UNIQUE还是NON-UNIQUE

 

标准表只能使用NON-UNIQUE(但可以省略);排序表可以用NON-UNIQUEUNIQUE(不能省略)哈希表只能使用UNIQUE(不能省略)

 

在定义内表时可以不指关键字此时使用默认标准关键字即相当于 WITH KEY DEFAULT KEY。如果定义的是STANDARD TABLE则连WITH KEY DEFAULT KEY选项都可以省略但如果是SORTED TABLEHASHED TABLE如是需要指定为DEFAULT KEY时,不能省略WITH KEY DEFAULT KEY,并且需要确保该内表里有可有作为默认Key的字段——如字符类型字段,否则不能通过编译

 

在定义排序表与哈希表时一定要指定索引类型与关键字可以指定为WITH KEY DEFAULT KEY),否则编译通过不过。

 

DEFAULT KEY默认标准Key为行结构中所有byte-typex ,xstring, xsequence类型与character-typec, d, n, t, string, clike类型的所有字段其他一切类型都会被忽略如果行结构中还有子结构则该子结构中的所有前面提到的类型字段也会被抽取出来作为Key的一部分内表类型的字段不会成为默认Key的一部分如果没有byte-typecharacter-type类型字段则默认是不会有Key,:

DATA: BEGIN OF line0 OCCURS 0,
     
i TYPE i ,
     
c(1),
     
END OF line0.
DATA: BEGIN OF line1,
     
i TYPE i ,
     
c(1),
      itab
LIKE line0[],
     
END OF line1.
DATA: BEGIN OF line2 OCCURS 0,
       
i TYPE i ,
       
c TYPE string,
       
line LIKE line1,
     
END OF line2.

line0
-i = 1.
line0
-c = 'a'.
APPEND line0 .
line0
-i = 2.
line0
-c = 'b'.
APPEND line0 .

line1
-i = 3.
line1
-c = 'c'.
line1
-itab = line0[].

line2
-i = 4.
line2
-c = 'd'.
line2
-line = line1.
APPEND line2.
LOOP AT  line2 .
 
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,但也能更新,这说明内表字段默认不会作为Key
MODIFY TABLE line2."根据关键字来修改内表
WRITE
: / sy-subrc.
LOOP AT  line2 .
 
WRITE: / line2-i , line2-c.
ENDLOOP.

 

虽然数字类型字段默认(DEFUALT KEY)不作为关键字段,但可以使用KEY明确指定;在使用KEY明确指定关键字段时,如果内表行包含结构组件,还可以指定到该结构组件的某个元素作为关键字段:

TYPES: BEGIN OF line0,
     
i TYPE i ,
     
c(1),
     
END OF line0.
TYPES: BEGIN OF line1,
     
i TYPE i ,
     
c(1),
      itab
TYPE line0,
     
END OF line1.
DATA itab1 TYPE TABLE OF line1 WITH KEY i itab.
DATA itab2 TYPE TABLE OF line1
WITH KEY i itab-i.

使用第二索引

像数据库表一样,内表也可以创建多个索引,内表有三种类型第二索引:

2  UNIQUE HASHED           哈希算法第二索引

2  UNIQUE SORTED            唯一升序第二索引

2  NON-UNIQUE SORTED 非唯一升序第二索引

TYPES sbook_tab
     
TYPE STANDARD TABLE

     
OF sbook
     
"
主索引如果要为主索引指定名称则只能使用预置的 primary_key
     
"但可以通过后面的 ALIAS 选项来修改ALIAS选项只能用于排序与哈希表
     
WITH NON-UNIQUE KEY primary_key "ALIAS my_primary_key
          
COMPONENTS carrid connid fldate bookid
     
"
第一个第二索引唯一哈希算法
     
WITH UNIQUE HASHED KEY hash_key
          
COMPONENTS
carrid connid fldate bookid
     
"
第二第二索引非唯一升序排序索引
     
WITH NON-UNIQUE SORTED KEY sort_key
          
COMPONENTS customid
.

 

第二索引会影响哪些行将被处理,以及处理顺序:

2  可以在READ TABLE itab, LOOP AT itab, MODIFY itab, DELETE itab内表操作语句中通过WITH [TABLE] KEY ... COMPONENTS或者USING KEY选项指定key_name来使用第二索引

2  可以在INSERT itabAPPEND语句中通过USING KEY选项来使用源内表的第二索引

 

DATA itab TYPE HASHED TABLE OF dbtab
 
WITH UNIQUE KEY col1 col2 ...

 
"向内表itab中添加大量的数据 
 
...
READ TABLE itab "使用主键进行搜索,搜索速度将会很慢
          
WITH KEY col3 = ... col4 = ...
          
ASSIGNING ...
上面程序中定义了一个哈希内表,在读取时未使用主键,在大数据量的情况下速度会很慢,所以在搜索字段上创建第二索引:
DATA itab TYPE HASHED TABLE OF dbtab
 
WITH UNIQUE KEY col1 col2 ...

 
"为非主键创建第二索引
 
WITH NON-UNIQUE SORTED KEY second_key
   
COMPONENTS col3 col4 ...

 
"向内表itab中添加大量的数据 
 
...
READ TABLE itab "根据第二索引进行搜索,会比上面程序快
          
WITH TABLE KEY second_key
          
COMPONENTS col3 = ... col4 = ...

          
ASSIGNING ...
... "在循环内表的Where条件中,如果内表不是排序内表,则不会使用二分搜索,如果使用SORTED KEY,则循环时,是否会用到二分搜索?
LOOP AT itab USING KEY second_key wherecol3=... col4=... .
...
ENDLOOP.

INDEX/ANY TABLE通用型内表

除上面三种标准类型外,还有一般性类型,即索引表(INDEX TABLE)和任意表(ANY TABLE),一般性类型可以用于类型定义中,但不能用于声明一个内表对象,因为它并没有指明任何明确的表类型,因而系统无法确定对其操作方式。一般性类型还可以用于指明字段符号和接口参数的类型,其实际类型可能在运行期内才能够确定。

image176

内表整体操作

内表间赋值

两个内表添加使用批量增加代替逐行

不推荐:

LOOP AT int_fligh1.
 
APPEND int_fligh1 TO int_fligh2.
ENDLOOP.

推荐:

Append lines of int_fligh1 to int_fligh2.

 

APPEND LINES OF<itab1> [FROM<n1>] [TO<n2>] TO<itab2>.

 

APPEND LINES OF A TO B.

 

行类型兼容的内表可以使用“=”直接进行赋值,前提是要求行结构可转换,规则参考这里Unicode fragment view of structures

比较内表

EQ, =, NE, <>, ><, GE, >=, LE, <=, GT, >, LT, <

 

比较标准:

先比较两个内表的行数行,如果行数多的内表就大;如果两个内表的行数相等,将会一行一行、一个字段一个字段的比较,如果字段本身是一个内表类型,则会递归比较;如果不是相等比较时,只要某行某个字段不等就会停止继续向后比较。

排序内表SORT…

可以通过内表的KEY标准表哈希表按理说哈希表是不能进行排序的,但ABAP里是可以的,与Java不同进行排序:

SORT <itab> [ASCENDING|DESCENDING] [AS TEXT] [STABLE].

SORT itab [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: itab TYPE HASHED TABLE OF c WITH UNIQUE DEFAULT KEY WITH HEADER LINE.
INSERT '3' INTO TABLE itab.
INSERT '2' INTO TABLE itab.
INSERT '1' INTO TABLE itab.
LOOP AT  itab.
 
WRITE: / itab.
ENDLOOP.
SORT itab .
SKIP.
LOOP AT  itab.
 
WRITE: / itab.
ENDLOOP.

3

2

1

 

1

2

3

根据指定的字段进行排序 BY

如果你有一个行类型为结构的内表,则在排序时可以指定排序字段:

 

BY会取消前面的整体排序字段,即不会再以默认的关键字段来排序,关键字段不现影响排序结构,这些字段可以是任何类型,包括表格。如果指定多个关键字段,则系统首先根据<F1>,然后根据<F2>,以此类推对记录进行排序。系统使用BY 之前指定的排序方式(升序还是降序)将作为 BY 之后指定的所有字段的缺省排序方式(即BY后面没有指定排序方式时会使用前面指定的整体排序方式),且在单个字段之后指定的排序方式将覆盖在 BY 之前指定的这些字段的排序方式。

 

可以使用 (<name>) 代替<fi>进行动态设置,如果<name>在运行时为空,系统就将其忽略,如果包含无效的组件名,则发生实时错误。对于任何在排序字段中使用的字段,用户都可指定偏移量和长度。

接字母顺序(字符语义)进行排序AS TEXT

CONVERT TEXT text INTOSORTABLECODE hex

根据当用户操作环境来生成字符text所对应的排序字符索引串,此索引串是与用户当前操作的环境有关,如语言、国家等。如中文环境平台下,中文字符串会根据中文的拼音来进行排序,这种排序规则就是在内部采用了另一种专用来排序的编码,hex就是用来存储这种排序编码的。

可以使用SET LOCALE来设置用户所处语言环境

 

 

SET LOCALE LANGUAGE<lg> [COUNTRY<cy>]

修改当前用户所处的语言环境

The fields <lg>, <cy>, and <m> must be of type C and must have the same lengths as the keyfields of table TCP0C. Table TCP0Cis a table, in which the text environment is maintainedplatform-dependent.

SET LOCALE只影响SORT ... AS TEXT, TRANSLATE ... TO

 

SET LOCALE LANGUAGE ''

lg为空时,会重新设置为登录时的语言环境

 

SORT <itab> ... AS TEXT ... .

根据用户当前所处的语言环境来进行排序(如中文环境下,中文字符按拼音的排序规则来进行排序),如果不指定该选项,则会默认使用Unicode排序

如果待排序的字符串只有ASCII字符,则没有必要使用该选项

 

publicclass T {

    publicstaticvoid main(String[] args) throws UnsupportedEncodingException {

        String str = "";

        byte[] b = "".getBytes("utf-8");

      

        for (byte c : b) {

            System.out.print(byteToHex(c));

        }

      

    }

 

    publicstatic String byteToHex(byte b) {

        return Integer.toHexString((b & 0x000000FF) | 0xFFFFFF00).substring(6)

                .toUpperCase();

    }

}

E79A84

 

image177

image178

 

 

DATA: BEGIN OF line,
 
c TYPE
string,
  b
TYPE
xstring,
 
x TYPE
xstring,
 
END OF line
.
"
在转换之前先一定要设置当前所要使用的语言环境
SET LOCALE LANGUAGE '1' COUNTRY 'CN'.
DATA: itab LIKE STANDARD TABLE OF line WITH HEADER LINE WITH NON-UNIQUE KEY c.

PERFORM append USING '
'.
PERFORM append USING '
'.
PERFORM append USING '
'.
PERFORM append USING '
'.
PERFORM append USING '
'.

WRITE: / '--
原始顺序--'.
LOOP AT
itab.
 
WRITE: / itab-c,itab-b,itab-x
.
ENDLOOP
.
SKIP
.
SORT itab BY c
.
WRITE: / '--
按字符的Unicode编码进行排序--'.
LOOP AT
itab.
 
WRITE: / itab-c,itab-b,itab-x
.
ENDLOOP
.
SKIP
.
SORT itab BY
b.
WRITE: / '--
直接按字符的UTF8编码所对应的数字进行排序--'.
LOOP AT
itab.
 
WRITE: / itab-c,itab-b,itab-x
.
ENDLOOP
.
SKIP
.
SORT itab BY c AS TEXT
.
WRITE: / '--
按中文语义(拼音)进行排序--'.
LOOP AT
itab.
 
WRITE: / itab-c,itab-b,itab-x
.
ENDLOOP
.
SKIP
.
WRITE: / '--
按中文字符所对应的排序Key来进行排序--'.
SORT itab BY x
.
LOOP AT
itab.
 
WRITE: / itab-c,itab-b,itab-x
.
ENDLOOP
.

FORM append  USING  value
(p_0059).
  itab-
c
= p_0059.
 
DATA : l_con TYPE  REF  TO
  cl_rpe_convert.
 
CREATE
  OBJECT l_con.
 
CALL METHOD
l_con->string_to_xstring
   
EXPORTING

     
input  = itab-c
   
IMPORTING
     
output
= itab-b.
  CONVERT TEXT itab-c INTO SORTABLE CODE itab-x.

 
APPEND  itab.
ENDFORM
.

--原始顺序--

 E79A84 C6D501050105

 E8BEB9 C57301050105

 E4BA8C C77201050105

 E5AE89 A901050105

 E995BF C5F401050105

 

----按字符的Unicode编码进行排序----

 E4BA8C C77201050105

 E5AE89 A901050105

 E79A84 C6D501050105

 E8BEB9 C57301050105

 E995BF C5F401050105

 

--直接按字符的UTF8编码所对应的数字进行排序--

 E4BA8C C77201050105

 E5AE89 A901050105

 E79A84 C6D501050105

 E8BEB9 C57301050105

 E995BF C5F401050105

 

--按中文语义(拼音)进行排序--

 E5AE89 A901050105

 E8BEB9 C57301050105

 E995BF C5F401050105

 E79A84 C6D501050105

 E4BA8C C77201050105

 

--按中文字符所对应的排序Key来进行排序--

 E5AE89 A901050105

 E8BEB9 C57301050105

 E995BF C5F401050105

 E79A84 C6D501050105

 E4BA8C C77201050105

稳定排序STABLE

SORT <itab> ... STABLE.

如果对于数组中出现的任意a[i],a[j](i<j),其中a[i]==a[j]在进行排序以后a[i]一定出现在a[j]之前则认为该排序是稳定的。(相等的数据不会再交换位置,排序后仍然后保持原始顺序)。

 

不知道为什么,去掉 STABLE 选项好像还是稳定的,难道默认就是稳定排序?

DESCRIBETABLE获取内表属性

DESCRIBETABLE

获取内表数据行数 Lines()

... lines( arg ) ...

The function lines determines the number of lines in an internal table. The argument arg must be an internal table.

内表行操作

单行操作

image179

多行操作

image180

适用所有类型内表的行操作

在该节中列出的操作适用所有类型的内表。如果你在操作之前知道内表的类型,请使用合适的操作,比如,使用 APPEND…TO 语句填充索引内表,使用 INSERT…INTO TABLE 来填充Hash表或通用性类型(ANY TABLEINDEX TABLE),这样效率会高一些。

INSERT向表中插入行

INSERT wa|{INITIAL LINE}|{LINES OF jtab [FROM idx1] [TO idx2] [USING KEY key_name|(name)]} 
INTO {
TABLE itab}
{
ASSIGNING <fs> [CASTING]
}|{ REFERENCE INTO dref }.

 

不能向排序表中插入重复的数据,否则抛异常

如果向哈希表中插入重得的数据,不会起作用,也不会抛异常

 

l  UNIQUE 的排序表或哈希表插入重复的数据时,不会抛异常,但数据不会被插入进去,这与APPEND是不一样的

插入一行

INSERT <line> INTO TABLE<itab>.

<line>可以是一个工作区或者是 INITIAL LINE

 

如果向一个 unique key 内表中插入重复的数据行,则SY-SUBRC to 4

 

向不同类型表中插入的情况:

2  标准表会在内表最后新增行, APPEND 效果一样

2  排序表:会根据表关键字段插入到合适的位置。如果是一个 non-unique 内表,会将重复的行插入到已经存在数据行的前面。所花费的时间会随着表中的数据增加成对数形式的增加。

2  哈希表:使用哈希算根据表关键字计算出所插入的位置,哈希表不会因为数据行的增加而速度减慢。

插入多行FROM…TO

INSERT LINES OF <itab1> [FROM <n1>] [TO <n2>] INTO TABLE<itab2>.

<itab1> and <itab2>要具有兼容的行类型。系统将使用单条插入规则一条条插入到<itab2>中。如果<itab1>是一个索引类型的表,则可以指定待插入的第一行<n1>与最后一行<n2>数据的索引

 

取决于表格大小和插入地点的不同,用该方式将一个表格插入到另一个中的速度比在循环中逐行进行插入要快近20倍。

DATA: BEGIN OF line,
col1
TYPE i
,
col2
TYPE i
,
col3
TYPE c
,
END OF line
.
DATA: itab LIKE STANDARD TABLE OF line
,
      jtab
LIKE SORTED TABLE OF line

           
WITH NON-UNIQUE KEY col1 col2.
DO 2 TIMES
.
 
line-col1 = sy-index. line-col2 = sy-index ** 2.line-col3 = 'a'
.
 
APPEND line TO
itab.
 
line-col1 = sy-index. line-col2 = sy-index ** 3.line-col3 = 'b'
.
 
APPEND line TO
jtab.
ENDDO
.
"
会将重复的行插入到已经存在数据行的前面
INSERT lines of itab INTO TABLE jtab.
LOOP AT jtab INTO line.
 
WRITE: / sy-tabix, line-col1, line-col2,line
-col3.
ENDLOOP
.

         1           1           1  a

         2           1           1  b

         3           2           4  a

         4           2           8  b

COLLECT合并

COLLECT [<wa>INTO] <itab>{ ASSIGNING<fs> [CASTING] } | { REFERENCEINTO dref }.

<itab>必须是扁平结构,所有其他非关键字段的字段必须是数字类型(IFP):

DATA: BEGIN OF line,
col1
TYPE c
,
col2
TYPE i
,
col3
TYPE c
,
END OF line
.
DATA: itab like STANDARD TABLE OF line

       
WITH HEADER LINE WITH NON-UNIQUE key col1.
itab-col1 =
'a'
.
itab-col2 =
1
.
itab-col3 =
'b'
.
APPEND
itab.
itab-col1 =
'a'
.
itab-col2 =
2
.
itab-col3 =
'c'
.
"
编译出错:非关键字段必须是 I P F 数字类型
*COLLECT itab INTO itab.

 

COLLECT语句将一个中具有相同关键字段值的行中同名的数字字段的值累计到一条记录上,只有非表关键字段被累加;当在内表中找不到指定的被累加行时,COLLECT语句的功能与APPEND语句是一样的,即将一个工作区的内容添加到内表中。使用COLLECT操作的内表有一个限制,即该的行结构中,除了表键字段以外的所有字段都必须是数字型(ipf

 

如果仅使用 COLLECT 语句填充内表,则不会出现重复条目,因此适用于统计表的构造。

 

不同类型的内表统计情况:

ü  标准表:系统会顺序查找是否已经存在的行,所花时间会随着表的行数线性增加,如果原始表里存在重复的行,则只会与第一行合并。SY-TABIX存储了COLLECT操作所对应的插入或合并索引号。

ü  排序表:系统使用二分查找法搜索已存在的行,索引的运行的时间会随着行数的增加成对数级的增加。SY-TABIX存储了COLLECT操作所对应的插入或合并索引号

ü  哈希表:系统使用哈希算法查找已存在的行,在使用COLLECT后,SY-TABIX的值还会是0,因为哈希表没有索引。

 

DATA: BEGIN OF line,
col1(3) TYPE c
,
col2(
2) TYPE
n,
col3
TYPE i
,
END OF line
.
DATA itab LIKE SORTED TABLE OF line

     
WITH NON-UNIQUE KEY col1 col2.
line-col1 = 'abc'. line-col2 = '12'. line-col3 = 3
.
COLLECT line INTO
itab.
WRITE
/ sy-tabix.
line-col1 = 'def'. line-col2 = '34'. line-col3 = 5
.
COLLECT line INTO
itab.
WRITE
/ sy-tabix.
line-col1 = 'abc'. line-col2 = '12'. line-col3 = 7
.
COLLECT line INTO
itab.
WRITE
/ sy-tabix.
LOOP AT itab INTO line
.
 
WRITE: / line-col1, line-col2, line
-col3.
ENDLOOP
.

         1

         2

         1

abc 12         10

def 34          5

READ 读取行

READ TABLE itab { 
{
FROM wa [USING KEY key_name|(name)
]}
| {WITH TABLE KEY [key_name|(name) COMPONENTS] {comp_name1|(name1)} = dobj1 {comp_name2|(name2)} = dobj2 ...
}
| WITH KEY {comp1 = dobj1 comp2 = dobj2 ... [BINARY SEARCH]} | {key_name|(name) COMPONENTS comp1 = dobj1 comp2 = dobj2 ...
}
|
INDEX idx [USING KEY key_name|(name)] }
{INTO wa [[COMPARING { {comp1 comp2...}|{ALL FIELDS}|{NO FIELDS} }] [TRANSPORTING { {comp1 comp2...}|{ALL FIELDS} }]]}| {ASSIGNING <fs> [CASTING]} | {REFERENCE INTO dref} | {TRANSPORTING NO FIELDS}..

comp1 comp2 ...
... { comp_name[-sub_comp][{+off(len)}|{->
attr}] } | {(name)} ...

 

如果未指定USING KEY选项,则默认会使用primary table key

如果内表定义了第二排序索引sorted secondary key,则可以使用 USING KEY 选项来指定这个第二排序索引,即读取时,根据此第二排序Key排序之后的索引来读取,但不能使用secondary hashed key.

如果内表的secondary key 存在,使用了USING KEY时,INDEX选项可以应用到不同类型的内表中(比如可以给Hash内表创建一个第二排序索引sorted secondary key,则在读取此Hash内表时,可以使用索引INDEX方式来读取) 

 

sy-subrc

sy-tabix

0

找到记录

sy-tabix为主或第二索引值primary or secondary table index used,如果是hash key,则sy-tabix为0

2

找到记录,COMPARING时相应字段不同

sy-tabix为主或第二索引值primary or secondary table index used,如果是hash key,则sy-tabix为0

4

记录没找到,且未读取到内表尾部

如果READ TABLE语句中明确地使用BINARY SEARCH方式读取、或者读取时使用了USE KEYWITH [TABLE] KEY key_name选项明确的指定通过UNIQUE SORTEDNON-UNIQUE SORTED类型的第二辅助索引来方式来读取的、又或者读取的内表本身就是排序类型,则sy-tabix的值为待查记录在该内表中本应该出现的位置索引,除些之外,sy-tabix的值是不确定的

8

记录没有找到,且读取到内表尾部了
如果通过了二分搜索,且探索到尾部都还没有搜到时,sy-tabix的值为
rows + 1

指定搜索关键字段

搜索关键字段可以是表关键字段,也可也是其他非表关键字段。

如果是non-unique的内表,有重复行时,会返回第一条数据

使用表关键字段进行读取

READ TABLE<itab>FROM <wa><result>.

或者

READ TABLE <itab>WITH TABLE KEY<k1> = <f1> ...<kn> = <fn><result>.

 

第一种的<wa>必须与行类型兼容,以表关键字为查找条件,且值来自<wa>,如果相应关键字段的值为空,则匹配所有的记录,如果所有关键字都为空,则会读取第一行

第二种也是使用整个表关键字段进搜索,k1…kn可以动态指定(如(<ni>) = <fi>.)。

 

如果在读取时,未使用第二辅助索引Key,而是使用的默认的primary table key ,则不同的类型的内表读取的方式不一样:

ü  标准表:顺序搜索,查找时间会随着条目的增加而线性增加

ü  排序表:二分查找,查找时间会随着条目的增加而对数级增加

ü  哈希表:使用哈希算法进行查询,查找时间不依赖于条目数

 

DATA: BEGIN OF line,
         col1
TYPE c,
         col2
TYPE p DECIMALS 5,
     
END OF line.
DATA itab LIKE line OCCURS 10 WITH HEADER LINE.
DO 5 TIMES.
 
line-col1 = sy-indexline-col2 = SQRT( sy-index ).
 
APPEND line TO itab.

ENDDO.

CLEAR: itab,line.
itab
-col1 = '2'.
READ TABLE itab INTO line.条件来自表头关键字段,并将查找到的结果存入到工作区
WRITE: / sy-subrc, itab-col2, line-col2.

CLEAR: itab,line.
itab
-col1 = '2'.
READ TABLE itab.条件来自表头关键字段,并将查找到的结果存入表头
WRITE: / sy-subrc, itab-col2, line-col2.

    0           0.00000           1.41421

    0           1.41421           0.00000

 

使用其他关键字段进行读取

如果使用其他非表关键字段为条件进行搜索时,可以使用以下语句:

READ TABLE<itab>WITH KEY= <key><result>.

或者

READ TABLE <itab> WITH KEY<k1> = <f1> ... <kn> = <fn><result>.

 

在第一个语句中,key是一个工作区,并且整个内表的行的所有字段都会作为搜索条件。注:一定是整行,而不是内表本身那些关键字段所构成的字段,也就是说与内表本身关键字段没有任何关系,请看下面示例:

DATA: BEGIN OF line,
         col1
TYPE c
,
         col2
TYPE
n,
         col3
TYPE i
,
     
END OF line
,
      line2
LIKE line
.
DATA: itab LIKE STANDARD TABLE OF line WITH HEADER LINE WITH KEY
col1 col2 .
line-col1 = '1'
.
line-col2 = '1'
.
line-col3 = 10
.
APPEND line TO
itab.
line-col1 = '2'
.
line-col2 = '2'
.
line-col3 = 20
.
APPEND line TO
itab.
CLEAR: line
.
line-col1 = '1'
.
line-col2 = '1'
.
"
注:这里不能省略下面语句,否则查找不到
line-col3 = 10.
READ TABLE itab INTO line2 WITH KEY = line
.
WRITE
: / sy-subrc, line2-col1.

"
如果行类型本身就是基本类型时
DATA: itab2 TYPE STANDARD TABLE OF i WITH HEADER LINE with KEY TABLE_LINE.
itab2 =
2
.
append
itab2.
itab2 =
1
.
append
itab2.
READ TABLE itab2 WITH KEY = 2
.
WRITE
: / sy-subrc, itab2.

 

在第二个语句中,这里的 k1…kn 不一定是内表中真正的关键字段,只要是内表行组件即可。如果 k1…kn 要到运行时才知道,则可以使用(' key ') = <f>的格式来动态指定要比较的字段,如果 key 为空,则会忽略比较。

 

以上二种两种方式对于所有表都是顺序搜索,所需时间随着表的数据量增加或线性增加。

以行首字段搜索

要将内表的行首定义为关键字,请使用 WITH KEY 选项

READ TABLE <itab>WITH KEY<k><result>.

<k>不能包含内表或包含内表的结构。

DATA: BEGIN OF line,
        
i TYPE i,
        
c TYPE c,
     
END OF line.
DATA itab LIKE line OCCURS 10.
line-i = 10.
line-c = 'a'.
append line to itab.
CLEAR: line
.
"以第一个字段为key
READ TABLE itab INTO line WITH KEY 10.
WRITE: / sy-subrc, line-c.

   0    a

USING KEY

READ TABLE itab {FROM wa [USING KEY key_name|(name)]}

 

DATA: sflight_tab TYPE HASHED TABLE OF sflight
                 
WITH UNIQUE KEY primary_key  COMPONENTS
carrid connid fldate
                 
WITH NON-UNIQUE SORTED KEY occupied_seats COMPONENTS seatsocc,
      sflight_wa 
LIKE LINE OF sflight_tab.
...

DO 10 TIMES.
 
"使用排序第二索引,这样即使是Hash类型的内表,也可以使用INDEX方式来读取Hash内表
  READ TABLE sflight_tab
      
INDEX sy-
index USING KEY occupied_seats
      
INTO sflight_wa.

 
...
ENDDO.

 

指定额外处理选项"><result>指定额外处理选项

你可以指定一些额外的选项来让系统如何处理查找到数据。

指定工作区

你可以将找到的数据行存储到一个带有<result>选项的工作区中:

READ TABLE <itab><key> INTO <wa>[COMPARING <f1><f2> ...|ALL FIELDS]

[TRANSPORTING <f1><f2> ...|ALL FIELDS|NO FIELDS].

这里的<fi>可以是动态指定的((<ni>)

COMPARING比较读取的单行内容

系统根据<key>(关键字段)读取指定的单行并先存储到<wa>工作区中,读取行之后表与工作区<wa>中的相应组件进行比较。

... <F1> ...<fn>表示只比较指定的字段,

... ALL FIELDS表示比较所有组件

 

如果系统找根据指定<key>找到了对应的条目,且进行比较的字段内容相同,则将 SY-SUBRC 设置为0,如果进行比较的字段内容不同,则返回值 2;如果系统根据<key>找不到条目,则包含 4如果系统找到条目,则无论比较结果如何,都将其读入目标区域

DATA: BEGIN OF line,
col1
TYPE i
,
col2
TYPE i
,
END OF line
.
DATA itab LIKE HASHED TABLE OF line WITH UNIQUE KEY
col1.
DO 3 TIMES
.
 
line-col1 = sy-index
.
 
line-col2 = sy-index ** 2
.
 
INSERT line INTO TABLE
itab.
ENDDO
.
line-col1 = 2. line-col2 = 3
.
READ TABLE itab FROM line INTO line COMPARING col2.

WRITE: 'SY-SUBRC =', sy-subrc.
WRITE: / line-col1, line
-col2.

SY-SUBRC =     2

         2           4

 

DATA: BEGIN OF line,
         col1
TYPE i,
         col2
TYPE i,
         col3
TYPE i,
     
END OF line.
DATA itab LIKE line OCCURS 10.
DO 10 TIMES.
 
line-col1 = sy-index.
 
line-col2 = sy-index ** 2.
 
line-col3 = sy-index ** 3.
 
APPEND line TO itab.
ENDDO.
CLEAR: line.
line-col1 = 2. line-col2 = 4
.
"只要根据关键字或索引条件在内表中读取到相应数据,不管该数据行是否
"COMPARING
指定的字段相符,都会覆盖存储到工作区中。
READ TABLE itab INTO line INDEX 4 COMPARING col1 col2.
WRITE: / sy-subrc, sy-tabix,line-col1,line-col2,line-col3.
CLEAR: line-col3.
"也可以使用关键字KEY来读取指定行再进行比较
READ TABLE itab INTO line WITH KEY col1 = 4 col2 = 16 COMPARING col1 col2.
WRITE: / sy-subrc, sy-tabix,line-col1,line-col2,line-col3.

    2           4           4          16          64

    0           4           4          16          64

TRANSPORTING读取一行的部分字段

系统根据<key>关键字段)条件查找对应的条目后,只<result>中指定的组件字段存储到工作区域中。

 

... NO FIELDS表示不传输任何组件,此种情况下,READ语句只影响系统字段 SY-SUBRC  SY-TABIX(前提条件是索引表),并且在TRANSPORTING NO FIELDS情况下,如果指定了<wa>,则会忽略掉。

DATA: BEGIN OF line,
col1
TYPE i
,
col2
TYPE i
,
END OF line
.
DATA itab LIKE SORTED TABLE OF line WITH UNIQUE KEY
col1.
DO 4 TIMES
.
 
line-col1 = sy-index
.
 
line-col2 = sy-index ** 2
.
 
INSERT line INTO TABLE
itab.
ENDDO
.
CLEAR line
.
READ TABLE itab WITH TABLE KEY col1 = 3INTO line TRANSPORTING col2.
主键没有被传输
WRITE: 'SY-SUBRC =', sy-subrc,
/
'SY-TABIX ='
, sy-tabix.
WRITE: / line-col1, line
-col2.

SY-SUBRC =     0

SY-TABIX =          3

         0           9

 

DATA: BEGIN OF line,
col1
TYPE i
,
col2
TYPE i
,
END OF line
.
DATA itab LIKE SORTED TABLE OF line WITH UNIQUE KEY
col1.
DO 4 TIMES
.
 
line-col1 = sy-index
.
 
line-col2 = sy-index ** 2
.
 
INSERT line INTO TABLE
itab.
ENDDO
.
READ TABLE itab WITH KEY col2 = 16 TRANSPORTING NO FIELDS
.
WRITE: 'SY-SUBRC ='
, sy-subrc,
/
'SY-TABIX ='
, sy-tabix.

SY-SUBRC =     0

SY-TABIX =          4

使用字段符号

image181

你可以将查到的数据行赋值给指定的字段符号:

READ TABLE <itab><key>ASSIGNING<FS>.

 

获取更多的信息,请参考使用字段符号进行访问

 

DATA: BEGIN OF line,
col1
TYPE i
,
col2
TYPE i
,
END OF line
.
DATA itab LIKE HASHED TABLE OF line WITH UNIQUE KEY
col1.
FIELD-SYMBOLS <fs> LIKE LINE OF
itab.
DO 4 TIMES
.
 
line-col1 = sy-index
.
 
line-col2 = sy-index ** 2
.
 
INSERT line INTO TABLE
itab.
ENDDO
.
READ TABLE itab WITH TABLE KEY col1 = 2 ASSIGNING
<fs>.
<fs>-col2 =
100
.
LOOP AT itab INTO line
.
 
WRITE: / line-col1, line
-col2.
ENDLOOP
.

         1           1

         2         100

         3           9

         4          16

 

MODIFY 修改行

MODIFY { 
{ 
TABLE itab [USING KEY key_name|(name)] | {itab INDEX idx [USING KEY key_name|(name)]} | {itab [USING KEY loop_key]} } FROM wa [
TRANSPORTING comp1 comp2...] [{ASSIGNING <fs> [CASTING]} | {REFERENCE INTO dref}]
|itab FROM wa [USING KEY key_name|(name)] TRANSPORTING comp1 comp2... 
WHERE log_exp|(cond_syntax) }.

 

comp1 comp2 ...
... { comp_name[-sub_comp][{+off(len)}|{->
attr}] } | {(name)} ...

修改单条记录(TABLE KEY

MODIFY TABLE <itab>[USING KEY key_name|(name)]FROM<wa> [TRANSPORTING<f1><f2> ...].

这里的<wa>扮演双重身份,不仅指定了要修改的行(条件),还包括要修改的新的值。系统以整个表的所有关键字段来搜索要修改的行。

 

USING KEY:如果未使用此选项,则会使用默认的主键primary table key来修改相应行

 

如果找到要修改的行,则将<wa>中所有非关键字段的内容拷贝到对应的数据行中对应的字段上, SY-SUBRC设置为 0,否则 SY-SUBRC 设置为4如果是 NON-UNIQUE 类型的表,且找到多条时只修改第一条数据

 

可以使用 TRANSPORTING 选项修改部分非关键字段。

 

Fi可以是动态指定(<ni>) ,如果ni 为空,则运行时会忽略。

 

DATA: BEGIN OF line,
col1
TYPE i,
col2
TYPE i,
END OF line.
DATA itab LIKE HASHED TABLE OF line WITH UNIQUE KEY col1.
DO 4 TIMES.
 
line-col1 = sy-index.
 
line-col2 = sy-index ** 2.
 
INSERT line INTO TABLE itab.
ENDDO.
line-col1 = 2. line-col2 = 100.
MODIFY TABLE itab FROM line.
LOOP AT itab INTO line.
 
WRITE: / line-col1, line-col2.
ENDLOOP.

         1           1

         2         100

         3           9

         4          16

修改多条记录(WHERE

MODIFY <itab> FROM <wa> TRANSPORTING<f1><f2> ... WHERE <cond>.

该语句会修改满中条件的多条件数据。逻辑表达式<cond>中的各子表达式的第一个操作数必须是内表行结构的组件。

 

这里的TRANSPORTING 是必须的,与上面MODIFY中的TRANSPORTING不一样。

 

如果是标准表,可以在TRANSPORTING后面指定修改字段为表关键字段,但排序表与哈希表则不能修改关键字段。

 

如果至少有一条数据被成功修改了,则SY-SUBRC0,否则为4

DATA: BEGIN OF line,
col1
TYPE i,
col2
TYPE i,
END OF line.
DATA itab LIKE HASHED TABLE OF line WITH UNIQUE KEY col1.
DO 4 TIMES.
 
line-col1 = sy-index.
 
line-col2 = sy-index ** 2.
 
INSERT line INTO TABLE itab.
ENDDO.
line-col2 = 100.
MODIFY itab FROM line TRANSPORTING col2 WHERE ( col2 > 1 ) AND ( col1 < 4 ).
LOOP AT itab INTO line.

 
WRITE: / line-col1, line-col2.
ENDLOOP.

         1           1

         2         100

         3         100

         4          16

DELETE 删除行

DELETE { {TABLE itab {FROM wa [USING KEY key_name|(name)]} | {WITH TABLE KEY [key_name|(name) COMPONENTS] {comp_name1|(name1)}=dobj1 {comp_name2|(name2)}=dobj2...}} | {itab INDEX idx [USING KEY key_name|(name)]} | {itab [USING KEY loop_key]}
| itab [USING KEY key_name|(name)] [FROM idx1] [TO idx2] [WHERE log_exp|(cond_syntax)
]
| ADJACENT DUPLICATES FROM itab [USING KEY key_name|(name)] [COMPARING {comp1 comp2 ...}|{ALL FIELDS}]... }

 

comp1 comp2 ...
... { comp_name[-sub_comp][{+off(len)}|{->
attr}] } | {(name)} ...

 

循环中插入或删除行

最好不要在循环中插入或删除行,因为可能会发生不必要的问题:插入操作会使插入位置后面的行的sy-tabix 都加1(只针对索引表),删除则会是被删除行后面所有行的索引都减1;如果是插入,则下次循环还是从当前被遍历行的后面开始接着遍历,但索引增加1了;但如果是删除的是当前遍历的行,则下次删除还是继续接着删除下一行数据,并且删除后下次循环的索引还是与上次一样(所以能连续删除,不会隔行删除) 

循环中插入行请参见这里

循环中删除行请参见这里

 

下面也能删除所有行:

LOOP AT itab_person FROM 1 to 1.
 
DELETE
itab_person.
ENDLOOP
.

删除单行(TABLE KEY

DELETE TABLE<itab>FROM<wa>.

或者

DELETE TABLE <itab> WITH TABLE KEY <k1> = <f1> ... <kn> = <fn>.

 

两个语句都是根据表的关键字段进行删除的,第二种要将所有表关键字段写上,不同第一种的是可以使用动态的字段名。

 

如果成功删除,则SY-SUBRC设置为0,否则为4。如果是 non-unique 内表,且满足条件的有多条件数据时,只会删除第一条

DATA: BEGIN OF line,
col1
TYPE i,
col2
TYPE i,
END OF line.
DATA itab LIKE HASHED TABLE OF line WITH UNIQUE KEY col1.
DO 4 TIMES.
 
line-col1 = sy-index.
 
line-col2 = sy-index ** 2.
 
INSERT line INTO TABLE itab.
ENDDO.
line-col1 = 1.
DELETE TABLE itab: FROM line,
WITH TABLE KEY col1 = 3.
LOOP AT itab INTO line.
 
WRITE: / line-col1, line-col2.
ENDLOOP.

         2           4

         4          16

删除多行(WHERE

DELETE<itab>WHERE<cond>.

 

如果至少有一条数据被成功删除,则SY-SUBRC0,否则为4

DATA: BEGIN OF line,
col1
TYPE i,
col2
TYPE i,
END OF line.
DATA itab LIKE HASHED TABLE OF line WITH UNIQUE KEY col1.
DO 4 TIMES.
 
line-col1 = sy-index.
 
line-col2 = sy-index ** 2.
 
INSERT line INTO TABLE itab.
ENDDO.
DELETE itab WHERE ( col2 > 1 ) AND ( col1 < 4 ).
LOOP AT itab INTO line.

 
WRITE: / line-col1, line-col2.
ENDLOOP.

   1           1

         4          16

删除邻近重复行(ADJACENT DUPLICATE

DELETE ADJACENT DUPLICATES FROM <itab>

[COMPARING<f1><f2> ...

|ALL FIELDS].

系统从内表<itab>中删除所有邻近重复条目。

在以下情况下表示记录重复:

_      如果没有 COMPARING 选项,则所内表有标准关键字段的内容相同时。

_      如果有 COMPARING 选项.... COMPARING <F1><F2> ... ,指定字段<F1><F2> ... 的内容必须相同才算重复。也可以通过写入 (<name>) 代替<F1>在运行时在括号中动态指定字段名。如果<name>在运行时为空,则系统将其忽略。如果包含无效的组件名,则会发生实时错误。

_      如果用 COMPARING 选项.... COMPARING ALL FIELDS ,内表行所有字段的内容必须相同时才算重复。

 

如果系统找到并删除至少一个重复条目则将 SY-SUBRC 设置为0。否则将其设置为4

 

在未使用COMPARING 选项时,要删除重复数据之前一定要按照内表的关键字声明的顺序来进行排序才能删除重复数据否则不会删除掉如果指定了COMPARING 选项,则需要根据指定的比较字段顺序进行排序COMPARING <F1><F2>则需要sort by <F1><F2>而不能是sort by <F2><F1>),才能删除所有重复数据。

 

DATA: BEGIN OF line,
        col1
TYPE i
,
        col2
TYPE c
,
     
END OF line
.
DATA itab LIKE line OCCURS 10
.
line-col1 = 1. line-col2 = 'A'. APPEND line TO
itab.
line-col1 = 1. line-col2 = 'A'. APPEND line TO
itab.
line-col1 = 1. line-col2 = 'B'. APPEND line TO
itab.
line-col1 = 2. line-col2 = 'B'. APPEND line TO
itab.
line-col1 = 3. line-col2 = 'B'. APPEND line TO
itab.
line-col1 = 4. line-col2 = 'B'. APPEND line TO
itab.
line-col1 = 5. line-col2 = 'A'. APPEND line TO
itab.
LOOP AT itab INTO line
.
 
WRITE: / line-col1, line
-col2.
ENDLOOP
.
"
所有字段相同时才算重复
DELETE ADJACENT DUPLICATES FROM itab COMPARING ALL FIELDS.
SKIP TO LINE 3
.
LOOP AT itab INTO line
.
 
WRITE: /14 line-col1, line
-col2.
ENDLOOP
.
"
指定字段重复时
DELETE ADJACENT DUPLICATES FROM itab COMPARING col1.
SKIP TO LINE 3
.
LOOP AT itab INTO line
.
 
WRITE: /28 line-col1, line
-col2.
ENDLOOP
.
"
根据表关键字段col2来判断是否重复
DELETE ADJACENT DUPLICATES FROM itab.
SKIP TO LINE 3
.
LOOP AT itab INTO line
.
 
WRITE: /42 line-col1, line
-col2.
ENDLOOP
.

         1  A         1  A          1  A          1  A

         1  A         1  B          2  B          2  B

         1  B         2  B          3  B          5  A

         2  B         3  B          4  B

         3  B         4  B          5  A

         4  B         5  A

         5  A

LOOP在循环中处理行

LOOP AT itab {INTO wa}|{ASSIGNING <fs> [CASTING]}|{REFERENCE INTO dref}|{TRANSPORTING NO FILDS}
[[
USING KEY key_name|(name)] [FROM idx1] [TO idx2] [WHERE log_exp|(cond_syntax)]]
.

...

ENDLOOP.

 

FROM … TO: 只适用于标准表与排序表

WHERE …  : 适用于所有类型的内表

 

如果没有通过USING KEY选项的key_name则循环读取的顺序与表的类型相关

l  标准表与排序表会按照primary table index索引的顺序一条一条的循环且在循环里SY-TABIX为当前正在处理行的索引号。

l  哈希表由于表没有排序,所以按照插入的顺序来循环处理,注,此时SY-TABIX 总是0,如:

DATA: hash TYPE HASHED TABLE OF i WITH HEADER LINE WITH UNIQUE KEY TABLE_LINE.
INSERT 4 INTO TABLE
hash.
INSERT 2 INTO TABLE
hash.
INSERT 3 INTO TABLE
hash.
INSERT 1 INTO TABLE
hash.
LOOP AT
  hash.
 
WRITE
: / sy-tabix, hash.
ENDLOOP.

         0           4

         0           2

         0           3

         0           1

 

可以嵌套LOOP,当进入或离开某层LOOP时,SY-TABIX会根据着相应变化。在ENDLOOP后面,如果至少有一条数据被处理,则SY-SUBRC 0,否则为4

 

如果循环的是哈希表,则sy-tabix恒为0

可以在循环内表时增加与删除当前行If you insert or delete lines in the statement block of a LOOP , this will have the following effects:

  • If you insert lines behind(后面) the current line, these new lines will be processed in the subsequent loop(下一次循环) passes. An endless loop(可能会引起死循环) can result.
  • If you delete lines behind the current line, the deleted lines will no longer be processed in the subsequent loop passes.
  • If you insert lines in front of the current line, the internal loop counter is increased by one with each inserted line. This affects sy-tabix in the subsequent loop pass(这会影响在随后的循环过程SY-TABIX).
  • If you delete lines in front of the current line, the internal loop counter is decreased by one with each deleted line. This affects sy-tabix in the subsequent loop pass.
SUM

要在循环处理期间计算内表中数字字段的内容之和:

SUM.

系统只能在 LOOP - ENDLOOP 块中处理该语句。

如果在 AT - ENDAT 块中使用 SUM则系统计算当前行组中所有行的数字字段之和并将其写入工作区域中相应的字段

 

如果某个内表行的组件是另一个表格,则不要使用 SUM 语句。

DATA: BEGIN OF line,
         col1
TYPE i
,
         col2
TYPE i
,
     
END OF line
.
DATA itab LIKE line OCCURS 10
.
DO 3 TIMES
.
 
line-col1 = sy-index
.
 
line-col2 = sy-index ** 2
.
 
APPEND line TO
itab.
ENDDO
.
LOOP AT itab INTO line
.
 
WRITE: / line-col1, line
-col2.
 
"
统计后会将统计的结果临时存入工作区
 
SUM.
 
WRITE: / line-col1, line
-col2.
ENDLOOP
.
SKIP
.
LOOP AT itab INTO line
.
 
WRITE: / line-col1, line
-col2.
ENDLOOP
.

         1           1

         6          14

         2           4

         6          14

         3           9

         6          14

 

         1           1

         2           4

         3           9

AT

AT <line>.

<statement block>

ENDAT.

 

<line>

含义

FIRST

内表的第一行时触发

LAST

内表的最后一行时触发

NEW <f>

相邻数据行中相同<f>字段构成一组,在循环到该组的开头时触发

END Of <f>

相邻数据行中相同<f>字段构成一组,在循环到该组最末时触发

 

在使用AT...... ENDAT之前,一这要先按照这些语句中的组件名进行排序,且排序的顺序要与在AT...... ENDAT语句中使用顺序一致。并且排序与声明的顺序决定了先按哪个分组,接照再按哪个进行分组,最后再按哪个进行分组,这与SQL中的Group By 的顺序是一样的意义

 

用在AT...... ENDAT语句中的中的组件名不一定要是结构中的关键字段,但这些字段一定要按照出现在AT关键字后面的使用顺序在结构最前面进行声明,且这些组件的声明之间不能插入其他组件的声明。如现在需要按照<f1>, <f2>, ....,多字段的顺序来使用在AT...... ENDAT语句中,则首先需要在结构中按照<f1>, <f2>, ....,多字段的顺序在结构最前面都声明,然后按照<f1>, <f2>, ....,多字段来排序的,最后在循环中按如下的顺序块书写程序(请注意在AT END OF的顺序与AT NEW 是相反的):

LOOP AT <itab>.

AT FIRST. ... ENDAT.

AT NEW <f1>. ...... ENDAT.

AT NEW <f2>. ...... ENDAT.

.......

<single line processing>

.......

AT END OF <f2>.... ENDAT.

AT END OF <f1>. ... ENDAT.

AT LAST. .... ENDAT.

ENDLOOP.

<single line processing>块专门用来处理所有非分组字段。你可以处理所有分组字段,但只要出现时,请按照以上顺序来书写代码块。

 

可以使用动态方式 ('F1') 来设置字段名称。

 

========================================================

如果循环的内表不是自己定义的,有时无法将分组的字段按顺序声明在一起,所以需要自己实现这些功能,下面是自己实现AT NEWAT END OF(另一好处是在循环内表时可以使用Where条件语句)(注:使用这种只需要按照分组的顺序排序即可,如要分成bukrsbukrs anlkl两组时,需要按照BY bukrs anlkl排序,而不能是BYanlkl bukrs):

DATA: lp_bukrs TYPE bukrs, "上一行bukrs字段的值
      lp_anlkl
TYPE anlkl. "上一行anlkl
字段的值

"下面假设按bukrsbukrs anlkl分成两组
SORT itab_data BY bukrs 
anlkl.
DATA: i_indx  TYPE i
.

DATA: lwa_data  Like itab_data 
LOOP AT itab_datawhere flg = 'X'
.

i_indx  = sy-tabix.
 
"**********AT NEW
对当前分组首行进行处理

IF  itab_data-bukrs <> lp_bukrs. "Bukrs
     
".........
   
ENDIF.
   
IF  itab_data-bukrs <> lp_bukrs OR itab_data-anlkl <> lp_anlkl. "bukrs anlkl 分组
     
".........
   
ENDIF.
   
IF  itab_data-bukrs <> lp_bukrs OR itab_data-anlkl <> lp_anlkl OR  itab_data-.. <> lp_.. . "bukrs anlkl .. 分组
     
".........
   
ENDIF.


 
"**********普通循环处理
 
".........

 
"**********AT END OF 对当前分组末行进行处理
 

 DATA : l_nolast1