Добавлять ведущие нули только в числовое поле в CDS?

В моей системе AS ABAP 7.50 у меня есть таблица, в которой длина материала равна 18, и мне нужно открыть ее через CDS, как если бы длина материала была 40, как в S / 4. Идентификаторы материалов в системе могут быть числовыми (с ведущими нулями) или буквенно-цифровыми. Поле материала должно быть преобразовано в MATNR40, и если идентификатор числовой, необходимо добавить начальные нули до 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?

Исходная таблица:

MATNR18 Description
000000000000000142 Numeric ID material
MATERIAL_2 Alphanumeric ID

Ожидаемый результат:

MATNR40 Description
0000000000000000000000000000000000000142 Numeric ID material
MATERIAL_2 Alphanumeric ID

person RaTiO    schedule 11.01.2021    source источник
comment
Данные просто считываются (предел / смещение / все) или интересующий столбец также фильтруется или используется в более сложных запросах? Потому что, если данные, которые вы пытаетесь преобразовать, используются в любых даже простых фильтрах (например, OData), эти фильтры, вероятно, не смогут понять ваши приведения, структуры case, регулярное выражение и все остальное. Ваш изначально составленный из лучших побуждений и краткий код CDS может затем стать огромным, трудно поддающимся отладке узким местом производительности с множеством непредвиденных ошибок. Возможно, вам будет лучше написать (протестированный) метод DPC_EXT, который выполняет преобразование за вас, чем пытаться решить эту проблему с помощью простого CDS / SQL.   -  person konstantin    schedule 12.01.2021
comment
Кстати: сравнение LIKE не понимает регулярных выражений. Это больше подстановочных знаков, но ничего особенного, как вы пытаетесь сделать. См. Официальную SAP-документацию regex vs. нравится. Если вы хотите использовать регулярное выражение в каком-либо коде ABAP, вы можете использовать ^\d+$ только для соответствия числовые значения или NOT LIKE %_% в SQL / CDS, если все нечисловые значения содержат символ подчеркивания.   -  person konstantin    schedule 12.01.2021
comment
@konstantin проблема в том, что некоторые таблицы в системе уже имеют длину 40 символов, и мне нужно создавать объединения и ассоциации между таблицами с использованием разной длины поля. Мне не разрешено изменять длину поля на этом этапе, поэтому сейчас я просто хотел решить это в CDS. В противном случае я просто сделаю промежуточную обработку в ABAP и буду использовать ДЛЯ ВСЕХ ЗАПИСЕЙ ...   -  person RaTiO    schedule 12.01.2021


Ответы (1)


Из-за ограниченной функциональности синтаксиса 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 

person astentx    schedule 12.01.2021
comment
Очень умно, спасибо, но все же не очень элегантно. Если никто другой не предложит лучшего решения, я отмечу его как правильный ответ. - person RaTiO; 12.01.2021
comment
вау, какой жестокий подход к нарушению ограничений CDS :) - person Suncatcher; 18.01.2021
comment
Да, это довольно странно, но похоже, что alpha применяется внутри преобразования BW, созданного HANA: string(if ( ltrim(string( \"0DOC_NUMBER\"), ' 0123456789') = '',string( alphanum( trim ( string( \"0DOC_NUMBER\" ) ), 10) ),midstru(ltrim( \"0DOC_NUMBER\" ) , 1,10 ) )). Итак, благодаря удобной функции trim, позволяющей удалить несколько символов, чего нет в CDS (и такой многозначный trim не представлен в некоторых СУБД, например в Oracle и DB2). - person astentx; 19.01.2021