在 VALUE 的左侧和右侧使用相同的 itab 会导致空 table。为什么?

Using the same itab on left and right side of VALUE results in empty table. Why?

这是给你的……

为什么这段代码会导致空 table gt_test2

gt_test2 = VALUE #(
  FOR gs_test1 IN gt_test1 WHERE ( v3 = gs_test3-v3 AND v4 = gs_test3-v4 )
  FOR gs_test2 IN gt_test2 WHERE ( v1 = gs_test1-v1 AND v2 = gs_test1-v2 )
  ( gs_test2 )
).
WRITE / lines( gt_test2 ).

这个结果正确吗?

DATA: gt_test2_2 LIKE gt_test2.
gt_test2_2 = VALUE #(
  FOR gs_test1 IN gt_test1 WHERE ( v3 = gs_test3-v3 AND v4 = gs_test3-v4 )
  FOR gs_test2 IN gt_test2 WHERE ( v1 = gs_test1-v1 AND v2 = gs_test1-v2 )
  ( gs_test2 )
).
WRITE / lines( gt_test2_2 ).

这是 ABAP 中的错误吗!?我一直认为首先评估表达式的右侧,然后将其分配给左侧。然而,在这个 ABAP 构造中,似乎在计算右侧时以某种方式在内部使用了左侧,这导致了不正确的结果。

最简单的工作示例。

REPORT ZZZ.

TYPES: BEGIN OF ty_test1,
  v1 TYPE char40,
  v2 TYPE char6,
  v3 TYPE char6,
  v4 TYPE char32,
  END OF ty_test1,
  BEGIN OF ty_test2,
    v1 TYPE char40,
    v2 TYPE char6,
    v5 TYPE numc3,
  END OF ty_test2,
  BEGIN OF ty_test3,
    v3 TYPE char6,
    v4 TYPE char32,
  END OF ty_test3.
TYPES: tty_test1 TYPE STANDARD TABLE OF ty_test1 WITH EMPTY KEY,
  tty_test2 TYPE STANDARD TABLE OF ty_test2 WITH EMPTY KEY.

INITIALIZATION.
  DATA(gt_test1) = VALUE tty_test1(
    ( v1 = '1' v2 = '007001' v3 = '0012345678' v4 = '001061' )
    ( v1 = '2' v2 = '007001' v3 = '0999999953' v4 = '001061' )
  ).
  DATA(gt_test2) = VALUE tty_test2(
    ( v1 = '1' v2 = '007001' v5 = '10' )
    ( v1 = '2' v2 = '007001' v5 = '15' )
  ).
  DATA(gs_test3) = VALUE ty_test3( v3 = '0999999953' v4 = '001061' ).

START-OF-SELECTION.
*  DATA: gt_test2_2 LIKE gt_test2.
*  gt_test2_2 =
  gt_test2 =
  VALUE #(
    FOR gs_test1 IN gt_test1 WHERE ( v3 = gs_test3-v3 AND v4 = gs_test3-v4 )
    FOR gs_test2 IN gt_test2 WHERE ( v1 = gs_test1-v1 AND v2 = gs_test1-v2 )
    ( gs_test2 )
  ).
  WRITE / lines( gt_test2 ).
*  WRITE / lines( gt_test2_2 ).

使用构造函数表达式,首先清除目标数据对象,因此您遇到的结果是:内部 table gt_test2FOR 循环时为空。

在您的情况下,您可以使用在清除目标数据对象之前调用的 LET 将内部 table 传输到辅助内部 table。

ABAP Documentation - "VALUE, Internal Tables" :

If the VALUE operator is used as the source of an assignment to an internal table, it is first initialized after the evaluation of a possible LET expression or is assigned the content of itab. Then, line_spec data is then evaluated and inserted directly into the target table.

In assignments of constructor expressions to an internal table, its existing lines cannot be used directly as an argument in line_spec. This is because this table is deleted before line_spec is evaluated or overwritten by the content of itab. If the entire internal table or lines from the left side are needed on the right side, however, they can be saved in local helper variables using a LET expression, since this expression is evaluated first.

Sandra 是对的,但是您可以使用 FILTER op 来克服这个限制,它没有这种令人失望的拦截器。 如果你想避免创建新的 table,你可以这样重新考虑你的样本:

...
TYPES: tty_test1 TYPE SORTED TABLE OF ty_test1 WITH NON-UNIQUE KEY primary_key COMPONENTS v1 v2
                                               WITH NON-UNIQUE SORTED KEY filt COMPONENTS v3 v4,
       tty_test2 TYPE SORTED TABLE OF ty_test2 WITH NON-UNIQUE KEY primary_key COMPONENTS v1 v2.
...

gt_test1 = FILTER #( gt_test1 USING KEY filt WHERE v3 = gs_test3-v3 AND v4 = gs_test3-v4 ).
gt_test2 = FILTER #( gt_test2 IN gt_test1 WHERE v1 = v1 AND v2 = v2 ).