Меню

VALUE, FOR и TABLE EXPRTESSIONS – ABAP 740

Разработчики SAP постоянно нас радуют новыми апгрейдами, в том числе и в ABAP; сегодня я хотел бы рассмотреть новые конструкции языка, которые упрощают нам с вами жизнь.

Содержание

Аннотация

Работа с операторами

Оператор VALUE

Примеры использования

Пример №1. Несколько способов инициализации структур

Пример №2. Инициализации внутренних таблиц

Пример №3. Инициализация сложных типов таблиц с глубокой структурой

Оператор FOR

Примеры использования

Пример №4. Копирование данных при создании таблицы из другой внутренней таблицы

Пример №5. Использование WHERE условий в операторе FOR

Пример №6. Использование вложенных FOR

TABLE EXPRESSIONS

Примеры использования

Пример №7. Чтение таблицы по индексу

Пример №8. Запись значений компонента в таблицу по индексу

Пример №9. Поиск и выдача данных из таблицы с использованием ключа, без какой-либо рабочей области

Аннотация

Разработчики SAP постоянно нас радуют новыми апгрейдами, в том числе и в ABAP; сегодня я хотел бы рассмотреть новые конструкции языка, которые упрощают нам с вами жизнь. Я использовал как материалы с официальных блогов SAP, так и некоторые заметки из иностранных обзоров. Цель же моя проста: познакомить тех, кто еще не знает этого, с новыми операторами и конструкциями языка, а может, и напомнить, о том, что иногда стоит привыкать делать что-то «по-новому», оставляя старые привычки позади!

Итак, рассмотрим два новых оператора и синтаксис работы с внутренними таблицами:

  1. Оператор VALUE
  2. Оператор FOR
  3. Выражения для внутренних таблиц (TABLE EXPRESSIONS)

Работа с операторами

Оператор VALUE

Для начала обратимся к официальной информации и почитаем, что пишут о новом операторе:

1. VDLUE – это по сути конструктор, который определяет данные с указанным типом

… VALUE dtype|#( ) …

2. Он может установить начальные значения для любого типа данных

… VALUE dtype|#( comp1 = a1 comp2 = a2 … ) …

3. Он может установить значение сразу для нескольких записей

… VALUE dtype|#( ( … ) ( … ) … ) …

4. Он не работает с простыми типами

Давайте посмотрим синтаксис определения таблиц с вложенными структурами:

VALUE dtype|#( col1 = dobj11 … ( col2 = dobj12 col3 = dobj13 … ) 
                                 ( col2 = dobj22 col3 = dobj23 … ) 
                                   … 
               col1 = dobj31 col2 = dobj32 … ( col3 = dobj33 … ) 
                                               ( col3 = dobj43 … ) 
               … ).

Как видно, синтаксис имеет гибкую структуру и чем-то походит на объявления массивов в современных языках программирования.

 Примеры использования

Пример №1. Несколько способов инициализации структур

TYPES:  BEGIN OF t_col2, 
           col1 TYPE i, 
           col2 TYPE i, 
        END OF t_col2.


TYPES: BEGIN OF t_struct, 
         col1 TYPE i, 
         col2 TYPE t_col2, 
       END OF t_struct.

DATA: struct TYPE t_struct, 
      col2 TYPE t_col2. 

“1
struct = VALUE t_struct( col1 = 1 
                         col2-col1 = 1 
                         col2-col2 = 2 ).

“2

col2   = VALUE   t_col2( col1 = 1 
                         col2 = 2 ). 
struct = VALUE t_struct( col1 = 1 
                         col2 = col2 ).

“3

struct = VALUE t_struct( col1 = 1 
                         col2 = VALUE #( col1 = 1 
                                         col2 = 2 ) ).

Пример №2. Инициализации внутренних таблиц

TYPES t_itab TYPE TABLE OF i WITH EMPTY KEY.

DATA itab TYPE t_itab.

itab = VALUE #( ( ) ( 1 ) ( 2 ) ).


DATA itab TYPE RANGE OF i.


itab = VALUE #( sign = ‘I’  option = ‘BT’ ( low = 1  high = 10 ) 
                                          ( low = 21 high = 30 ) 
                                          ( low = 41 high = 50 ) 
                            option = ‘GE’ ( low = 61 )  ).

Пример №3. Инициализация сложных типов таблиц с глубокой структурой

TYPES:

  BEGIN OF ty_alv_data,

    kunnr   TYPE kunnr,

    name1   TYPE name1,

    ort01   TYPE ort01,

    land1   TYPE land1,

    t_color TYPE lvc_t_scol,

  END   OF ty_alv_data.

TYPES: tt_alv_data TYPE STANDARD TABLE OF ty_alv_data

                                        WITH DEFAULT KEY.

* classical

DATA: itab_alv_c TYPE tt_alv_data.

FIELD-SYMBOLS: <fs_a>   LIKE LINE OF itab_alv_c,

               <fs_col> LIKE LINE OF <fs_a>-t_color.

APPEND INITIAL LINE TO itab_alv_c ASSIGNING <fs_a>.

<fs_a>-kunnr = '123'.

<fs_a>-name1 = 'ABCD'.

<fs_a>-ort01 = 'LV'.

<fs_a>-land1 = 'NV'.

APPEND INITIAL LINE TO <fs_a>-t_color ASSIGNING <fs_col>.

<fs_col>-fname = 'KUNNR'.

<fs_col>-color-col = COL_NEGATIVE.

<fs_col>-color-int = 0.

<fs_col>-color-inv = 0.

APPEND INITIAL LINE TO <fs_a>-t_color ASSIGNING <fs_col>.

<fs_col>-fname = 'ORT01'.

<fs_col>-color-col = COL_TOTAL.

<fs_col>-color-int = 1.

<fs_col>-color-inv = 1.

APPEND INITIAL LINE TO itab_alv_c ASSIGNING <fs_a>.

<fs_a>-kunnr = '456'.

<fs_a>-name1 = 'XYZ'.

<fs_a>-ort01 = 'LA'.

<fs_a>-land1 = 'CA'.


* Using VALUE

DATA(itab_alv) =

  VALUE tt_alv_data(

                    "First Row

                    ( kunnr = '123' name1 = 'ABCD'

                        ort01 = 'LV' land1 = 'NV'

                        " color table

                        t_color = VALUE #(

                                          " Color table - First Row

                                           ( fname = 'KUNNR'

                                             color-col = COL_NEGATIVE

                                             color-int = 0

                                             color-inv = 0

                                            )

                                          " Color Table - 2nd Row

                                           ( fname = 'ORT01'

                                             color-col = COL_TOTAL

                                             color-int = 1

                                             color-inv = 1

                                            )

                                          )

                    )

                    "Second row

                   ( kunnr = '456' name1 = 'XYZ'

                        ort01 = 'LA' land1 = 'CA'

                    )

                 ).

Тесно с этим оператором может сотрудничать еще один новенький оператор, оператор FOR!

Оператор FOR

Этот оператор предоставляет возможность пройтись по таблице (почти как старый добрый LOOP), и по своей природе является итератором, его особенность в удобном синтаксисе и достаточно широких возможностях использования.

Рассмотрим мини-пример:

DATA(t_city) =
  VALUE tt_citys(
    FOR ls_cust IN t_customres
      INDEX INTO cust_index
    ( ls_cust-city )
  ).
 

Мы определяем таблицу t_city, записи в которую добавляются одновременно с созданием. В таблицу t_ заносятся все города из таблицы ls_cust, одновременно с каждой итерацией переключается индекс строки в переменной cust_index.

Примеры использования

Посмотрим полные примеры использования…

Пример №4. Копирование данных при создании таблицы из другой внутренней таблицы

 
TYPES:
  BEGIN OF ty_customer,
    customer TYPE char10,
    NAME     TYPE char30,
    city     TYPE char30,
    route    TYPE char10,
  END   OF ty_customer.
TYPES: tt_customers TYPE SORTED TABLE OF ty_customer

Если хотите прочитать статью полностью и оставить свои комментарии присоединяйтесь к sapland

У вас уже есть учетная запись?

Войти

Обсуждения Количество комментариев17

Комментарий от  

Олег Башкатов

  |  04 июля 2017, 08:02

Леонид, я правильно понимаю, что реально Вы не используете эти конструкции и не применяете? иначе, зачем Вы копируете "один-в-один" из статьи 2015года в том числе и примеры:
 
zevolving.com/2014/09
 
zevolving.com/2015/05

Комментарий от  

Леонид Мартынов

  |  04 июля 2017, 09:34

Леонид, я правильно понимаю, что реально Вы не используете эти конструкции и не применяете? иначе, зачем Вы копируете "один-в-один" из статьи 2015года в том числе и примеры:
 
zevolving.com/2014/09
 
zevolving.com/2015/05

Реально я с ними не так давно познакомился, примеры в общем доступе из интернета в том числе сап блогов , не хотел тратить время на измышления своих,теперь пытаюсь их применять, и по своим коллегам вижу , что они тоже не часто не то что не используют, не знаю что такие конструкции появились. Цель статьи рассказать, ознакомить =)

Комментарий от  

Олег Точенюк

  |  04 июля 2017, 21:43

Реально я с ними не так давно познакомился, примеры в общем доступе из интернета в том числе сап блогов , не хотел тратить время на измышления своих,теперь пытаюсь их применять, и по своим коллегам вижу , что они тоже не часто не то что не используют, не знаю что такие конструкции появились. Цель статьи рассказать, ознакомить =)

Ознакомить то оно конечно полезно, только в таком виде лучше бы не делать этого. А то ведь послушают вас и возьмут на вооружение, например предложенный вами последний пример:
 
* Старый метод доступа
READ TABLE itab_multi_comp INTO ls_comp WITH KEY kunnr = '123'.
WRITE: / ls_comp-ort01.
 
* Новый метод доступа
WRITE: / itab_multi_comp[ kunnr = '123' ]-ort01.
 
а потом плакать будут, окружающие, ну зато мне работы может подкинут :-) в перспективе, так как суть старого и нового методов различна и сравнивать их в таком виде очень не рекомендуется, а вы вот сравниваете и не понимаете в чем существенная разница.

Комментарий от  

Леонид Мартынов

  |  05 июля 2017, 05:44

Ознакомить то оно конечно полезно, только в таком виде лучше бы не делать этого. А то ведь послушают вас и возьмут на вооружение, например предложенный вами последний пример:
 
* Старый метод доступа
READ TABLE itab_multi_comp INTO ls_comp WITH KEY kunnr = '123'.
WRITE: / ls_comp-ort01.
 
* Новый метод доступа
WRITE: / itab_multi_comp[ kunnr = '123' ]-ort01.
 
а потом плакать будут, окружающие, ну зато мне работы может подкинут :-) в перспективе, так как суть старого и нового методов различна и сравнивать их в таком виде очень не рекомендуется, а вы вот сравниваете и не понимаете в чем существенная разница.

я лишь показал примеры использования новых моделей, как их лучше применять решит каждый в зависимости от задачи, не правда ли? Использовать ли первую (скажем с лог. поиском) или простую вторую конструкцию - решит программист,не было целью обучать программированию, целью было продемонстрировать. Если вы готовы судить о том, чтО я понимаю , а что нет то мне жаль, что вы готовы это делать заочно. Еще раз повторюсь - цель показать примеры!
 
Тем не менее спасибо за комментарий =)

Комментарий от  

Леонид Мартынов

  |  05 июля 2017, 06:00

Ознакомить то оно конечно полезно, только в таком виде лучше бы не делать этого. А то ведь послушают вас и возьмут на вооружение, например предложенный вами последний пример:
 
* Старый метод доступа
READ TABLE itab_multi_comp INTO ls_comp WITH KEY kunnr = '123'.
WRITE: / ls_comp-ort01.
 
* Новый метод доступа
WRITE: / itab_multi_comp[ kunnr = '123' ]-ort01.
 
а потом плакать будут, окружающие, ну зато мне работы может подкинут :-) в перспективе, так как суть старого и нового методов различна и сравнивать их в таком виде очень не рекомендуется, а вы вот сравниваете и не понимаете в чем существенная разница.

Удивляюсь только одному, сколь много людей  готовы выразить  многозначность своего ЭГО и показать свой великолепный ум, на таком мелком материале....без зазрения совести уверенные, что у других нет возможности отличить черное от белое, или скажем доступ к одному полю и чтение в структуру....беда!

Комментарий от  

Леонид Мартынов

  |  05 июля 2017, 08:32

Коллеги, в любом случае спасибо за проявленный интерес и критические замечания, думаю, что я учту это, если буду писать что-то подобное еще в будущем. Как я уже писал, мне было любопытно рассказать о таких конструкциях (на мой субъективный взгляд редких). Конечно же, как и применять лучше, где и в каком случае, не входило в планы, использованные примеры, служили лишь примерами. Я буду рад увидеть ваши статьи на эту тему, и готов конечно поучиться и методам применения best practice и в целом у вас! Я всегда открыт к новому и обучению. Всем творческих успехов, спасибо!

Комментарий от  

Олег Точенюк

  |  05 июля 2017, 15:40

я лишь показал примеры использования новых моделей, как их лучше применять решит каждый в зависимости от задачи, не правда ли? Использовать ли первую (скажем с лог. поиском) или простую вторую конструкцию - решит программист,не было целью обучать программированию, целью было продемонстрировать. Если вы готовы судить о том, чтО я понимаю , а что нет то мне жаль, что вы готовы это делать заочно. Еще раз повторюсь - цель показать примеры!
 
Тем не менее спасибо за комментарий =)

А очно вы себе это как представляете, я к вам в гости или вы ко мне? Комментарии к статье как бы и предназначены для общения и высказывания своего мнения по прочитанному. Не очень понимаю в чем была проблема?  Ну добавьте в следующий раз в конце статьи, что просьба по статье не высказываться, раз это сильно почему-то задевает.
 
По поводу решил программист, согласитесь для того, чтобы что-то решить, нужно представлять последствия своих решений (например использовать BAPI или вкатить прямой апдейт таблиц). Из написанного вами получается, что последствий никаких, это просто новый, более компактный метод записи кода. Я правильно понял донесенную вами мысль?

Комментарий от  

Олег Точенюк

  |  05 июля 2017, 15:43

Удивляюсь только одному, сколь много людей  готовы выразить  многозначность своего ЭГО и показать свой великолепный ум, на таком мелком материале....без зазрения совести уверенные, что у других нет возможности отличить черное от белое, или скажем доступ к одному полю и чтение в структуру....беда!

Вы даже не представляете какая беда... уже попал на любителей нового синтаксиса, оказывается, таки не понимают.

Комментарий от  

Леонид Мартынов

  |  05 июля 2017, 16:14

Вы даже не представляете какая беда... уже попал на любителей нового синтаксиса, оказывается, таки не понимают.

Верю вам! =) Я не сомневаюсь в вашем опыте, я тоже много всего видел, и конечно проблема оптимизации очень неприятная, особенно выправление.....тут я не могу с вами не согласиться, многие например не только забывают о хеширвоанных и сортированных таблицах, но и не используют банальный двоичный поиск. Поверьте, просто , что цель была совсем другая, кто касается примеров, может они и не удачные, соглашусь (и в след раз постараюсь подобрать более жизненные). Удачного вам вечера!

Комментарий от  

Леонид Мартынов

  |  05 июля 2017, 16:15

А очно вы себе это как представляете, я к вам в гости или вы ко мне? Комментарии к статье как бы и предназначены для общения и высказывания своего мнения по прочитанному. Не очень понимаю в чем была проблема?  Ну добавьте в следующий раз в конце статьи, что просьба по статье не высказываться, раз это сильно почему-то задевает.
 
По поводу решил программист, согласитесь для того, чтобы что-то решить, нужно представлять последствия своих решений (например использовать BAPI или вкатить прямой апдейт таблиц). Из написанного вами получается, что последствий никаких, это просто новый, более компактный метод записи кода. Я правильно понял донесенную вами мысль?

Не совсем =) пример был рассчитан на "показать пример" - это не руководство так делать, писать в таблице конечно)) "преступление"...хотя даже бывает и он необходим))) в экстренно оперативных случаях
 

Спасибо за ваше мнение!

Комментарий от  

Сергей Левченко

  |  13 июля 2017, 11:31

Ознакомить то оно конечно полезно, только в таком виде лучше бы не делать этого. А то ведь послушают вас и возьмут на вооружение, например предложенный вами последний пример:
 
* Старый метод доступа
READ TABLE itab_multi_comp INTO ls_comp WITH KEY kunnr = '123'.
WRITE: / ls_comp-ort01.
 
* Новый метод доступа
WRITE: / itab_multi_comp[ kunnr = '123' ]-ort01.
 
а потом плакать будут, окружающие, ну зато мне работы может подкинут :-) в перспективе, так как суть старого и нового методов различна и сравнивать их в таком виде очень не рекомендуется, а вы вот сравниваете и не понимаете в чем существенная разница.

Олег, лучше напиши какие могут быть проблемы. Воспитание учителей неблагодарный труд. :)
Вообше непонятно, зачем АБАПу новые операторы, если все "старые" языки пошли в библиотеки.
 
С уважением
Сергей

Комментарий от  

Иван Рыбкин

  |  13 июля 2017, 12:46

Вы даже не представляете какая беда... уже попал на любителей нового синтаксиса, оказывается, таки не понимают.

Олег, добрый день. Если не трудно, напишите плз, какие возникают проблемы при использовании нового синтаксиса? ( не считая того , что надо использовать TRY..  ENTRY ).  Чисто практический интерес..

Комментарий от  

Олег Точенюк

  |  13 июля 2017, 19:45

Олег, добрый день. Если не трудно, напишите плз, какие возникают проблемы при использовании нового синтаксиса? ( не считая того , что надо использовать TRY..  ENTRY ).  Чисто практический интерес..

Да я просто не знаю, как бы статья не моя, наверное лучше чтобы автор продолжил раскрывать данную тему, ну как мне кажется.
 
Хорошо, буквально один пример, из приведенного выше, который я использовал в самом начале.
 
* Старый метод доступа
READ TABLE itab_multi_comp INTO ls_comp WITH KEY kunnr = '123'.
WRITE: / ls_comp-ort01.
 
* Новый метод доступа
WRITE: / itab_multi_comp[ kunnr = '123' ]-ort01.
 
На самом деле старый метод написан не правильно, эквивалент нового метода должен быть таким:
READ TABLE itab_multi_comp INTO ls_comp WITH KEY kunnr = '123' TRANSPORTING ort01.
 
т.е. вы фактически читаете значение одного поля. К чему это ведет с точки зрения производительности. В старой конструкции обычно читали всю запись, а дальше фактически вы могли работать со всеми полями считанной записи. В новой методике многие начинать писать так:
 
WRITE: /
itab_multi_comp[ kunnr = '123' ]-ort01,
itab_multi_comp[ kunnr = '123' ]-ort02,
itab_multi_comp[ kunnr = '123' ]-ort03,
itab_multi_comp[ kunnr = '123' ]-ort04.
 
Абап не умеет оптимизировать такие конструкцию, фактически это приводит к 4 последовательными чтениям т.е. в старых терминах можно считать что будет выполняь следующий код:
 
READ TABLE itab_multi_comp INTO:
ls_comp WITH KEY kunnr = '123' TRANSPORTING ort01,
ls_comp WITH KEY kunnr = '123' TRANSPORTING ort02,
ls_comp WITH KEY kunnr = '123' TRANSPORTING ort03,
ls_comp WITH KEY kunnr = '123' TRANSPORTING ort04.
 
Как можно понять производительность при этом проседает, хотя написание кода более короткое и визуально воспринимается проще.

Комментарий от  

Сергей Плаксин

  |  21 июля 2017, 11:47

Да я просто не знаю, как бы статья не моя, наверное лучше чтобы автор продолжил раскрывать данную тему, ну как мне кажется.
 
Хорошо, буквально один пример, из приведенного выше, который я использовал в самом начале.
 
* Старый метод доступа
READ TABLE itab_multi_comp INTO ls_comp WITH KEY kunnr = '123'.
WRITE: / ls_comp-ort01.
 
* Новый метод доступа
WRITE: / itab_multi_comp[ kunnr = '123' ]-ort01.
 
На самом деле старый метод написан не правильно, эквивалент нового метода должен быть таким:
READ TABLE itab_multi_comp INTO ls_comp WITH KEY kunnr = '123' TRANSPORTING ort01.
 
т.е. вы фактически читаете значение одного поля. К чему это ведет с точки зрения производительности. В старой конструкции обычно читали всю запись, а дальше фактически вы могли работать со всеми полями считанной записи. В новой методике многие начинать писать так:
 
WRITE: /
itab_multi_comp[ kunnr = '123' ]-ort01,
itab_multi_comp[ kunnr = '123' ]-ort02,
itab_multi_comp[ kunnr = '123' ]-ort03,
itab_multi_comp[ kunnr = '123' ]-ort04.
 
Абап не умеет оптимизировать такие конструкцию, фактически это приводит к 4 последовательными чтениям т.е. в старых терминах можно считать что будет выполняь следующий код:
 
READ TABLE itab_multi_comp INTO:
ls_comp WITH KEY kunnr = '123' TRANSPORTING ort01,
ls_comp WITH KEY kunnr = '123' TRANSPORTING ort02,
ls_comp WITH KEY kunnr = '123' TRANSPORTING ort03,
ls_comp WITH KEY kunnr = '123' TRANSPORTING ort04.
 
Как можно понять производительность при этом проседает, хотя написание кода более короткое и визуально воспринимается проще.

К тому же для конструкции:
WRITE: /
itab_multi_comp[ kunnr = '123' ]-ort01.
нельзя будет забывать писать
TRY.
CATCH CX_SY_ITAB_LINE_NOT_FOUND.
ENDTRY.
Иначе, приведет к неминуемому дампу, если такой записи во внутренней таблице нет.

Комментарий от  

Олег Точенюк

  |  26 июля 2017, 12:09

К тому же для конструкции:
WRITE: /
itab_multi_comp[ kunnr = '123' ]-ort01.
нельзя будет забывать писать
TRY.
CATCH CX_SY_ITAB_LINE_NOT_FOUND.
ENDTRY.
Иначе, приведет к неминуемому дампу, если такой записи во внутренней таблице нет.

Ну это да, тут вообще с этим кодом интересно вышло. вместо сокращения и удобства, по факту получается писать нужно больше, чего им SY-SUBRC помешала без всякого дампа не очень понимаю.

Комментарий от  

Олег Башкатов

  |  06 декабря 2019, 06:20

К тому же для конструкции:
WRITE: /
itab_multi_comp[ kunnr = '123' ]-ort01.
нельзя будет забывать писать
TRY.
CATCH CX_SY_ITAB_LINE_NOT_FOUND.
ENDTRY.
Иначе, приведет к неминуемому дампу, если такой записи во внутренней таблице нет.

можно так
ls_line = VALUE #( lt_tab[ f1 = 'NOT_EXIST' ] OPTIONAL ).
 
тогда не нужны проверки на исключение.

Комментарий от  

Олег Точенюк

  |  12 декабря 2019, 15:05

Олег, лучше напиши какие могут быть проблемы. Воспитание учителей неблагодарный труд. :)
Вообше непонятно, зачем АБАПу новые операторы, если все "старые" языки пошли в библиотеки.
 
С уважением
Сергей

Зачем новые? Скажем так многое стало более удобно. Просто нужно понимать техническую сторону реализации. Скажем так конструкция вида:
 
LOOP AT <таблица> INTO data(<строка>).
ENDLOOP.
 
намного удобнее и проще чем отдельно объявление строки заголовка.
 
Или заполнение таблицы через VALUE тоже как мне кажется удобнее и проще. Так что смысл есть.