仅向 CDS 中的数字字段添加前导零?

Add leading zeros only to numeric field in CDS?

在我的 AS ABAP 7.50 系统中,我有一个 table,其中 material 长度为 18,我需要通过 CDS 公开它,就好像 material 长度是 40 一样在 S/4。系统中的 material ID 可以是数字(带前导零)或字母数字。 material 字段需要转换为 MATNR40,如果 ID 是数字,则需要将前导零添加到 40 个字符。

首先,我尝试了`lpad。但当然,它还会将前导零添加到字母数字值中:

lpad( cast(matnr as matnr40), 40, '0' ) as material_long,

然后我添加了一个 case 但我无法使条件按预期工作。正如康斯坦丁在评论中确认的那样,我尝试在此处使用正则表达式是不可能的:

case when matnr like '%[^0-9.]%'
     then lpad( cast(matnr as matnr40), 40, '0' )
     else cast(matnr as matnr40)
end as material_long,

CDS 本身是否有针对此问题的解决方案?

来源table:

MATNR18 Description
000000000000000142 Numeric ID material
MATERIAL_2 Alphanumeric ID

预期结果:

MATNR40 Description
0000000000000000000000000000000000000142 Numeric ID material
MATERIAL_2 Alphanumeric ID

由于 CDS 语法中的功能有限,我看到的唯一方法是嵌套 10 个 REPLACE 函数来删除数字并将结果与​​初始字符串进行比较。如果它是初始的,那么你只有数字,所以你可以 LPAD 他们用零。如果不是 - 使用原始值。

这是我的代码:

@AbapCatalog.sqlViewName: 'Z_V_TEST'
@AbapCatalog.compiler.compareFilter: true
@AbapCatalog.preserveKey: true
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'Test'
define view Z_TEST as select from /bi0/mmaterial {
    cast(
      case replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(material,
        '0', ''), '1', ''), '2', ''), '3', ''), '4', ''), '5', ''), '6', ''), '7', ''), '8', ''), '9', '')
        when ''
        then lpad(material, 40, '0')
        else material
      end as abap.char(40)
    ) as MATERIAL_ALPHA,
    material
}

结果是:

REPORT Z_TEST.

    select *
    from Z_V_TEST
    where material in ('LAMP', '000000000000454445')

      into table @data(lt_res)
    .
    cl_demo_output=>display( lt_res ).



MATERIAL_ALPHA                           | MATERIAL 
-----------------------------------------+-------------------
0000000000000000000000000000000000454445 | 000000000000454445 
LAMP                                     | LAMP 

这是 7.55 的做法,当 custom entities 被引入时:

  1. 创建自定义实体

    @EndUserText.label: 'Material List'
    @ObjectModel.query.implementedBy: 'ABAP:ZCL_MATERIAL_ZEROED'
    @Search.searchable: false
    define custom entity zcds_mat {
      key matnr  : abap.char( 40 );
          maktx  : abap.char( 40 );
    }
    
  2. 为其创建实现class

     CLASS ZCL_MATERIAL_ZEROED DEFINITION
       PUBLIC
       FINAL
       CREATE PUBLIC .
    
       PUBLIC SECTION.
         INTERFACES if_rap_query_provider.
       PROTECTED SECTION.
       PRIVATE SECTION.
     ENDCLASS.
    
     CLASS ZCL_MATERIAL_ZEROED IMPLEMENTATION.
       METHOD if_rap_query_provider~select.
         DATA: it_result   TYPE  TABLE OF zcustomer_zero. "Internal table to be returned , easier to handle return if internal table is as same type of our data definition
         DATA: lv_param    TYPE string."Local variable to fetch and save parameter value
         TRY.
             TRY.
                 IF io_request->is_data_requested( ). "Fetching incoming data
                   io_request->get_paging( ).
    
                   SELECT matnr maktx FROM makt INTO TABLE @it_result.
    
                   LOOP AT it_result ASSIGNING FIELD-SYMBOL(<fldsym>).
                     <fldsym>-matnr = | { <fldsym>-matnr ALPHA = OUT } |.
                   ENDLOOP.
    
                   io_response->set_total_number_of_records( lines( it_result ) ). "setting the total number of records which will be sent
                   io_response->set_data( it_result  ). "returning the data as internal table
                 ENDIF.
               CATCH cx_a4c_rap_query_provider INTO DATA(lx_exc). "CX_A4C_RAP_QUERY_PROVIDER is now deprecated so use CX_RAP_QUERY_PROVIDER
    
             ENDTRY.
           CATCH cx_rfc_dest_provider_error INTO DATA(lx_dest).
         ENDTRY.
       ENDMETHOD.
     ENDCLASS.
    

这里我们通过 string templates

添加前导零

您不能直接使用自定义实体,但您可以在 OData service 中使用它,以防您有此意图。