- 内表
-
- 概念
内表是在程序内部定义的表。是定义在内存中,所以运行速度会比磁盘中是实体表快很多。
内表的定义,可以通过type来定义,也可以通过变量来定义。
例如:先定义一个结构体,然后再通过结构体定义内表
先顶一个结构体的变量,在通过变量来定义内表。
数组与内表
在PYTHON中,定义数字 students[100],即定义100个student的数组
而在内表中,其实就是一个任意行的数组,没一行可以有一个字段或者多个字段。
如图5-5,在sawon这个内表,就是一个数组。
先定义一个结构体类型,在通过顶一个一个表类型,来定义这个数组。
内表在刚定义的时候,是不会占用内存的。
只是使用INITIAL SIZE n 用来指定内表初始的行数n。
即为预留的内存大小。最大到2000M
内表的创建:参照局部表 VS 参照全局表
1.参照局部表类型创建内表
2.参照全局表定义内表
1.参照局部表类型创建内表
就需要先定义一个结构体类型,然后参照这个结构体类型定义一个表类型
再依据表类型定义的变量
types:begin of s_tru, no(6) TYPE c, name(10) type c, part(16) type c, end of s_tru. TYPES: t_tru TYPE STANDARD TABLE OF s_tru WITH non-UNIQUE key no . data: gv_itab TYPE t_tru WITH HEADER LINE. gv_itab-no := '123456'. gv_itab-name := 'Dillon'. gv_itab-part := 'Bussines'. APPEND gv_itab. LOOP AT gv_itab. WRITE: /, gv_itab-no, gv_itab-name, gv_itab-part. ENDLOOP. |
2.参照全局表定义
就是该表已经在系统中存在了。值需要直接定义表变量即可。
data: gv_itab type t_tab with unique key <keys> initial size n with header line. |
所以在定义内表的时候,有2中定义法,参考局部和参考全局
参考局部的,就是自己要先定义内表的结构类型。再去定义内表变量
参考全局,是系统中现在已经有的表,是用type关键字,并且确定是否带表头,以及是否存在索引。With unique key with header line
-
- 内表与表头
当在定义内表的时候,使用到了关键字 with header line的时候,就会自动生成表头。
当使用带表头的内表时,明确表头的数据后再使用。
data gv_itab TYPE type with header line.
Data gv_itab like obj with header line.
在循环带有表头的内表时候,是直接把数据传递至表头。
带表头 与 不带表头的 区别
不带表头的内表循环
LOOT AT gv_itab INTO gs_wa.
Write: /, gs_wa-carrid.
ENDLOOP.
带表头的内表的循环
LOOP AT gv_itab.
Write: /, gv_itab-carrid.
ENDLOOP.
未来在使用修改数据的时候,也是存在差异
MODIFY TABLE gv_itab from gv_wa.
MODIFY TABLE
这里就注意,所有的带表头和不带表头的内表操作的差异,基本都是这样的。
不推荐使用OCCURS语句定义的表头内表。
内表的类型:有3种
标准表、哈希表、排序表。
其中标准表和排序表都是索引表。
标准表
是一个树形结构内表,是利用索引查找内表行数据易于使用的内表类型。
标准表中不能使用with unique语句
Data:gv_itab TYPE STANDARD TABLE OF s_stru
WITH NON-UNIQUE KEY <keys>
INITIAL SIZE n
WITH HEADER LINE.
内表是以with default key语句为默认语句。是标准关键字
所谓标准关键字是,默认为此语句。
即下面两个语句表达的意思相同:
Data gv_tab TYPE STANDARD TABLE OF t_line WITH DEFAULT KEY,.
Data gv_tab TYPE STANDARD TABLE OF t_line.
用户自定义关键字
With key field1.
Read table 用于内表的单行查询。
READ TABLE ~ INDEX n.
用于读取table的第n行数据。
如果不采用索引来读取,可以采用字段指定关键字来读取
READ TABLE gv_tab WITH TABLE KEY col1 = ‘enjoy’ col2 = ‘ABAP’.
读取关键字以外的
READ TABLE gv_tab WITH KEY col3= 1.
由此可见,read table有2中方式:
- 索引的,方式,一次只能读一样,要想全部读出来,就需要控制索引+1
- 使用关键字和非关键字 with table key 或者非关键字 with key
排序表
标准表与排序表都是索引表。
其中排序表是已经按照关键字排序号的内表类型
排序表定义关键字的时候,可以使用with unique语句,
而标准表只能使用with non-unique语句。
排序表自带binary search 功能
定义排序表的时候,务必明确unique/non-unique
对于排序表,不能使用append,因为需要排序,append是追加在后面
如果使用append会发生关于排序的dump error。
这里需要注意的在sorted表,insert数据后,使用index读取数据的时候,则是按照insert的顺序进行读取的。
这里参见一下程序代码
TYPES: BEGIN OF t_line,
COL TYPE C,
SEQ TYPE I,
END OF t_line.
TYPES: GT_TAB TYPE SORTED TABLE OF t_line WITH UNIQUE KEY COL.
DATA:GV_TAB TYPE GT_TAB WITH HEADER LINE.
GV_TAB-COL := 'B'.
GV_TAB-SEQ := 1.
INSERT TABLE GV_TAB.
GV_TAB-COL := 'A'.
GV_TAB-SEQ := 2.
INSERT TABLE GV_TAB.
CLEAR GV_TAB.
READ TABLE GV_TAB INDEX 2.
WRITE: / GV_TAB-COL, GV_TAB-SEQ.
*这里比较有意思,index 2 ,还是读的是第二个插入的数据,并不是第一个。
哈希表
哈希表是没有索引的,因为要使用hash算法来分散。
只能使用hash值计算出key值进行检索
Hash表一定要设置为unique形式的
HASH表不能使用索引,因此在read table的时候,不能使用index语句
只能使用
Read table ~ with table key field1.
Read table ~ with key field2.
内表的访问速度的问题,用以前的数据库知识就能知道。
Binary search 二分查找。前提是表是排序的表。
Read table ~ with key col1 binary search.
-
- 内表的命令
-
-
- 内表的赋值
-
Move itab1 to itab2 .
Itab1 = itab2.
只复制了表头,不会带数据
Move itab1[] to itab2[].
Itab1,itab2 类型是一直的,按照字段顺序进行赋值。
如果字段顺序不同,就要使用以下语句:
Move-corresponding itab1 to itab2.
这里在赋值的时候,首先要确定是否存在表头,
Itab1 = itab2 是仅仅复制表头的操作,即move itab1 to itab2.
带表头的数据赋值给带表头的 move itab1[] to itab2[].
带表头的数据复制给不带表头的 move itab1[] to itab2.
复制内表的数据的时候,一定是带[]的move
-
-
- 内表的初始化
-
与其他变量一样的,内表是可以清空的。
初始化内表的命令有3个 clear、 refresh、free
同样这3个动作操作的时候,要区分内表是否带表头。
Clear语句返回release内存空间但不删除开始要求的的内存容量信息(initial size N)
带表头的内表:clear itab 只删除表头,如果要删除带表头的表体,要使用[] clear itab[].
不带表头的内表:clear itab 删除的是表体
refresh只删除内表的数据,无法删除内存空间。若想释放内存空间free语句。
Refresh itab.
Free itab.
对于这3个命令总结一下
Clear : clear itab 若果itab带表头,则清除的只是表头,数据仍然存在。如果不带表头,清除的是表体,如果想清除带表头的内表的表体,则应该写成clear itab[].
Refresh: refresh itab 清楚的是表体,即内表的数据。但不释放内存空间
Free: free itab 是释放内表的内存空间。
Refresh itab后,要判断itab是否是初始化状态,
If itab IS INITIAL.
……
ENDIF.
-
-
- 内表排序
-
表默认关键字排序
对hash表和标准表进行排序,用内表字典的关键字
Sort itab [ascending | descending ].
这个语句,对应的是内表定义时有关键字
表指定字段的排序
Sort itab [ascending | descending ]
By f1 [ascending | descending ]
....
fn [ascending | descending ].
F1 到Fn中间用空格
如果fn中的值存在null值,则排序会排除此列。
Stable sort
每次使用sort命令时排序序列号一直在变化,此时使用stable sort就会保留排序序列号,但是也会也会消耗更多的排序时间。
Sort itab ... stable.
存在相同数据的时候,重新排序后stable选项仍能保持原先的排序顺序。
【这个排序功能目前的经历中很少用到,等后面有使用需求的时候,再细细研究。】
-
-
- 内表属性
-
用describe语句可以确认内表属性
DESCRIBE TABLE itab [LINES gv_line] [OCCURS gv_init] [KIND gv_kind].
gv_line 返回内表的行数
Gv_init 返回内存初始的大小
Gv_kind 返回3中表类型中哪一种。
-
- 追加内表数据
追加内表数据有3个命令insert append collect
Insert 与append都是将数据插入最后一行。
但insert语句根据表类型的不同,执行结果不同。
Collect语句用于合计关键字相同的数字类型的字段。
-
-
- Insert 语句
-
追加一条数据
INSERT line INTO TABLE itab.
如果执行成功,sy-subrc就返回0.不成功则返回4.
利用关键字追加多条数据
INSERT lines OF itab1 FROM n1 TO n2 INTO TABLE itab2.
这里使用索引来定位itab1 的数据
利用索引追加一条数据
利用index语句,可以在index指定位置追加 一条数据,次方法不适用于hash表
Insert line into itab index idx.
这种语法很少用,知道就行了
同理:
Insert lines of itab1 into itab2 index idx.
APPEND 与Insert的区别
对于标准表来说,都是追加到最后一行
排序表,按照顺序追加。如果non-unique key 有重复的数据,会追加相同数据的上一行。
Hash表是按照hash值来追加
-
-
- Append语句
-
Insert可以按照索引和关键字来追加数据,
Append只能利用索引来追加,这样导致hash表就不能使用append
Insert 后面的关键字是into
Append的关键字是to
追加一条数据
Append line to itab.
追加多条数据
Append lines of itab1 to itab2.
Append lines of itab1 from n1 to n2 to itab2.
APPEND initial line 创建一个空内表后可以追加新数据
Append initial line to itab
Sorted by语句
Append gs_line to gt_itab sorted by col1.
使用了sorted by 那么该字段,就会按照descending来排序后追加数据
看到这里的一段程序也同时明白了一个参数的意思
Initial size N
就是该表初始化的大小为N行数据。
-
-
- Collect语句
-
使用collect语句可以合计内表中数字类型的字段【f, i, p】
collect wa into tab.
收先明确的是collect也是插入数据,只是在插入数据的时候,先要做一个判断
是否存在相同的关键字。
如果存在相同的关键字,只是把追加数据的值加到相同关键字的值上。
如果不存在相同的关键字,那么就直接插入数据。
-
- 修改内表数据
使用modify来修改内表的数据
利用关键字修改一条数据
当内表关键字并非唯一,存在重复数据的时候,modify则修改的是第一条数据。
MODIFY TABLE itab FROM wa [TRANSPORTING f1 f2...].
可以利用transporting语句修改指定字段的值。
Modify table gt_itab from gs_line.
会通过gs_line的关键字去定位修改数据,然后将不同的值修改掉。
利用where条件修改多条数据
修改多条数据
MODIFY itab FROM wa TRANSPORTING f1 f2 ... WHERE cond.
EG: modify gt_itab from gs_line index sy-tabix transporting carrname.
这段代码是可以执行的,直接能看到at new的作用
data: BEGIN OF gs_line, carrid type sflight-carrid, carrname type scarr-carrname, fldata type sflight-fldate, end of gs_line. data: gt_itab like table of gs_line. select carrid connid into CORRESPONDING FIELDS OF table gt_itab from sflight. LOOP at gt_itab into gs_line. WRITE : / gs_line-carrid, gs_line-carrname, gs_line-fldata. ENDLOOP. LOOP at gt_itab into gs_line. AT NEW carrid. select SINGLE carrname into gs_line-carrname from scarr where carrid = gs_line-carrid. modify gt_itab from gs_line index sy-tabix TRANSPORTING carrname. ENDAT. ENDLOOP. uline. LOOP at gt_itab into gs_line. WRITE : / gs_line-carrid, gs_line-carrname, gs_line-fldata. ENDLOOP. |
在LOOP循环中使用到了at new
At first 是内表第一条数据执行时
At new f1 字段f1值与上一条数据比较有变化时执行。
At end of f1 字段f1值与下一条数据有变化时执行
At last 是内表最后一条数据时执行。
利用索引修改一条数据
MODIFY itab FROM wa [INDEX idx] [TRANSPORTING f1 f2 ...].
SY-TABIX: 当前处理的是internal table 的第几笔
这里就是内表循环的计数器
Modify gt_itab From gs_line Index sy-tabix.
-
- 删除内表数据
- delete删除内表的一条数据
- 删除内表数据
可以利用delete删除内表的一条数据
对应行数据,还可以把关键字和索引作为查询条件查询后删除。
DELETE TABLE itab [FROM wa].
DELETE TABLE itab WITH TABLE KEY k1 = f1 ... kn = fn.
这里有一个关键点,表必须有with [unique|non-unique] key
否则就不能这样用
利用where条件删除多少条数据
Delete itab where cond.
Eg:
Delete gt_itab where col1 = 2 and col2 = 4.
-
-
- 利用索引删除内表数据
-
Delete itab index idx.
DELETE itab FROM n1 TO n2.
DELETE itab FROM n1.
DELETE itab TO n2.
这几个语句只针对索引表,即标准表和排序表,hash表就没法使用了。
-
-
- 删除重复行
-
利用ADJACENT DUPLICATE 语句删除重复行
在删除重复行之前,要对表进行排序,使用sort语句进行排序
才能使用
DELETE ADJACENT DUPLICATE ENTRIES FROM itab
[COMPARING f1 f2 ...| ALL FIELDS].
不使用comparing语句会删除关键字重复的数据
在没有定义关键字的情况下,前几个字符串类型的字段将成为关键字。
-
- 读取内表数据
利用read读取内表数据
当存在表头时,对应的数据会保存到表头中,否则会保存到workarea中
-
-
- 利用关键字读内表
-
READ TABLE itab FROM wa INTO result.
READ TABLE itab WITH TABLE KEY k1 = f1 ... kn=fn INTO result.
代码片:
gv_itabwa-col1 = 2.*【workarea】 read TABLE gv_itab1 from gv_itabwa into gv_itabwa. WRITE: / gv_itabwa-col1, gv_itabwa-col2. |
-
-
- 利用所有读内表
-
READ TABLE itab INDEX idx INTO result.
EG:
READ TABLE gt_itab INTO gs_itabwa INDEX 1.