ABAP Nested控制

ABAP Nested控制

ℹ️概述
DO和WHILE语句可以被测试以及与其他循环形式组合。每个嵌套循环将具有由系统创建和监视的自己的SY-INDEX。嵌套循环允许我们在一个循环内部包含另一个或多个循环。

🔧 语法格式

嵌套DO循环语法

1
2
3
4
5
6
DO [n TIMES].
<statement block n>.
DO [m TIMES].
<statement block m>.
ENDDO.
ENDDO.

嵌套WHILE循环语法

1
2
3
4
5
6
WHILE <condition1>.
<statement block 1>.
WHILE <condition2>.
<statement block 2>.
ENDWHILE.
ENDWHILE.

混合嵌套语法

1
2
3
4
5
6
DO [n TIMES].
<statement block 1>.
WHILE <condition>.
<statement block 2>.
ENDWHILE.
ENDDO.

📊 嵌套循环执行流程



graph TD
    A[开始外层循环] --> B{外层条件}
    B -->|满足| C[执行外层语句块]
    B -->|不满足| G[结束外层循环]
    C --> D{进入内层循环}
    D --> E{内层条件}
    E -->|满足| F[执行内层语句块]
    E -->|不满足| H[退出内层循环]
    F --> I{继续内层循环?}
    I -->|是| E
    I -->|否| C
    H --> C
    G --> J[继续执行]


📝 示例代码

1. 简单嵌套DO循环

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
REPORT ys_sep_15.
DATA:
a1 TYPE i,
b1 TYPE i.
a1 = 0.
b1 = 0.

DO 2 TIMES.
a1 = a1 + 1.
WRITE: / 'Outer', a1.
DO 10 TIMES.
b1 = b1 + 1.
WRITE: ' Inner', b1.
ENDDO.
ENDDO.

输出

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Outer 1
Inner 1
Inner 2
Inner 3
Inner 4
Inner 5
Inner 6
Inner 7
Inner 8
Inner 9
Inner 10
Outer 2
Inner 11
Inner 12
Inner 13
Inner 14
Inner 15
Inner 16
Inner 17
Inner 18
Inner 19
Inner 20

2. 嵌套WHILE循环

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
REPORT ys_sep_15.
DATA:
lv_outer TYPE I VALUE 1,
lv_inner TYPE I VALUE 1.

WHILE lv_outer <= 3.
WRITE: / 'Outer loop:', lv_outer.

WHILE lv_inner <= 2.
WRITE: ' Inner loop:', lv_inner.
lv_inner = lv_inner + 1.
ENDWHILE.

lv_outer = lv_outer + 1.
lv_inner = 1. " 重置内层计数器
ENDWHILE.

3. 混合嵌套循环

1
2
3
4
5
6
7
8
9
10
11
12
13
14
REPORT ys_sep_15.
DATA:
lv_counter TYPE I VALUE 1.

DO 3 TIMES.
WRITE: / 'Outer DO loop:', sy-index.

WHILE lv_counter <= 3.
WRITE: ' Inner WHILE loop:', lv_counter.
lv_counter = lv_counter + 1.
ENDWHILE.

lv_counter = 1. " 重置计数器
ENDDO.

🔍 嵌套循环的执行机制

SY-INDEX的行为

每个嵌套循环都有自己的SY-INDEX:

1
2
3
4
5
6
DO 2 TIMES.
WRITE: / 'Outer loop - SY-INDEX:', sy-index.
DO 3 TIMES.
WRITE: ' Inner loop - SY-INDEX:', sy-index.
ENDDO.
ENDDO.

输出

1
2
3
4
5
6
7
8
Outer loop - SY-INDEX: 1
Inner loop - SY-INDEX: 1
Inner loop - SY-INDEX: 2
Inner loop - SY-INDEX: 3
Outer loop - SY-INDEX: 2
Inner loop - SY-INDEX: 1
Inner loop - SY-INDEX: 2
Inner loop - SY-INDEX: 3

执行次数计算

对于嵌套循环,总执行次数 = 外层循环次数 × 内层循环次数

外层次数 内层次数 总次数
2 3 6
5 10 50
n m n × m

⚠️ 注意事项

1. 性能考虑

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
" ❌ 性能差:不必要的三层嵌套
DO 1000 TIMES.
DO 1000 TIMES.
DO 1000 TIMES.
" 复杂操作
ENDDO.
ENDDO.
ENDDO.

" ✅ 性能优化:减少嵌套层次或使用数据表
DATA: lt_large TYPE TABLE OF i.

DO 1000 TIMES.
APPEND sy-index TO lt_large.
ENDDO.

LOOP AT lt_large INTO DATA(lv_value).
DO 1000 TIMES.
" 处理数据
ENDDO.
ENDLOOP.

2. 无限循环风险

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
" ❌ 危险:内层循环可能无限
DO.
DO.
" 忘记添加退出条件
ENDDO.
ENDDO.

" ✅ 安全:添加明确的退出条件
DO 10 TIMES.
DO 5 TIMES.
" 处理逻辑
IF some_condition.
EXIT.
ENDIF.
ENDDO.
ENDDO.

3. 变量作用域

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
" ✅ 正确:注意变量作用域
DATA: lv_outer_var TYPE I.

DO 3 TIMES.
DATA: lv_inner_var TYPE I VALUE 1.
lv_outer_var = sy-index.

WRITE: / 'Outer:', lv_outer_var.
WRITE: ' Inner initial:', lv_inner_var.

DO 2 TIMES.
lv_inner_var = lv_inner_var + 1.
WRITE: ' Inner now:', lv_inner_var.
ENDDO.
ENDDO.

💡 使用场景

1. 矩阵处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
" 处理二维数据
DATA:
lt_matrix TYPE TABLE OF TABLE OF i,
lv_row TYPE I,
lv_col TYPE I.

" 填充矩阵
DO 5 TIMES.
DATA: lt_row TYPE TABLE OF i.
DO 5 TIMES.
APPEND sy-index TO lt_row.
ENDDO.
APPEND lt_row TO lt_matrix.
ENDDO.

" 读取矩阵
LOOP AT lt_matrix INTO DATA(lt_row).
DO 5 TIMES.
lv_col = sy-index.
WRITE: / lt_row[ lv_col ].
ENDDO.
ENDLOOP.

2. 多层条件检查

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
" 检查多层数据
SELECT * FROM vbak INTO TABLE @DATA(lt_vbak)
WHERE vkorg = '1000'.

LOOP AT lt_vbak INTO DATA(lwa_vbak).
DO 3 TIMES. " 检查3个订单项
SELECT * FROM vbap INTO TABLE @DATA(lt_vap)
WHERE vbeln = lwa_vbak-vbeln
AND posnr = sy-index.

IF sy-subrc = 0.
LOOP AT lt_vap INTO DATA(lwa_vap).
WRITE: / 'Order:', lwa_vbak-vbeln,
'Item:', lwa_vap-posnr,
'Material:', lwa_vap-matnr.
ENDLOOP.
ENDIF.
ENDDO.
ENDLOOP.

3. 分组处理

1
2
3
4
5
6
7
8
9
" 按组处理数据
DO 3 TIMES. " 处理3个不同的组
WRITE: / 'Processing Group:', sy-index.

DO 10 TIMES. " 处理每个组的10个项目
WRITE: ' Item:', sy-index.
" 具体处理逻辑
ENDDO.
ENDDO.

🔧 优化技巧

1. 减少嵌套层数



graph TD
    A[原始嵌套] --> B[优化思路]
    B --> C[使用数据结构]
    B --> D[使用辅助方法]
    B --> E[使用循环控制]
    
    A --> A1[DO 10]
    A1 --> A2[DO 5]
    A2 --> A3[DO 3]
    A3 --> A4[处理数据]
    
    C --> C1[使用内表]
    D --> D1[提取方法]
    E --> E1[使用EXIT]

2. 使用EXIT提前退出

1
2
3
4
5
6
7
8
9
10
11
12
13
" 使用EXIT避免不必要的循环
DO 100 TIMES.
DO 100 TIMES.
IF some_condition.
EXIT. " 退出内层循环
ENDIF.
" 处理数据
ENDDO.

IF another_condition.
EXIT. " 退出外层循环
ENDIF.
ENDDO.

3. 使用CONTINUE跳过

1
2
3
4
5
6
7
8
9
10
11
12
13
14
" 使用CONTINUE跳过特定迭代
DO 10 TIMES.
IF some_skip_condition.
CONTINUE. " 跳过当前迭代
ENDIF.

DO 5 TIMES.
IF another_skip_condition.
CONTINUE. " 跳过内层迭代
ENDIF.

" 处理数据
ENDDO.
ENDDO.

💡 最佳实践

1. 嵌套设计原则

  • 保持嵌套层次简单(建议不超过3层)
  • 确保每个循环都有明确的退出条件
  • 考虑使用辅助函数减少嵌套

2. 性能优化

  • 避免在深层嵌套中进行复杂操作
  • 考虑使用索引或缓存优化数据访问
  • 适当使用EXIT和CONTINUE控制流程

3. 代码可读性

  • 使用有意义的变量名
  • 添加必要的注释说明嵌套逻辑
  • 保持代码缩进清晰

4. 错误处理

  • 为嵌套循环添加适当的错误处理
  • 考虑资源释放和内存管理
  • 避免无限循环的风险