更新 MARA 表的最佳解决方案是啥?

Posted

技术标签:

【中文标题】更新 MARA 表的最佳解决方案是啥?【英文标题】:What is the best solution to update the MARA table?更新 MARA 表的最佳解决方案是什么? 【发布时间】:2017-03-13 03:14:57 【问题描述】:

我今天面临一个问题:如何使用自定义和非自定义字段更新 MARA 表?

我找到了一些解决方案,但我想知道什么是最好的解决方案。

我来自 HCM 模块。在这个模块上,我们有变更日志。因此,如果可能的话,我想用日志更改来更新 MARA 表。

上下文:

    从表中选择一个 MARA 条目(确定) 编辑字段(确定) 检查每个字段,如果新值已经在可用值上 更新表格

逻辑:

DATA:
  lt_mara TYPE TABLE OF mara,
  ls_mara TYPE mara.

lv_matnr = '000000000024856';

* Seelct data
"" matnr from CONVERSION_EXIT_MATN1_INPUT
SELECT SINGLE * INTO ls_mara FROM mara WHERE matnr = lv_matnr.

* Modification
ls_mara-vlumn = '999.9'. 
"ls_mara-z* = '...'.   

* Checks : volumn is numeric, ...
" [...]

* Update
" [...]

我只有 MARA 的信息,没有相关表格的数据。

解决方案 1 - MATERIAL_MAINTAIN_DARK

使用功能模块MATERIAL_MAINTAIN_DARK

CALL FUNCTION 'MATERIAL_MAINTAIN_DARK'
    EXPORTING
        kz_activ_cad = blank
        flag_muss_pruefen = fest_x
        sperrmodus = fest_e
        max_errors = 0
        p_kz_no_warn = fest_x " 'N' ?
        kz_prf = blank " 's' ?
        kz_verw = fest_x
        kz_aend = fest_x
        kz_dispo = fest_x
        kz_test = blank
        kz_mdip = blank
        kz_mprp = blank
        kz_ale = blank
        kz_actv = blank
    TABLES
        AMARA_UEB = TMARA_UEB
        AMERRDAT = lt_amerrdat
    EXCEPTIONS
        OTHERS = 7.

" Loop lt_amerrdat.
"   CALL FUNCTION 'RPY_MESSAGE_COMPOSE' [...]
"     WRITE:/ lv_errmsg.

" ROLLBACK WORK.
" or
" CALL FUNCTION 'DB_COMMIT'.

(我用了https://archive.sap.com/discussions/thread/169786这个代码逻辑)

问题:我成功执行了代码,但现在我发现了一些功能性错误。如果我正确理解了这个 FM 的功能,修改将通过 tcode 执行(即:MM01/02/03)。 但是,我不知道每一行的初始 tcode 是什么,并且我遇到了功能问题(即:文章类别不正确,...),具体取决于所使用的 tcode。

你知道我怎样才能跳过这些检查吗?或者知道初始tcode?​​p>

解决方案 2 - BAPI_MATERIAL_SAVEDATA

使用功能模块BAPI_MATERIAL_SAVEDATA。 此 FM 允许使用标准字段 + 自定义更新 MARA 表(通过 EXTENSION(X))

有关信息,我的 BAPI_TE_MARABAPI_TE_MARAX 看起来像:

材料(MATNR,字符,18) .APPEND (ZBAPI_TE_MARAX) NOCHANGE(BAPIUPDATE,char,1)

我想我必须在它上面添加每个 Z* 字段,然后才能使用这个 FM ? 此外,我没有找到更新表字段的解决方案。如果我正在检查 FM,我有一些对象,但列名不一样。 如何找到此 FM 上的字段与 MARA 表上的字段之间的映射?

解决方案 3

我是否对代码的完整性进行了检查,我想我可以使用简单的 INSERT/UPDATE (MODIFY) 吗? 这应该是最简单的解决方案。

CONCATENATE sy-mandt lv_matnr INTO lv_mara_key.

" Lock object
CALL FUNCTION 'ENQUEUE_E_TABLE'
    EXPORTING
        MODE_RSTABLE   = 'E'
        tabname        = 'MARA'
        varkey         = lv_mara_key
    EXCEPTIONS
        foreign_lock   = 1      system_failure = 2      OTHERS = 3.

ls_mara-ernam = sy-uname.
" ...
" std & custo

MODIFY mara FROM ls_mara.

" Unlock object
CALL FUNCTION 'DEQUEUE_E_TABLE'
    EXPORTING
        MODE_RSTABLE   = 'E'
        tabname        = 'MARA'
        varkey         = lv_mara_key
    EXCEPTIONS
        foreign_lock   = 1      system_failure = 2      OTHERS = 3.

我对所有推荐、教程或建议感兴趣 :)

【问题讨论】:

我会选择解决方案 2。不建议使用解决方案 3,除非您知道也不应该更新其他相关表。 嗨。谢谢。实际上,不会涉及其他表。除了 MARA 表,我没有其他信息。方式:海量上传mara数据。对于另一个,将使用另一个程序或手动过程。我没有找到任何关于 Sol 2 的好文档。你有吗? 解决方案 2 将是三者中最好的。 BAPI是SAP的官方接口,所以你有一个可靠的连接,更新或升级后可能不会改变,而内部功能模块可能会改变。 BAPI 中的字段名称不同,但如果您查看函数模块声明,您会发现它们使用相同的数据类型。大多数情况下,将内部字段名映射到 BAPI 字段名就足够了。通常 BAPI 使用标准英文字段名,而表通常使用 5 或 6 个字符长的字段名,通常是德语。 【参考方案1】:

解决方案 #3 在 SAP 系统中只是不是一个有效的选项

【讨论】:

【参考方案2】:

最后,这是选择的解决方案。我们将BAPI_MATERIAL_SAVEDATA 与扩展名一起使用。 如果您想使用它,我评论了代码以帮助您:)

FORM update_mara
  USING
    us_result TYPE mara. "Input entry of mara with masterdata to update in the system

  DATA :  ls_mara           TYPE bapi_te_mara,
          ls_head           TYPE bapimathead,
          lt_extensionin    TYPE TABLE OF bapiparex,
          ls_extensionin    TYPE bapiparex,
          lt_extensioninx   TYPE TABLE OF bapiparexx,
          ls_extensioninx   TYPE bapiparexx,
          ls_return         TYPE bapiret2,
          lv_x              TYPE char41,
          lv_mara           TYPE string. "Container for all data of ls_mara

  " MASTERDATA PART
  MOVE-CORRESPONDING us_result TO ls_mara.
  ls_mara-material = ls_head-material = us_result-matnr.
  "At least the mendatory key field: 'material'

  " DATA PART
  " Use extension BAPI_TE_MARA
  ls_extensionin-structure = 'BAPI_TE_MARA'.
  lv_mara = ls_mara.
  " Fill data into the extension
  ls_extensionin+30(960) = lv_mara.
  APPEND ls_extensionin TO lt_extensionin.

  " FLAG PART
  CLEAR lv_x.
  DO 41 TIMES. "Don't forget to change 'lv_x TYPE char41' if needed
    CONCATENATE lv_x 'X' INTO lv_x.
    "Add an 'X' where you want to activate the update
    "Here, it's for all fields
  ENDDO. " End of the do loop for all fields of the mara

  " Use extension BAPI_TE_MARAX
  ls_extensioninx-structure  = 'BAPI_TE_MARAX'.
  ls_extensioninx-valuepart1(18)  = us_result-matnr.
  ls_extensioninx-valuepart1+19   = lv_x.
  " The first part (18) of the extensioninx is the matnr and the next ones some 'X' flags to activate the update or not.
  APPEND ls_extensioninx TO lt_extensioninx.

  " PROCESS PART
  CALL FUNCTION 'BAPI_MATERIAL_SAVEDATA'
    EXPORTING
      headdata     = ls_head
    IMPORTING
      return       = ls_return
    TABLES
      extensionin  = lt_extensionin
      extensioninx = lt_extensioninx
  .

  IF ls_return-type = 'E'.
    CALL FUNCTION 'BAPI_TRANSACTION_ROLLBACK'.
  ELSE.
    CALL FUNCTION 'BAPI_TRANSACTION_COMMIT'
      EXPORTING
        wait = 'X'.
  ENDIF.  " End if of check of BAPI result

ENDFORM.                    " UPDATE_MARA

【讨论】:

您可以先使用DESCRIBE FIELD TYPE DATA(lv_type) COMPONENTS DATA(lv_number_of_fields).,然后使用DO lv_number_of_fields TIMES.,而不是硬编码更新标志结构中的字段数(本例中为41)。通过这种方式,您的代码将获得可重用性并避免将来可能出现的 DUMP【参考方案3】:

解决方案 1 和 2 都很好。在使用其中一个 FM 更改标准字段后,您可以直接填充自定义字段,就像在解决方案 3 中所做的那样。

【讨论】:

【参考方案4】:

解决方案 2. 期间。有关详细信息,请参阅来自 @chrisian 和 @dirk-trilsbeek 的优秀 cmets。

关于您关于字段映射的后续问题。对用户更友好的名称非常适合从 SAP 外部使用 BAPI 的人,但它们确实很难映射到我们在 SAP 内部知道的字段。幸运的是,SAP 在这些情况下大部分时间都使用相同的数据元素,因此这是匹配它们的一种方法。否则,不同的 BAPI 通常具有从 BAPI 字段转换为数据库字段的转换功能模块。对于您提到的材料 BAPI,您可以检查子例程

_UEBERGEBEN(这将转换为
_TRANSFER),其中
是 MARA、MARC 等。请注意,例如 MARA_UEBERGEBEN 例程调用 FM MAP2I_BAPI_MARA_TO_MARA_UEB 并且此 FM 具有从 BAPI 结构到 MARA 的翻译,例如NET_WEIGHT 映射到 NTGEW。

【讨论】:

【参考方案5】:

使用解决方案 1,但是这些自定义字段应该预先分配给组!这应该在自定义路径中完成:

Logistic General-> Material Master-> Field Selection-> 将字段分配给字段选择组

如果还没有组,您应该创建新组。该组确定字段何时启用/禁用/活动/非活动等。 代码应如下所示:

CALL FUNCTION 'MATERIAL_MAINTAIN_DARK'
 EXPORTING
  sperrmodus = ' '
  kz_prf = 'W'
  max_errors = ' '
  p_kz_no_warn = 'X'
  kz_verw = 'X'
  kz_aend = 'X'
  kz_dispo = 'X'
  kz_test = ' '
  flag_muss_pruefen = ' '
  call_mode = 'ACT'
 IMPORTING
  matnr_last = w_matnr_last
  number_errors_transaction = w_nb_errors
 TABLES
  amara_ueb = t_amara_ueb
  amarm_ueb = t_amarm_ueb
 EXCEPTIONS
  kstatus_empty = 1
  tkstatus_empty = 2
  t130m_error = 3
  internal_error = 4
  too_many_errors = 5
  update_error = 6
 OTHERS = 7.

 IF sy-subrc <> 0.
  MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO.
 ELSE.
  COMMIT WORK.
 ENDIF.

【讨论】:

以上是关于更新 MARA 表的最佳解决方案是啥?的主要内容,如果未能解决你的问题,请参考以下文章

在 SQL 中从另一个表更新一个表的最佳方法是啥?

在使用表时更新表中数据而不锁定表的最佳方法是啥?

迁移到新的 SQL Server 后,在 MS Access 中更新链接表的最佳方法是啥?

第一次将数据从其他来源插入应用程序表的最佳方法是啥?

处理具有数百万条记录更新和大量读数的 MySQL 表的最佳方法

创建和填充数字表的最佳方法是啥?