Pull to refresh

ABAP: Выборка справочных значений по их ключам из таблиц БД

ERP-systems *
Написал не так давно метод для выборки во внутреннюю таблицу справочных значений по их ключам с помощью создания динамической программы. К сожалению, исходный код приложить не получится, так как начальство запретило это делать. Так что ограничусь общим описанием теории.

К примеру есть у нас внутренняя таблица:

DATA:
  begin of it_TABLE occurs 0, 
      BE type T001-BUKRS,
      BENAME type T001-BUTXT,
  end of it_TABLE
.

В таблице заполнено поле BE и нам нужно выбрать из T001 значение BUTXT по соответствующему BE и заполнить поле BENAME. Как это нужно сделать «правильно» (т.е. с минимальными затратами памяти и максимально быстро).

  1. Выберем уникальные значения поля BE;
  2. Сделаем FOR ALL ENTRIES из T001;
  3. Пройдем по внутренней таблице и для каждого BE найдем соответствующее значение в выбранных из T001 данных. (Само собой используем HASH-таблицу для ускорения поиска)
И эта последовательность всегда одна и та же.
Вот код этого процесса
FIELD-SYMBOLS:
  <wa_Table> like line of it_Table
.  
*-- Создаем список уникальных значений поля BE
TYPES:
	BEGIN OF s_k1,
		BUKRS type T001-BUKRS,
	END OF s_k1
.
DATA:
	it_k1 TYPE SORTED TABLE OF s_k1 WITH UNIQUE KEY
	 BUKRS
	, wa_k1 like line of it_k1.
LOOP AT it_Table ASSIGNING <wa_Table>.
	wa_k1-BUKRS = <wa_Table>-BE.
	INSERT wa_k1 INTO TABLE it_k1.
ENDLOOP.
*-- Выбираем список значений из T001 по сформированным ключам
TYPES:
	BEGIN OF s_v1,
		BUKRS TYPE T001-BUKRS,
		BUTXT TYPE T001-BUTXT,
	END OF s_v1
.
DATA:
	it_v1 TYPE SORTED TABLE OF s_v1 WITH NON-UNIQUE KEY
	BUKRS
	, wa_v1 like line of it_v1.

IF it_k1[] IS INITIAL.
	REFRESH it_v1.
ELSE.
	SELECT
	 BUKRS
	 BUTXT
	 FROM T001
	 INTO CORRESPONDING FIELDS OF TABLE it_v1
	  FOR ALL ENTRIES in it_k1
	WHERE BUKRS = it_k1-BUKRS
	.
ENDIF.
*-- Присваиваем значения по ключам
LOOP AT it_Table ASSIGNING <wa_Table>.
	READ TABLE it_v1 INTO wa_v1
	 with table key
		BUKRS = <wa_Table>-BE
	.
	IF sy-subrc = 0.
		<wa_Table>-BENAME = wa_v1-BUTXT.
	ELSE.
		CLEAR <wa_Table>-BENAME.
	ENDIF.
ENDLOOP.
А если у нас всегда выполняются одни и те же действия, то значит стоит сократить их описание до минимума. В частности в данном случае нам нужно указать таблицу из которой нужно выбирать, ключевые поля и поля из которых в которые нужно записать данные.

Т.е. имеем следующую небольшую строку, в которой записана вся суть приведенного выше кода:
  'T001{BUKRS=BE}{BUTXT>BENAME}'   

Передаем в метод строку, указанную выше + нашу внутреннюю таблицу. И после вызова метода поле BENAME будет заполнено соответствующими значениями из T001-BUTXT. Мы сократили наш код, к тому же другому программисту достаточно иметь под рукой справку по методу и он быстро поймет что делает данная строка. При этом весь алгоритм укладывается в небольшую строку.
Вот код , сгенерированнй моим методом
 TYPES:
   BEGIN OF s_k1,
     BUKRS type T001-BUKRS,
   END OF s_k1
 .
 DATA:
    it_k1 TYPE SORTED TABLE OF s_k1 WITH UNIQUE KEY
     BUKRS
   , wa_k1 like line of it_k1.
 FIELD-SYMBOLS:
    <fs_1_BUKRS> type ANY,
    <fs_1_BUTXT> type ANY
 .
"-- Создаем список уникальных значений поля BE
 LOOP AT <it_Table> ASSIGNING <wa_Table>.
   "--
   ASSIGN COMPONENT 'BE'
       OF STRUCTURE <wa_Table>
       TO <fs_1_BUKRS>.
   wa_k1-BUKRS = <fs_1_BUKRS>.
   "-- Добавить в список ключей
   INSERT wa_k1 INTO TABLE it_k1.
 ENDLOOP.
 TYPES:
   BEGIN OF s_v1,
     BUKRS TYPE T001-BUKRS,
     BUTXT TYPE T001-BUTXT,
   END OF s_v1
 .
 DATA:
   it_v1 TYPE SORTED TABLE OF s_v1 WITH NON-UNIQUE KEY
    BUKRS
   , wa_v1 like line of it_v1.
*-- Выбираем значения из T001
 IF it_k1[] IS INITIAL.
   REFRESH it_v1.
 ELSE.
   SELECT
     BUKRS
     BUTXT
     FROM T001
     INTO CORRESPONDING FIELDS OF TABLE it_v1
      FOR ALL ENTRIES in it_k1
    WHERE BUKRS = it_k1-BUKRS
   .
 ENDIF.
 FREE it_k1.
*-- Присваиваем значения по ключам
 LOOP AT <it_Table> ASSIGNING <wa_Table>.
   ASSIGN COMPONENT 'BE'
       OF STRUCTURE <wa_Table> TO <fs_1_BUKRS>.
   ASSIGN COMPONENT 'BENAME'
       OF STRUCTURE <wa_Table> TO <fs_1_BUTXT>.
   "-- Читаем значение
   READ TABLE it_v1 INTO wa_v1
     with table key
        BUKRS = <fs_1_BUKRS>
   .
   IF sy-subrc = 0.
     <fs_1_BUTXT> = wa_v1-BUTXT.
   ELSE.
     CLEAR:
       <fs_1_BUTXT>
     .
   ENDIF.
 ENDLOOP.
 FREE it_v1.
 
Для полноценной работы метода добавим в него возможность указывать константы и системные переменные (к примеру sy-langu часто требуется для выборки текстов). Также добавим возможность указания списка команд — тогда мы сможем последовательно выбирать данные.

Как это работает? — с помощью динамических программ. Т.е. метод анализирует переданные через строку параметры, генерирует динамическую программу и запускает её. Добавление программы происходит через «INSERT REPORT l_repid FROM CODE.» чтобы не ограничиваться количеством созданных программ.

P.S. Особо я рад этому методу когда приходится выбирать много значений и периодически уже в процессе работы от постановщика приходит указание на добавление новых поле для выборки.

update: код процесса написал в правильном виде — получилось 53 строки. Строка параметров + вызов метода = 5 строк. Т.е. код сократился в 10 раз и теперь он размещается в пределах одной страницы. Что, по моему мнению, сильно повышает читабельность.
Tags: abap SAP
Hubs: ERP-systems
Total votes 18: ↑11 and ↓7 +4
Comments 30
Comments Comments 30

Popular right now

Top of the last 24 hours