LOOP AT itab - Basic Form

LOOP AT itab result [cond 条件]. 
  ... 
  [AT ... 
    ... 
  ENDAT.] 
  ... 
ENDLOOP.

语句LOOP AT itab的这个变体对每个读取行执行一次LOOP和ENDLOOP之间的语句块。

◾ 输出响应结果确定读取行内容的方式和位置。
◾ 执行循环时使用的表键可以在条件中确定。要么读取所有行,要么指定条件来限制读取哪些行。
◾ AT…ENDAT可用于定义控制级处理的控制结构。

如果将内部表指定为函数方法、构造函数表达式或表表达式的返回值或结果,则会在循环期间保持该值。之后,将无法再访问内部表。

如果在USING key之后没有指定明确的表键名称,则读取行的顺序取决于表类别,如下所示:

◾ 标准表和排序表

通过主表索引中的行号升序读取行。在每个循环过程中,系统字段sy-tabix包含主表索引中当前行的行号。

◾ 哈希表

行按照插入表中的顺序以及语句sort后使用的排序顺序进行处理。在每个循环过程中,系统字段sy-tabix包含值0。

循环将继续运行,直到读取了满足条件的所有表行,或使用语句退出。如果找不到合适的行或内部表为空,则根本不会运行循环。

系统字段

此语句的变体LOOP AT设置系统字段sy-tabix的值:

◾ 在索引表的每个循环中,以及在关联表索引中的当前表行的行号上使用排序键时,都会进行传递。

◾ 在哈希表中以及对值0使用哈希键时。

LOOP AT不会修改sy-subrc。使用ENDLOOP离开循环后,sy-tabix设置为进入循环前的值,适用于sy-subrc:

sy-subrc含义

0循环至少运行了一次。

4循环根本没有运行。

系统字段sy-tfill和sy-tleng也会被填充。

在循环中更改内部表

如果在LOOP的语句块中插入或删除行,则会产生以下影响:在索引表上循环或使用排序键的情况下,插入或删除的行相对于当前行的位置由相应表索引中的行号决定。对于哈希表上的循环,如果使用哈希键,则位置取决于插入顺序。

◾ 如果在当前行之后插入行,则在后续循环过程中处理这些新行。可能会导致无休止的循环。

◾ 如果在当前行之后删除行,则在后续循环过程中不再处理删除的行。

◾ 如果在当前行之前插入行,则每个插入行的内部循环计数器增加一个。这会影响sy-tabix,它也会增加(在索引表上循环或使用排序键的情况下,在随后的循环过程中)。

◾ 如果删除了当前行之前的一行或多行,则内部循环计数器将每删除一行减少一个。对于索引表上的循环或使用排序键的情况,这会影响后续循环过程中的sy-tabix,sy-tabix也会相应减少。

根据上述规则,使用此表替换LOOP中的整个表体将导致循环在下一个循环过程中退出。如果之后将新行添加到表中,则尤其如此。由于这通常会产生不可预测的程序行为,因此无法在循环中以更改模式访问整个表体。如果静态地知道这一点,则类和具有静态地知道的次键的LOOPS中会发生语法错误。否则,出于兼容性原因,语法检查只会返回警告。但是,在运行时,当使用CLEAR、FREE、LOCAL、REFRESH、SORT、DELETE…WHERE等语句以及对itab的所有类型的赋值替换整个表体时,大多数情况下都会发生运行时错误。

ABAP指南编程指南

循环处理

笔记

◾ 如果使用引用变量指定内部表itab,则使用条目中引用的表完全执行循环。对引用变量的任何更改都不会对循环产生影响。在循环完成之前,无法从垃圾回收器中删除关联的对象。如果表由字段符号表示,则也是如此。在循环中实现字段符号后,当输入loop时,仍会使用链接到字段符号的表进行迭代。

◾ 没有隐式选择合适的键或索引。使用的表键或表索引总是唯一指定的。如果有合适的辅助表键但未使用此表键,语法检查将发出警告。应使用钥匙清除此警告。但是,在特殊情况下,可以使用杂注绕过它。

◾ 通常,读取LOOP中的多行比使用语句read TABLE或表表达式读取多个单独的行要好。

◾ 没有可以反转读取行顺序的添加。这必须使用DO、WHILE或FOR迭代来完成,在迭代中,使用read TABLE或表表达式读取各行。然后必须在循环中相应地编程循环条件(参见可执行示例)。
◾ 由于兼容性原因,当替换表体时,循环中没有运行时的唯一情况是在没有指定的次键的情况下读取直接指定的表,并且为输出响应结果指定了工作区。
◾ 使用特殊变量LOOP AT mesh_path,可以在网格路径的最后一个节点上执行循环。
◾ 在某些构造函数表达式中,可以使用迭代表达式和FOR进行进一步形式的表迭代。

案例

DATA name TYPE scarr-carrname VALUE '*'. 
cl_demo_input=>request( CHANGING field = name ). 

DATA: scarr_tab TYPE SORTED TABLE OF scarr 
                WITH UNIQUE KEY carrname, 
      spfli_tab TYPE SORTED TABLE OF spfli 
                WITH NON-UNIQUE KEY carrid. 
SELECT * 
       FROM scarr 
       INTO TABLE @scarr_tab. 

SELECT * 
       FROM spfli 
       INTO TABLE @spfli_tab. 

LOOP AT scarr_tab ASSIGNING FIELD-SYMBOL(<scarr_line>) 
                  WHERE carrname CP name. 
  LOOP AT spfli_tab INTO DATA(spfli_line) 
                    WHERE carrid = <scarr_line>-carrid. 
    cl_demo_output=>write_data( spfli_line ). 
  ENDLOOP. 
ENDLOOP. 
cl_demo_output=>display( ).