Измените определенные поля BSEG из обычной структурированной таблицы

Я пытаюсь использовать следующее:

update bseg from zbseg

где таблицы имеют разную длину (ZBSEG - это уменьшенная версия BSEG).

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

Табличные данные из кластера сокращаются до нескольких полей и копируются в прозрачную таблицу (словарь данных в новой прозрачной таблице имеет первичные ключи + только несколько полей кластера), после чего данные в БД будут изменены и скопированы обратно через UPDATE в кластер .

update bseg from zbseg

этот оператор обновляет значения полей из ZBSEG, но в остальном не сохраняет старые значения, а скорее устанавливает начальные значения.

Я пробовал даже это:

SELECT *
FROM bseg
INTO TABLE gt_bseg.

SELECT mandt bukrs belnr gjahr buzei buzid augdt
FROM zbseg
INTO CORRESPONDING FIELDS OF TABLE gt_bseg.

но он по-прежнему перекрывает те поля, которые не рассматриваются в zbseg.

Любой оператор, который обновит только определенный диапазон полей, извлеченных из ZBSEG, не затрагивая другие BSEG поля?

ИЗОБРАЖЕНИЕ: Цикл по исходной полной и короткой таблице


person OrdinaryPerson    schedule 27.08.2018    source источник


Ответы (3)


Я думаю, вам нужно получить записи из zbseg с ограничением, потому что будет существовать миллион записей, затем получить их из bseg по одной и обновить его, а затем удалить или обновить его флаги из zbseg для повышения производительности.

tables: BSEG, ZBSEG.

data: GT_ZBSEG like ZBSEG occurs 1 with header line,
      GS_BSEG type BSEG.

select *
into table GT_ZBSEG up to 1000 rows
from ZBSEG.

check SY-SUBRC is initial.
check SY-DBCNT is not initial.

loop at GT_ZBSEG.
  select single * from BSEG into GS_BSEG
  where BSEG~MANDT = GT_ZBSEG-MANDT
    and BSEG~BUKRS = GT_ZBSEG-BUKRS
    and BSEG~BELNR = GT_ZBSEG-BELNR
    and BSEG~GJAHR = GT_ZBSEG-GJAHR
    and BSEG~BUZEI = GT_ZBSEG-BUZEI.
  if SY-SUBRC ne 0.
    message E208(00) with 'Record not found!'.
  endif.
  if GS_BSEG-BUZID ne GT_ZBSEG-BUZID
  or GS_BSEG-AUGDT ne GT_ZBSEG-AUGDT.
    move-corresponding GT_ZBSEG to GS_BSEG.
    update BSEG from GS_BSEG.
  endif.
  " delete same records and transfered
  delete ZBSEG from GT_ZBSEG.
endloop.
person mkysoft    schedule 27.08.2018
comment
Спасибо за ответ, mkysoft. Но все динамично, поэтому я не мог получить к ним доступ по первичному ключу. Поэтому я должен сделать что-то, что мне действительно не нравится, а именно LOOP in LOOP, поэтому я возьму исходные данные и обновлю только соответствующие поля из второй таблицы. Пожалуйста, взгляните на первый пост, где я выложу картинку из цикла. Спасибо! - person OrdinaryPerson; 28.08.2018
comment
Возможно, вы сможете найти ключевые поля с помощью FM BDL_DDIF_TABL_GET и создать динамическое условие. С другой стороны, я думаю, что использование собственного sql с хешем строки является хорошим вариантом для определения измененных строк. Затем сделайте петлю с ними. - person mkysoft; 28.08.2018
comment
Согласовано с @mkysoft, динамическое условие легко использовать (DATA where TYPE string. where = 'BSEG~MANDT = GT_ZBSEG~MANDT AND ...'. SELECT … WHERE (where)); предпочтительнее использовать RTTI, то есть cl_abap_typedescr, как объяснено в @ AZn5ReD, вместо неподдерживаемых функциональных модулей, таких как (BDL_) DDIF_TABL_GET; Что касается собственного SQL, обычно его нельзя использовать в кластеризованной таблице (например, BSEG), поскольку BSEG является логическим представлением реальной таблицы базы данных, специфичным для SAP (RFBLG для BSEG). - person Sandra Rossi; 29.08.2018
comment
выберите ОДИН * из (tabname_new) --- ›ZBSEG в ‹dyn_wa› ---› Символ поля со структурой ZBSEG WHERE (LV_WHERE_COND). LV_WHERE_COND = (MANDT eq ‹dyn_wa_clust› -MANDT и BELNR eq ‹dyn_wa_clust› -BELNR и BUREG eq ‹dyn_wa_clust› -BUREG и LFDNR eq ‹dyn_wa_clust› -LFDNR не поддерживается. для глубоких объектов данных.) Я также пробовал с ZBSEG ~ MANDT = ‹dyn_wa_clust› -MANDT, но безуспешно. - person OrdinaryPerson; 06.09.2018
comment
Не обращайте внимания на предыдущую ошибку. Я чиню это ! :) И работает очень шустро. Миллион спасибо mkysoft !! - person OrdinaryPerson; 06.09.2018

Вот фрагмент кода, который вы можете использовать для своей задачи. Он основан на динамическом операторе UPDATE, который позволяет обновлять только определенные поля:

DATA: handle      TYPE REF TO data,
      lref_struct TYPE REF TO cl_abap_structdescr,
      source      TYPE string,
      columns     TYPE string,
      keys        TYPE string,
      cond        TYPE string,
      sets        TYPE string.

SELECT tabname FROM dd02l INTO TABLE @DATA(clusters) WHERE tabclass = 'CLUSTER'.

LOOP AT clusters ASSIGNING FIELD-SYMBOL(<cluster>).
  lref_struct ?= cl_abap_structdescr=>describe_by_name( <cluster>-tabname ).
  source = 'Z' && <cluster>-tabname. " name of your ZBSEG-like table
* get key fields
  DATA(key_fields) = VALUE ddfields( FOR line IN lref_struct->get_ddic_field_list( ) 
                                     WHERE ( keyflag NE space ) ( line ) ).
  lref_struct ?= cl_abap_structdescr=>describe_by_name( source ).
* get all fields from source reduced table
  DATA(fields) = VALUE ddfields( FOR line IN lref_struct->get_ddic_field_list( ) ( line ) ).

* filling SELECT fields and SET clause
  LOOP AT fields ASSIGNING FIELD-SYMBOL(<field>).
    AT FIRST.
      columns = <field>-fieldname.
      CONTINUE.
    ENDAT.
    CONCATENATE columns <field>-fieldname INTO columns SEPARATED BY `, `.
    IF NOT line_exists( key_fields[ fieldname = <field>-fieldname ] ).
      IF sets IS INITIAL.
        sets = <field>-fieldname && ` = @<fsym_wa>-` && <field>-fieldname.
      ELSE.
        sets = sets && `, ` && <field>-fieldname && ` = @<fsym_wa>-` && <field>-fieldname.
      ENDIF.
    ENDIF.
  ENDLOOP.

* filling key fields and conditions
  LOOP AT key_fields ASSIGNING <field>.
    AT FIRST.
      keys = <field>-fieldname.
      CONTINUE.
    ENDAT.
    CONCATENATE keys <field>-fieldname INTO keys SEPARATED BY `, `.
    IF cond IS INITIAL.
      cond = <field>-fieldname && ` = @<fsym_wa>-` && <field>-fieldname.
    ELSE.
      cond = cond && ` AND ` && <field>-fieldname && ` = @<fsym_wa>-` && <field>-fieldname.
    ENDIF.
  ENDLOOP.

* constructing reduced table type
  lref_struct ?= cl_abap_typedescr=>describe_by_name( source ).
  CREATE DATA handle TYPE HANDLE lref_struct.
  ASSIGN handle->*  TO FIELD-SYMBOL(<fsym_wa>).

* updating result cluster table
  SELECT (columns)
    FROM (source)
    INTO @<fsym_wa>.
  UPDATE (<cluster>-tabname)
  SET (sets)
  WHERE (cond).
  ENDSELECT.

ENDLOOP.

Эта часть выбирает все таблицы кластера из DD02L и делает предположение, что вы уменьшили таблицу БД с префиксом Z для каждой целевой таблицы кластера. Например. ZBSEG для BSEG, ZBSET для BSET, ZKONV для KONV < / strong> и так далее.

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

person Suncatcher    schedule 08.07.2019

Вы можете попробовать использовать оператор MODIFY для обновления таблиц.

Другой способ сделать это - использовать cl_abap_typedescr для получения полей каждой таблицы и сравнения их для обновления.

Вот пример того, как получить поля.

DATA : ref_table_des TYPE REF TO cl_abap_structdescr,
       columns TYPE abap_compdescr_tab.

ref_table_des ?= cl_abap_typedescr=>describe_by_data( struc ).
columns = ref_table_des->components[].
person AZn5ReD    schedule 28.08.2018
comment
modify for dbtab не позволяет обновлять отдельные поля, и если вы говорите об изменении для itab, вы должны предоставить полный рабочий динамический образец - person Suncatcher; 09.07.2019