Generi c способ обработки ключа сцепленной таблицы - PullRequest
2 голосов
/ 21 апреля 2020

Если у меня есть значение tabkey, например, DATA(lv_tabkey) = '1000041508773180000013000'., которое является объединенным значением всех ключей таблицы для записи, и я знаю имя соответствующей таблицы:

Как я могу получить запись таблицы для него без разбиения tabkey вручную и, следовательно, необходимость записи порядка и длины каждого ключевого поля?

Полный пример:

" The first 3 chars always belong to the 'mandt' field 
" which can't be filtered in the SELECT, therefore 
" I ignore it and start with key2
DATA(lv_tabkey) = '1000041508773180000013000'.

"ToDo - how to make this generic? - START
DATA(lv_key2) = lv_tabkey+3(12).
DATA(lv_key3) = lv_tabkey+15(3).
DATA(lv_key4) = lv_tabkey+18(4).
DATA(lv_key5) = lv_tabkey+22(3).
DATA(lv_where) =      'key2 = ' && lv_key2 && 
                 ' AND key3 = ' && lv_key3 && 
                 ' AND key4 = ' && lv_key4 && 
                 ' AND key5 = ' && lv_key5.
"ToDo - how to make this generic? - END

SELECT *
  FROM table_x
  INTO TABLE DATA(lt_results)
  WHERE (lv_where).

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

Ответы [ 2 ]

2 голосов
/ 23 апреля 2020

Оператор, который вы ищете:

Назначить вкладку TO РУЧКА ТИПА ЛИТЕРАТУРЫ r_type_struct.

Зная дескриптор типа для структуры (ключ таблицы), которую вы может заполнить его значениями в общем случае c и запросить таблицу, используя структуру. Вот как:

DATA: handle      TYPE REF TO data,
      lref_struct TYPE REF TO cl_abap_structdescr.

FIELD-SYMBOLS: <key_fld> TYPE abap_componentdescr.

SELECT * UP TO 5000 ROWS
  FROM cdpos
  INTO TABLE @DATA(t_cdpos)
  WHERE tabname NOT LIKE '/%'.

LOOP AT t_cdpos ASSIGNING FIELD-SYMBOL(<fs_cdpos>).
  lref_struct ?= cl_abap_structdescr=>describe_by_name( <fs_cdpos>-tabname ).

* get key fields
  DATA(key_fields) = VALUE ddfields( FOR line IN lref_struct->get_ddic_field_list( ) WHERE ( keyflag NE space ) ( line ) ).

* filling key field components
  DATA(key_table) = VALUE abap_component_tab( FOR ls_key IN key_fields
                                              ( name = ls_key-fieldname
                                                type = CAST #( cl_abap_datadescr=>describe_by_name( ls_key-domname ) )
                                               )
                                            ).
* create key fields type handle
  TRY.
      DATA(r_type_struct) = cl_abap_structdescr=>create( key_table ).
    CATCH cx_sy_struct_creation .
  ENDTRY.

* create key type
  CHECK r_type_struct IS NOT INITIAL.
  CREATE DATA handle TYPE HANDLE r_type_struct.
  ASSIGN handle->* TO FIELD-SYMBOL(<structure>).

* assigning final key structure
  ASSIGN <fs_cdpos>-tabkey TO <structure> CASTING TYPE HANDLE r_type_struct.

* filling values
  LOOP AT key_table ASSIGNING <key_fld>.
    ASSIGN COMPONENT <key_fld>-name OF STRUCTURE <structure> TO FIELD-SYMBOL(<val>).
    CHECK sy-subrc = 0.
    <key_fld>-suffix = <val>.
  ENDLOOP.

  DATA(where_cond) = REDUCE string( INIT where = ` ` FOR <field> IN key_table WHERE ( name <> 'MANDT' ) NEXT where = where && <field>-name && ` = '` && <field>-suffix && `' AND ` ).
  where_cond = substring( val = where_cond off = 0 len = strlen( where_cond ) - 4 ).

  IF <fs_cdpos>-tabname = 'BNKA'.
    SELECT *
    INTO TABLE @DATA(lt_bnka)
    FROM bnka
    WHERE (where_cond).
  ENDIF.

ENDLOOP.

Здесь я построил пример для таблицы CDPOS, которая содержит имена таблиц и дополнительные объединенные значения ключей в поле tabkey, другими словами, именно то, что вы пытаетесь использовать.

В al oop он определяет типы таблиц, строит ключ и делает запрос SQL в общем виде c. Здесь для простоты я использовал таблицу BNKA, но SQL SELECT можно также генерировать через символ поля. Также я сделал трюк, заполнив значения в той же вкладке, которая содержит компоненты структуры, в поле SUFFIX.

PS Перед передачей условия в запросе выполните правильную проверку типа данных, чтобы избежать таких ошибок, как SAPSQL_DATA_LOSS , потому что с новым синтаксисом он делает строгую проверку.

1 голос
/ 23 апреля 2020

ваш вариант использования напоминает мне, как я имею дело с ключом изменения документа (CDHDR / CDPOS). Надеюсь, поможет!

DATA:
  lv_tabkey  TYPE char50,
  ls_table   TYPE table_x.
FIELD-SYMBOLS:
  <ls_src_x> TYPE x,
  <ls_tgt_x> TYPE x.

"Add Client info the Table key if your table is Client dependent. 
CONCATENATE sy-mandt lv_tabkey INTO lv_tabkey.

ASSIGN lv_tab_key TO <ls_src_x> CASTING.
ASSIGN ls_table TO <ls_tgt_x> CASTING.
<ls_tgt_x> = <ls_src_x>.

"Now ls_table has the key info filled including MANDT if you have the MANDT in table key. 

SELECT *
  FROM table_x
    INTO TABLE DATA(lt_results)
    WHERE key2 = ls_table-key2 AND key3 = ls_table-key3
          AND key4 = ls_table-key4 AND key5 = ls_table_key5.
...