辅助密钥完全指定但未使用时发出警告,但如果指定则错误

Jag*_*ger 5 sap abap

我很困惑.如果我编译下面的代码

REPORT zzy.

CLASS lcl_main DEFINITION FINAL CREATE PRIVATE.
  PUBLIC SECTION.
    CLASS-METHODS:
      class_constructor,
      main.
  PRIVATE SECTION.
    TYPES: BEGIN OF t_record,
      transid TYPE sy-index,
      item1   TYPE char20,
      value1  TYPE p LENGTH 7 DECIMALS 2,
      value2  TYPE p LENGTH 7 DECIMALS 2,
      value3  TYPE p LENGTH 7 DECIMALS 2,
      value4  TYPE p LENGTH 7 DECIMALS 2,
    END OF t_record,
    tt_record TYPE STANDARD TABLE OF t_record WITH NON-UNIQUE KEY transid item1 WITH UNIQUE HASHED KEY sec_key COMPONENTS value1 value2 value3.
    CLASS-DATA:
      mt_record TYPE tt_record.
ENDCLASS.

CLASS lcl_main IMPLEMENTATION.
  METHOD class_constructor.
    DO 10 TIMES.
      INSERT VALUE t_record( transid = sy-index item1 = |Item{ sy-index }| value1 = sy-index value2 = sy-index / 2 value3 = sy-index / 4 value4 = 0 )
        INTO TABLE mt_record.
    ENDDO.
  ENDMETHOD.

  METHOD main.
    DATA:
      l_secs TYPE i,
      l_millisecs TYPE i,
      l_start TYPE timestampl,
      l_end   TYPE timestampl,
      l_diff  LIKE l_start.
    GET TIME STAMP FIELD l_start.
    LOOP AT mt_record INTO DATA(ls_record)
      WHERE value1 = '100.00' AND value2 = '150.0' AND value3 = '10.0'.

      ASSERT 1 = 1.

    ENDLOOP.
    GET TIME STAMP FIELD l_end.
    l_diff = l_end - l_start.

    WRITE: / l_diff.
  ENDMETHOD.
ENDCLASS.

START-OF-SELECTION.
  lcl_main=>main( ).
Run Code Online (Sandbox Code Playgroud)

我收到以下警告

程序ZZY
辅助键"SEC_KEY"已完全指定.但是,主
键用于访问.检查使用"SEC_KEY"访问是否更
有效

但如果我指定此键,USING KEY sec_key那么我得到编译时错误!

REPORT zzy.

CLASS lcl_main DEFINITION FINAL CREATE PRIVATE.
  PUBLIC SECTION.
    CLASS-METHODS:
      class_constructor,
      main.
  PRIVATE SECTION.
    TYPES: BEGIN OF t_record,
      transid TYPE sy-index,
      item1   TYPE char20,
      value1  TYPE p LENGTH 7 DECIMALS 2,
      value2  TYPE p LENGTH 7 DECIMALS 2,
      value3  TYPE p LENGTH 7 DECIMALS 2,
      value4  TYPE p LENGTH 7 DECIMALS 2,
    END OF t_record,
    tt_record TYPE STANDARD TABLE OF t_record WITH NON-UNIQUE KEY transid item1 WITH UNIQUE HASHED KEY sec_key COMPONENTS value1 value2 value3.
    CLASS-DATA:
      mt_record TYPE tt_record.
ENDCLASS.

CLASS lcl_main IMPLEMENTATION.
  METHOD class_constructor.
    DO 10 TIMES.
      INSERT VALUE t_record( transid = sy-index item1 = |Item{ sy-index }| value1 = sy-index value2 = sy-index / 2 value3 = sy-index / 4 value4 = 0 )
        INTO TABLE mt_record.
    ENDDO.
  ENDMETHOD.

  METHOD main.
    DATA:
      l_secs TYPE i,
      l_millisecs TYPE i,
      l_start TYPE timestampl,
      l_end   TYPE timestampl,
      l_diff  LIKE l_start.
    GET TIME STAMP FIELD l_start.
    LOOP AT mt_record INTO DATA(ls_record) USING KEY sec_key
      WHERE value1 = '100.00' AND value2 = '150.0' AND value3 = '10.0'.

      ASSERT 1 = 1.

    ENDLOOP.
    GET TIME STAMP FIELD l_end.
    l_diff = l_end - l_start.

    WRITE: / l_diff.
  ENDMETHOD.
ENDCLASS.

START-OF-SELECTION.
  lcl_main=>main( ).
Run Code Online (Sandbox Code Playgroud)

程序ZZY
键"SEC_KEY"是"HASHED KEY"类型的辅助键.在这些情况下必须提供所有关键组件

我在这做错了什么?

vwe*_*ert 4

如条件的语法文档LOOP中所述,

如果指定了辅助表键,则还指定的任何 WHERE 条件都必须是可优化的。否则会发生语法错误或引发异常。

当深入研究什么是可比较的、可优化的、什么不是的规则时,一定要准备好足够的咖啡或任何你喜欢的兴奋剂,因为这是乏味的事情。在这种情况下,指定的比较必须包括 aTYPE P和 a TYPE C(如'100.00') - 这应该是可能的 - 但此外,长度必须匹配,但它们不匹配。甚至文档指出

由于比较规则的复杂性(特别是对于基本数据类型),构建一组详细说明比较类型何时与左操作数的数据类型匹配的规则并不是一个好主意。

底线:使用完全相同的类型进行键访问,切勿依赖隐式转换。如果您使用与valueN列相同的类型声明变量或常量并在比较中使用它,它就会起作用。