ABAP 内表

一、内表有关概念

1、内表的定义

在 ABAP 中,内表(Internal Table)是用于在内存中存储数据的结构,类似于数据库中的表,但它是在程序执行期间临时存在的。内表常用于在 ABAP 程序中处理和操作数据,比如将数据库查询结果存储在内表中,或者用于对数据进行各种操作,如排序、过滤、更新等。

内表是 ABAP 中最重要的数据结构之一,几乎所有与数据处理相关的操作都涉及到内表。

2、内表的类型及定义方法

a、标准内表(standard tables

最常用的内表类型,它允许动态增长和删除行,但行的顺序并不是固定的。

DATA: 内表名称 TYPE (STANDARD) TABLE OF 类型(可以数据库表作为类型,这里填写表名).
b、排序内表(sorted tables)默认为升序排列。

排序内表在插入数据时会自动排序,它适用于查找操作,特别是当你需要按某种顺序访问数据时,排序内表比标准内表的性能更好。

DATA: 内表名称 TYPE SORTED TABLE OF 类型(可以数据库表作为类型,这里填写表名)
        WITH UNIQUE KEY 列名(作为排序依据) .
c、哈希内表(hashed tables

哈希内表通过哈希算法快速访问数据,特别适用于需要通过键来快速查找的场景。

DATA: 内表名称 TYPE HASHED TABLE OF 类型(可以数据库表作为类型,这里填写表名)
        WITH UNIQUE KEY 列名(作为排序依据) .

二、插入数据

1、APPEND 向内表末尾插入一条数据。

本节以及后续演示所用到的内表定义以及结构体定义如下:

TYPES : BEGIN OF ty_student,
          id   TYPE i,
          name TYPE string,
          age  TYPE i,
        END OF ty_student.

DATA : lt_students TYPE STANDARD TABLE OF ty_student,
       lv_student TYPE ty_student.

最初没有数据。

 使用APPEND向内表末尾插入数据。插入两条数据,显示结果。 

lv_student-id = 1.
lv_student-name = 'Via'.
lv_student-age = 22.
APPEND lv_student TO lt_students."追加至内表,至末尾

lv_student-id = 2.
lv_student-name = 'Libra'.
lv_student-age = 23.
APPEND lv_student TO lt_students.

WRITE: / '        索引'.
LOOP AT lt_students INTO lv_student.
  WRITE: / sy-tabix, lv_student-id, lv_student-name.
ENDLOOP.

结果显示如下,APPEND追加至内表末尾。 

2、INSERT 向指定位置插入一条数据。

INSERT 数据名(多用结构体) INTO 内表名 INDEX 行号.

lv_student-id = 1.
lv_student-name = 'Via'.
lv_student-age = 22.
APPEND lv_student TO lt_students."追加至内表,至末尾

lv_student-id = 2.
lv_student-name = 'Libra'.
lv_student-age = 23.
APPEND lv_student TO lt_students.

lv_student-id = 3.
lv_student-name = 'Soobin'.
lv_student-age = 24.
APPEND lv_student TO lt_students.

***********insert***********
lv_student-id = 4.
lv_student-name = 'Lily'.
lv_student-age = 25.
INSERT lv_student INTO lt_students INDEX 2."插入到第二位
***********insert***********

WRITE: / '        索引'.
LOOP AT lt_students INTO lv_student.
  WRITE: / sy-tabix, lv_student-id, lv_student-name.
ENDLOOP.

可以从结果输出看到通过INSERT插入时,Lily变成了第二位,这里INDEX n会使成为第n个行。 

 3、COLLECT 插入同时对内表中的重复记录进行汇总。

COLLECT主要作用是根据指定的字段进行 分组,如果在内表中已经存在与当前行的非数值字段相同的记录,COLLECT会将该记录的数值字段累加到现有记录中;如果没有找到相同的记录,COLLECT会将该记录插入到内表中。(有记录则累加,没记录则插入)

运行下面这段代码。

*COLLECT根据非数值字段进行比较,将数值字段进行累加*
TYPES : BEGIN OF ty_class,
          students TYPE i,
          teacher  TYPE i,
          name     TYPE string,
        END OF ty_class.

DATA : lt_classes TYPE STANDARD TABLE OF ty_class,
       lv_class      TYPE ty_class.

lv_class-students = 20.
lv_class-teacher = 3.
lv_class-name = '一班'.
COLLECT lv_class into lt_classes.

lv_class-students = 45.
lv_class-teacher = 5.
lv_class-name = '二班'.
COLLECT lv_class into lt_classes.

lv_class-students = 30.
lv_class-teacher = 3.
lv_class-name = '一班'.
COLLECT lv_class into lt_classes.

cl_demo_output=>display( lt_classes ).

结果如下,发现结果中将两次一班的人数进行了累加。根据非数值字段name对students和teacher字段进行了累加。

三、删除数据

演示用学生内表初始数据如下(每次运行前数据都是该初始数据):

1、DELETE根据条件删除内表中记录。

a、根据索引删除数据。
DELETE 内表名 INDEX n.
ULINE.
WRITE : '删除索引为1的数据'.SKIP.
DELETE  lt_students INDEX 1.
WRITE: / '        索引'.
LOOP AT lt_students INTO lv_student.
  WRITE: / sy-tabix, lv_student-id, lv_student-name.
ENDLOOP.

运行后结果:  

b、 根据条件删除。

DELETE 内表名 WHERE 条件.

1)如果只有一行符合条件。
ULINE.
WRITE : '删除名为Soobin的数据'.SKIP.
DELETE  lt_students WHERE  name = 'Soobin'.
LOOP AT lt_students INTO lv_student.
  WRITE: / sy-tabix, lv_student-id, lv_student-name.
ENDLOOP.

运行后结果: 

2)如果有多行符合条件。
ULINE.
WRITE : '删除名为VIA的数据'.SKIP.
DELETE  lt_students WHERE  name = 'Via'.
LOOP AT lt_students INTO lv_student.
  WRITE: / sy-tabix, lv_student-id, lv_student-name.
ENDLOOP.

 运行后结果如下,可以看到删除了所有名为Via的数据

 2、DELETE ADJACENT DUPLICATES删除相邻的重复项。

DELETE ADJACENT DUPLICATES FROM  内表名 (COMPARING 字段1 字段2 字段3).

区别于DELETE会删除所有符合条件的数据,DELETE ADJACENT DUPLICATES只会删除相邻的重复项,且会保留第一行。通过下面两个例子进行比较。

a、 删除name相同的字段。
ULINE.
WRITE : '删除全字段重复的数据'.SKIP.
DELETE ADJACENT DUPLICATES FROM  lt_students COMPARING name.
LOOP AT lt_students INTO lv_student.
  WRITE: / sy-tabix, lv_student-id, lv_student-name.
ENDLOOP.

运行后结果如下,可以看到第一个Via由于和后两个Via不相邻,并没有被删除,后面的两个Via由于相邻被删除了,但是保留了相邻的索引靠前的那一个(注意她们的id)。DELETE ADJACENT DUPLICATES只会删除相邻的重复项,且会保留第一行

那么如果我想将删除所有的重复项且保留一个要怎么做?

 b、排序后删除name相同的字段。 
ULINE.
SORT lt_students."根据全字段排序
WRITE : '排序后数据'.SKIP.
LOOP AT lt_students INTO lv_student.
  WRITE: / sy-tabix, lv_student-id, lv_student-name.
ENDLOOP.
ULINE.
WRITE : '删除全字段重复的数据'.SKIP.
DELETE ADJACENT DUPLICATES FROM  lt_students.
LOOP AT lt_students INTO lv_student.
  WRITE: / sy-tabix, lv_student-id, lv_student-name.
ENDLOOP.

运行结果如下, 可以看到删除了id为5、6的Via,保留了id为1的Via。 

c、 DELETE ADJACENT DUPLICATES总结。

DELETE ADJACENT DUPLICATES 只会删除相邻的重复项,且会保留重复项中的第一行
所以在删除重复的数据之前 必须先对内表进行排序,具体如下:

1)若需要删除全字段匹配的数据 则直接sort+表名。
2)若需要删除某些字段相同的数据 则sort + 表名 + BY 字段名1 字段名2 字段名3。
3)删除语句:DELETE ADJACENT DUPLICATES FROM 表名 COMPARING 字段名1 字段名2 字段名3。(ALL FIELDS-全部字段)

3、CLEAR清空内表中数据。

CLEAR 表名.

ULINE.
CLEAR lt_students.
WRITE : 'CLEAR后的数据'.SKIP.
LOOP AT lt_students INTO lv_student.
  WRITE: / sy-tabix, lv_student-id, lv_student-name.
ENDLOOP.

四、修改数据

READ TABLE 内表名 INTO 结构体 WITH TABLE KEY 条件.
MODIFY TABLE 内表名 FROM 结构体.                                  

*修改内表中数据*
READ TABLE lt_students INTO lv_student WITH TABLE KEY name = 'Via'."with table key只会返回第一条符合条件的数据
lv_student-id = 888.
MODIFY TABLE lt_students FROM lv_student."根据结构体来修改内表数据
ULINE.
WRITE : '修改后数据'.
LOOP AT lt_students INTO lv_student.
  WRITE: / sy-tabix, lv_student-id, lv_student-name.
ENDLOOP.

 可以看到,虽然条件WITH TABLE KEY name='Via'有三个满足条件的学生,但是READ的结果只会返回第一个结果。

修改数据的具体步骤:

a、READ找到需要修改的数据。

b、MODIFY对内表进行修改。 

注:MODIFY在数据库里面没有符合条件的数据的时候会增加数据。

五、查询数据

1、根据索引进行查询。

READ TABLE 内表名 INTO 结构体 INDEX n.

READ TABLE lt_students INTO lv_student INDEX 1."读取索引为1的那个行
WRITE : / '索引为1的学生是',lv_student-id,lv_student-name,lv_student-age.

查询结果:

2、根据关键字查询。

READ TABLE 内表名 INTO 结构体 WITH KEY 条件.

READ TABLE lt_students INTO lv_student WITH KEY name = 'Libra'.
WRITE : / '关键字NAME是Libra的人是',lv_student-id,lv_student-name,lv_student-age.

 查询结果:

3、二分法查询。

a、给表排序:SORT 表名 BY 字段名 (ASCENDING)/DESCENDING.(默认升序可以不写,降序写 DESCENDING)
b、二分法查找:READ TABLE 内表名 INTO 结构体 WITH KEY 条件 BINARY SEARCH。
SORT lt_students BY name ASCENDING.
READ TABLE lt_students INTO lv_student WITH KEY name = 'Soobin' BINARY SEARCH.
WRITE : / '二分法查找关键字NAME是Soobin的人是',lv_student-id,lv_student-name,lv_student-age.

查询结果:

数据量更大的时候才会体现处二分法的作用。 二分法思想

4、LOOP循环查询。

LOOP AT 内表名 INTO 结构体 (WHERE 条件). 

SORT lt_students BY id ASCENDING.
WRITE : '排序后,根据条件name = Via 循环读取:'.SKIP.
WRITE: / '        索引'.
LOOP AT lt_students INTO lv_student WHERE name = 'Via'.
  WRITE: / sy-tabix, lv_student-id, lv_student-name,lv_student-age.
ENDLOOP.

条件查询的时候,只会查询出满足条件的行。 

### 删除ABAP中的元素或记录 在ABAP中,删除内中的特定元素可以通过多种方式实现。以下是几种常见的方法及其对应的语法和解释。 #### 使用 `DELETE` 命令按条件删除记录 可以使用 `DELETE` 命令配合条件达式来移除满足某些标准的行: ```abap DATA: lt_itab TYPE TABLE OF sflight, ls_sflight LIKE LINE OF lt_itab. SELECT * FROM sflight INTO TABLE lt_itab UP TO 10 ROWS. " Delete records where carrid is 'LH' DELETE FROM lt_itab WHERE carrid = 'LH'. ``` 这段代码先从数据库 `sflight` 中选取最多十条记录到内部格 `lt_itab` 中[^2],接着利用 `DELETE` 关键字加上过滤条件 `WHERE carrid = 'LH'` 来清除所有航空公司编号为 `'LH'` 的航班信息[^4]。 #### 移除指定范围内的多条记录 当需要删除某范围内连续的几项时,可采用循环遍历并计数的方式找到目标位置再执行删除动作: ```abap FIELD-SYMBOLS: <fs_line> TYPE ANY TABLE. DATA: lv_counter TYPE i VALUE 0, n1 TYPE i, " Start index of deletion range n2 TYPE i. " End index of deletion range n1 = 3. " Example start position n2 = 5. " Example end position LOOP AT lt_itab ASSIGNING FIELD-SYMBOL(<line>) WITH CLEAN KEY. ADD 1 TO lv_counter. IF lv_counter >= n1 AND lv_counter <= n2. DELETE itab INDEX sy-tabix. ENDIF. ENDLOOP. ``` 这里定义了两个变量 `n1`, `n2` 示要删除的第一项(`n1`)到最后一项(`n2`)的位置索引;通过 `LOOP...AT` 循环访问每一条记录的同时增加计数器 `lv_counter` ,一旦发现当前序号落在给定区间之内就调用 `DELETE` 并传入当前行号作为参数完成单次删除操作[^1]。 #### 利用新版本简化语法 (适用于 ABAP 7.4 及以上) 自 ABAP 版本7.4起引入了一些更简洁高效的语句形式用于处理集合型数据结构,比如可以直接作用于整个列上的函数运算符: ```abap MODIFY lt_itab FROM VALUE #( ) TRANSPORTING NO FIELDS WHERE connid IN ('CA987', 'AA123'). ``` 上述命令会一次性将符合条件的所有项目标记为空值而不实际改变其存在状态,随后可通过再次筛选排除掉这些已置空的对象达到间接性的批量清理效果[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值