ABAP CHECK 语句

205 阅读4分钟

介绍

在写接口函数的时候,采用了 ALV 报表中的 CHECK 语句,导致报错了整个函数就返回了,并没有将后台数据打印到后台表中。因此将 CHECK 的用法记录一下笔记。

CHECK 语句

CHECK 语句根据条件终止循环传递。如果 CHECK 语句中的条件被评估为 false,则忽略 CHECK 语句之后语句块中的所有剩余语句,则进程将退出当前循环跳过并处理下一个循环。 CHECK 语句中的条件可以是任何逻辑表达式。

例如:

CHECK input_value > 0 AND input_value <= 100.
CHECK input_value <= 0 OR input_value >= 200.

image.png

使用方法

循环块内:

CHECK <log_exp>.

带有逻辑数据库的报表:

CHECK sel.

CHECK SELECT-OPTIONS

检查由语句 SELECT-OPTIONS sel 要求的选择标准。如果这个检查的结果是否定的,那么这个事件的处理将被终止,任何下属数据库表的 GET 事件也不会被处理。

在各种循环中的使用:

DO … ENDDO
WHILE … ENDWHILE
LOOP … ENDLOOP
SELECT … ENDSELECT
*&---------------------------------------------------------------------*  
*& Report ZCHECK  
*&---------------------------------------------------------------------*  
*&  
*&---------------------------------------------------------------------*  
REPORT zcheck.  
  
DO 10 TIMES.  
  CHECK sy-index MOD 2 = 0.  
  WRITE / sy-index.  
ENDDO.

比如取 10 以内的整数:

image.png

如果语句 CHECK 位于一个循环之外,并且 log_expfalse,那么该语句将终止当前的处理块。可以为 log_exp 指定任何逻辑表达式。

*&---------------------------------------------------------------------*  
*& Report ZCHECK  
*&---------------------------------------------------------------------*  
*&  
*&---------------------------------------------------------------------*  
REPORT zcheck.  
  
DATA: lv_sum TYPE i.  
  
CHECK lv_sum IS NOT INITIAL.  

" DO 之后的循环将不会执行
DO 10 TIMES.  
  lv_sum = sy-index.  
  CHECK sy-index MOD 2 = 0.  
  WRITE / sy-index.  
ENDDO.

在处理块退出后,运行环境的进行方式与处理块以正常方式退出时相同(除了事件块 LOAD-OF-PROGRAMreporting event block GET之外)。特别是,程序的输出参数被传递给绑定的实际参数。

  • 事件块 LOAD-OF-PROGRAM 不能使用 CHECK 退出。
  • 在使用 CHECK 退出 Report 事件块 GET 后,相关逻辑数据库的层次结构中的下级节点不再被处理。逻辑数据库读取当前节点的下一行,或者下一个更高的节点,如果它已经达到了层次结构级别的终点。

检查 SELECT-OPTIONS 的所有选择,其中 FOR 后面的参考字段属于当前表 dbtab 。而且它只在GET 事件后调用。

建议仅使用 RETURN 退出程序

例如在一个方法内的 CHECK 语句就像一个有条件的 RETURN 语句,所以要确定任何给定的 CHECK 语句的效果可能会很混乱。

在程序(方法、功能模块、子例程)中,CHECK log_exp 在循环外的工作方式与以下方式相同:

IF NOT log_exp.  
  RETURN.  
ENDIF.

例如:

IF NOT sy-index MOD 2 = 0.
    RETURN.
ENDIF.

用于退出处理块的语句 CHECK 的另一个变体是 CHECK SELECT-OPTIONS,只能在逻辑数据库的 GET 事件块中使用。

如果不是退出程序,可以使用 CONTINUE 代替:

IF not condition.
  CONTINUE.
ENDIF.

在上面的例子中,即可以使用这段逻辑替换,也能打印出 1-10 之间的偶数:

REPORT zcheck.  
  
*DATA: lv_sum TYPE i.  
*CHECK lv_sum IS NOT INITIAL.  
  
DO 10 TIMES.  
*  CHECK sy-index MOD 2 = 0.  
  IF sy-index MOD 2 = 0.  
    WRITE / sy-index.  
  ELSE.  
*    RETURN.  
    CONTINUE.  
  ENDIF.  
  
ENDDO.

注意选择易于解释的逻辑表达式的形式。由于关键字 CONTINUE 只能在循环中使用,现在继续到下一个迭代实例的意图是不明确的。

如果出现 exception 情况,该怎么做?

exception 情况下,你可以通过使用伪注释 "#EC CHECK_IN_LOOP " 来抑制这一问题,该注释应放在 CHECK 语句本身之后:

LOOP AT tadir ASSIGNING FIELD-SYMBOL(<tadir>).
  CHECK <tadir>-delflag = abap_true. "#EC CHECK_IN_LOOP
ENDLOOP.

CHECK 语句之前:

LOOP AT tadir ASSIGNING FIELD-SYMBOL(<tadir>).
  CHECK <tadir>-delflag = abap_true.
  "some more code...
ENDLOOP.

改变之后:

LOOP AT tadir ASSIGNING FIELD-SYMBOL(<tadir>).
  IF <tadir>-delflag = abap_false.
    CONTINUE.
  ENDIF.
  "some more code...
ENDLOOP.

请注意,在此示例中,表达代码背后意图的最简洁方法是完全删除循环内的语句,并将其替换为 LOOP 语句中的 WHERE 子句:

LOOP AT tadir ASSIGNING FIELD-SYMBOL(<tadir>) WHERE delflag = abap_false.
  "some more code...
ENDLOOP.

总结

CHECK 如果条件失败,它只是忽略剩余的行,并退出存在 CHECK 命令的模块。在循环中使用的话,就会退出当前循环,如果在循环外使用,就会退出整个方法或子例程。所以在不明确检查条件,或者检查条件过多的情况下,建议使用 IF + RETURN/CONTINUE 进行代替。

参考链接: