ABAP表数据备份功能

应用场景】重要的业务数据表结构需要调整,某个字段的长度需要修改等,但数据库表中已经存在很多数据,冒然直接改表字段可能会导致数据丢失,这种问题的后果可能非常严重。

解题思路】复制出一个新表,在新表里改好字段长度,然后把旧表的数据插入到新表,这一步就是备份数据,再修改旧表的字段长度,如果旧表数据丢失,可以立马把新表的数据复制回旧表,这样就可以解决一些不能预见的的问题。最后数据切换成功运行一段时间后,再把备份的表和数据删除。

【核心逻辑】1. 使用游标方式备份表数据   2. 数据量很大的表采用分包分批次处理。

START-OF-SELECTION.
  IF p_bak = 'X'.
    DATA:lt_ztfi0023_bak    TYPE STANDARD TABLE OF ztfi0023_bak.
    DATA:lt_ztfi1040_01_bak TYPE STANDARD TABLE OF ztfi1040_01_bak.
    DATA:zc_bk              TYPE cursor.
    DATA:lc_line            TYPE i VALUE 300000.
    DATA:lv_lines_23        TYPE i.


* ztfi0023
    OPEN CURSOR zc_bk FOR
    SELECT * FROM ztfi0023.
    IF sy-subrc <> 0.
      MESSAGE 'ZTFI0023未取到任何数据' TYPE 'I' DISPLAY LIKE 'E'.
      CLOSE CURSOR zc_bk.
      EXIT.
    ENDIF.

    DO.
      FETCH NEXT CURSOR @zc_bk INTO TABLE @lt_ztfi0023_bak PACKAGE SIZE @lc_line.
      IF sy-subrc <> 0.
        CLOSE CURSOR zc_bk.
        COMMIT WORK AND WAIT.
        FREE lt_ztfi0023_bak.
        EXIT.
      ENDIF.

      MODIFY ztfi0023_bak FROM TABLE lt_ztfi0023_bak.
      DESCRIBE TABLE lt_ztfi0023_bak LINES DATA(lv_lines).

      lv_lines_23 = lv_lines_23 + lv_lines.
    ENDDO.


* ztfi1040_01
    SELECT * INTO CORRESPONDING FIELDS OF TABLE lt_ztfi1040_01_bak FROM ztfi1040_01.
    MODIFY ztfi1040_01_bak FROM TABLE lt_ztfi1040_01_bak.
    COMMIT WORK.

    DESCRIBE TABLE lt_ztfi1040_01_bak LINES DATA(lv_lines_1040).
    FREE lt_ztfi1040_01_bak.

    DATA(lv_msg) = |备份成功!ZTFI0023_BAK条目数 { lv_lines_23 }, ZTFI1040_01_BAK条目数 { lv_lines_1040 }。|.
    MESSAGE lv_msg TYPE 'S'.

  ELSEIF p_del = 'X'.
    DELETE FROM ztfi0023_bak.
    DELETE FROM ztfi1040_01_bak.
    COMMIT WORK.
    MESSAGE '删除成功!' TYPE 'S'.
  ENDIF.

*&---------------------------------------------------------------------*
*& Report ZRP_BACKUP_TABLE
*&---------------------------------------------------------------------*
REPORT zrp_backup_table.

TABLES:ztbackup_data,sscrfields.

DATA:gt_log TYPE TABLE OF ztbackup_head WITH HEADER LINE.
DATA:gv_table TYPE char20,
     zc_bk    TYPE cursor.
FIELD-SYMBOLS: <fs_tab>  TYPE STANDARD TABLE,
               <fs_tab1> TYPE STANDARD TABLE,
               <fs_wa>.

PARAMETERS: p1 RADIOBUTTON GROUP gr1 USER-COMMAND u01,
            p2 RADIOBUTTON GROUP gr1,
            p3 RADIOBUTTON GROUP gr1.

SELECTION-SCREEN FUNCTION KEY: 1.
SELECT-OPTIONS: s_table FOR ztbackup_data-tablename,
                "s_srtfd FOR ztbackup_data-srtfd MODIF ID m01,
                s_datum FOR ztbackup_data-datum MODIF ID m01,
                s_uzeit FOR ztbackup_data-uzeit MODIF ID m01.
" p_guid  TYPE ztbackup_data-srtfd MODIF ID m01.

"AT SELECTION-SCREEN ON p_table.
"  PERFORM frm_check_table.

INITIALIZATION.

  PERFORM set_function_icon_and_text.

AT SELECTION-SCREEN OUTPUT.
  PERFORM frm_set_screen.

AT SELECTION-SCREEN.
  PERFORM deal_sel_screen_ucomm USING sscrfields-ucomm.

START-OF-SELECTION.

  CASE 'X'.
    WHEN p1.
      PERFORM frm_backup.
    WHEN p2.
      PERFORM frm_get_backlog.
      PERFORM frm_dislay_backlog.
    WHEN p3.
      PERFORM frm_del_backlog.

  ENDCASE.
*&---------------------------------------------------------------------*
*&      Form  FRM_BACKUP_TABLE
*&---------------------------------------------------------------------*
FORM frm_backup_table USING p_table
                            p_lines.
  DATA: lt_tab  TYPE REF TO data,
        lt_tab1 TYPE REF TO data,
        ls_tab  TYPE REF TO data.

  DATA: lv_line  TYPE i,
        lv_times TYPE i,
        lv_end   TYPE c,
        lc_line  TYPE i VALUE 300000.

  DATA: lv_text TYPE string.
  DATA: lv_guid TYPE guid,
        lv_key  TYPE char32.
  DATA: ls_ztbackup_data TYPE ztbackup_data,
        ls_ztbackup_head TYPE ztbackup_head.



  FIELD-SYMBOLS: <fs_tab>  TYPE STANDARD TABLE,
                 <fs_wa>,
                 <fs_tab1> TYPE STANDARD TABLE.


  SELECT SINGLE tabname
    INTO @DATA(l_tabname)
    FROM dd02l
    WHERE tabname = @p_table.
  IF sy-subrc <> 0.
    WRITE:/ p_table,'-数据库表不存在'.
    EXIT.
  ENDIF.

  CREATE DATA lt_tab TYPE TABLE OF (p_table).
  CREATE DATA lt_tab1 TYPE TABLE OF (p_table).
  CREATE DATA ls_tab TYPE REF TO  (p_table).

  ASSIGN lt_tab->* TO <fs_tab>.
  ASSIGN lt_tab1->* TO <fs_tab1>.
  ASSIGN ls_tab->* TO <fs_wa>.


  OPEN CURSOR zc_bk FOR
  SELECT *
    FROM (p_table).
*  INTO TABLE  <fs_tab>.
  IF sy-subrc <> 0.
    " MESSAGE '未取到任何数据' TYPE 'I' DISPLAY LIKE 'E'.
    WRITE:/ p_table,'-未取到任何数据'.
    CLOSE CURSOR zc_bk.
    EXIT.
  ENDIF.
  DO.
    IF p_lines IS NOT INITIAL.
      lc_line = p_lines.
    ENDIF.
    FETCH NEXT CURSOR @zc_bk INTO TABLE @<fs_tab> PACKAGE SIZE @lc_line.
    IF sy-subrc <> 0.
      CLOSE CURSOR zc_bk.
      COMMIT WORK AND WAIT.
      EXIT.
    ENDIF.

    DESCRIBE TABLE <fs_tab> LINES lv_line.

    ls_ztbackup_head-bc_guid    = cl_swf_utl_guid_create=>get_guid_16( ).

    ls_ztbackup_head-tablename  = p_table.
    DESCRIBE TABLE <fs_tab> LINES ls_ztbackup_head-lines.
    "ls_ztbackup_head-lines      = lv_times.
    ls_ztbackup_head-datum      = sy-datum .
    ls_ztbackup_head-uzeit      = sy-uzeit.
    ls_ztbackup_head-uname      = sy-uname.

    INSERT ztbackup_head FROM ls_ztbackup_head.

    LOOP AT <fs_tab> ASSIGNING <fs_wa>.
      CLEAR lv_end.
      lv_times = lv_times + 1.

      APPEND <fs_wa> TO <fs_tab1>.
      AT LAST.
        lv_end = 'X'.
      ENDAT.
      IF lv_times = lc_line.
        lv_end = 'X'.
      ENDIF.

      IF lv_end = 'X'.
        CLEAR lv_end.

        lv_guid = cl_swf_utl_guid_create=>get_guid_16( ).
        lv_key =  lv_guid.
        ztbackup_data-bc_guid   = ls_ztbackup_head-bc_guid.
        ztbackup_data-tablename = p_table.
        ztbackup_data-datum     = sy-datum.
        ztbackup_data-uzeit     = sy-uzeit.
        ztbackup_data-uname     = sy-uname.
        ztbackup_data-lines     = lv_times.

        lv_line = lv_times.
        CLEAR lv_times.
        EXPORT <fs_tab1> TO DATABASE ztbackup_data(a1) ID lv_key.
        IF sy-subrc <> 0.
          WRITE:/ p_table,'-数据备份失败'.
        ELSE.
          WRITE:/ p_table,'-成功备份数据条目数:', lv_line.
        ENDIF.
        CLEAR <fs_tab1>.

        IF sy-subrc = 0.
*          COMMIT WORK AND WAIT.
        ENDIF.
      ENDIF.
    ENDLOOP.
  ENDDO.

ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  FRM_DISPLAY_BACKUPTABLE
*&---------------------------------------------------------------------*
FORM frm_display_backuptable .
  DATA: ls_ztbackup_data TYPE ztbackup_data.
  DATA: lt_tab  TYPE REF TO data,
        lt_tab1 TYPE REF TO data,
        ls_tab  TYPE REF TO data.

  DATA: lv_line TYPE i.
  DATA: lv_text TYPE string.
  DATA: lv_guid TYPE guid,
        lv_key  TYPE char32.
  DATA: lt_ztbackup_data TYPE TABLE OF ztbackup_data WITH HEADER LINE.



  DATA:
    ls_layout   TYPE lvc_s_layo,
    lt_fieldcat TYPE kkblo_t_fieldcat, " WITH HEADER LINE,
    lv_st_name  TYPE dd02l-tabname.

  DATA: lt_fieldcat_lvc TYPE lvc_t_fcat,
        wa_fieldcat_lvc TYPE lvc_s_fcat,

        gd_tab_group    TYPE slis_t_sp_group_alv,
        gd_layout       TYPE lvc_s_layo,     "slis_layout_alv,
        gd_repid        LIKE sy-repid.


  FIELD-SYMBOLS:<fs_table> TYPE STANDARD TABLE.
  FIELD-SYMBOLS:<fs_fieldcat> TYPE lvc_s_fcat.

  " 获取备份数据

  SELECT *
    INTO TABLE lt_ztbackup_data
    FROM ztbackup_data
    WHERE bc_guid = gt_log-bc_guid.
  IF sy-subrc <> 0.
    MESSAGE '找不到备份数据' TYPE 'I' DISPLAY LIKE 'E'.
    EXIT.
  ELSE.
    SORT lt_ztbackup_data BY srtfd.
    DELETE ADJACENT DUPLICATES FROM lt_ztbackup_data COMPARING srtfd.
  ENDIF.
  CREATE DATA lt_tab TYPE TABLE OF (gt_log-tablename).
  CREATE DATA lt_tab1 TYPE TABLE OF (gt_log-tablename).
  CREATE DATA ls_tab TYPE REF TO  (gt_log-tablename).

  ASSIGN lt_tab->* TO <fs_tab>.
  ASSIGN lt_tab1->* TO <fs_tab1>.
  ASSIGN ls_tab->* TO <fs_wa>.

*  SELECT SINGLE *
*    INTO ls_ztbackup_data
*    FROM ztbackup_data
*    WHERE srtfd     = gt_log-srtfd
*      AND tablename = gt_log-tablename.
*  IF sy-subrc <> 0.
*    MESSAGE '输入数据备份版本不存在' TYPE 'S' DISPLAY LIKE 'E'.
*    REJECT.
*  ENDIF.
  LOOP AT lt_ztbackup_data.
    IMPORT <fs_tab1> FROM DATABASE ztbackup_data(a1) ID lt_ztbackup_data-srtfd IGNORING CONVERSION ERRORS.
    APPEND LINES OF <fs_tab1> TO <fs_tab>.
    CLEAR <fs_tab1>.
  ENDLOOP.

  " 显示数据

  ls_layout-zebra             = 'X'.

  lv_st_name = gt_log-tablename.

  CALL FUNCTION 'LVC_FIELDCATALOG_MERGE'
    EXPORTING
      i_structure_name       = lv_st_name
    CHANGING
      ct_fieldcat            = lt_fieldcat_lvc
    EXCEPTIONS
      inconsistent_interface = 1
      OTHERS                 = 2.
  IF sy-subrc <> 0.
* Implement suitable error handling here
  ENDIF.

  LOOP AT lt_fieldcat_lvc INTO wa_fieldcat_lvc.
    CASE wa_fieldcat_lvc-fieldname.
      WHEN 'RELID' OR 'SRTF2' OR 'CLUSTR' OR 'CLUSTD'.
        wa_fieldcat_lvc-no_out = 'X'.
        MODIFY lt_fieldcat_lvc FROM wa_fieldcat_lvc.
    ENDCASE.
  ENDLOOP.

  ls_layout-cwidth_opt = 'X'.

  CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY_LVC'
    EXPORTING
      i_callback_program       = sy-repid
      i_callback_pf_status_set = 'FRM_SET_STATUS'
      i_callback_user_command  = 'FRM_USER_COMMAND2'
      is_layout_lvc            = ls_layout
      it_fieldcat_lvc          = lt_fieldcat_lvc
    TABLES
      t_outtab                 = <fs_tab>
    EXCEPTIONS
      program_error            = 1
      OTHERS                   = 2.
  IF sy-subrc <> 0.
*   Implement suitable error handling here
  ENDIF.


ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  FRM_CHECK_TABLE
*&---------------------------------------------------------------------*
FORM frm_check_table USING p_table.

ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  FRM_DISPLAY_BACKLOG
*&---------------------------------------------------------------------*
FORM frm_get_backlog .

  SELECT *
    INTO CORRESPONDING FIELDS OF TABLE gt_log
    FROM ztbackup_head
  WHERE tablename IN s_table.
  SORT gt_log BY datum DESCENDING uzeit DESCENDING.
  "DELETE ADJACENT DUPLICATES FROM gt_log COMPARING srtfd.


ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  FRM_DISLAY_BACKLOG
*&---------------------------------------------------------------------*
FORM frm_dislay_backlog .
  DATA:
    ls_layout   TYPE lvc_s_layo,
    lt_fieldcat TYPE kkblo_t_fieldcat, " WITH HEADER LINE,
    lv_st_name  TYPE dd02l-tabname.

  DATA: lt_fieldcat_lvc TYPE lvc_t_fcat,
        wa_fieldcat_lvc TYPE lvc_s_fcat,

        gd_tab_group    TYPE slis_t_sp_group_alv,
        gd_layout       TYPE lvc_s_layo,     "slis_layout_alv,
        gd_repid        LIKE sy-repid.


  FIELD-SYMBOLS:<fs_table> TYPE STANDARD TABLE.
  FIELD-SYMBOLS:<fs_fieldcat> TYPE lvc_s_fcat.

  ls_layout-zebra             = 'X'.

  lv_st_name = 'ZTBACKUP_HEAD'.

  CALL FUNCTION 'LVC_FIELDCATALOG_MERGE'
    EXPORTING
      i_structure_name       = lv_st_name
    CHANGING
      ct_fieldcat            = lt_fieldcat_lvc
    EXCEPTIONS
      inconsistent_interface = 1
      OTHERS                 = 2.
  IF sy-subrc <> 0.
* Implement suitable error handling here
  ENDIF.

  LOOP AT lt_fieldcat_lvc INTO wa_fieldcat_lvc.
    CASE wa_fieldcat_lvc-fieldname.
      WHEN 'RELID' OR 'SRTF2' OR 'CLUSTR' OR 'CLUSTD'.
        wa_fieldcat_lvc-no_out = 'X'.
        MODIFY lt_fieldcat_lvc FROM wa_fieldcat_lvc.
    ENDCASE.
  ENDLOOP.

  ls_layout-cwidth_opt = 'X'.

  CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY_LVC'
    EXPORTING
      i_callback_program      = sy-repid
      i_callback_user_command = 'FRM_USER_COMMAND'
      is_layout_lvc           = ls_layout
      it_fieldcat_lvc         = lt_fieldcat_lvc
    TABLES
      t_outtab                = gt_log
    EXCEPTIONS
      program_error           = 1
      OTHERS                  = 2.
  IF sy-subrc <> 0.
*   Implement suitable error handling here
  ENDIF.
ENDFORM.


FORM frm_user_command       USING
       i_okcode   LIKE sy-ucomm
       i_selfield TYPE slis_selfield.
  "  BREAK-POINT.
  CASE i_okcode.
    WHEN '&IC1'.
      READ TABLE gt_log INDEX i_selfield-tabindex.
      PERFORM frm_display_backuptable.

  ENDCASE.
ENDFORM.

*&---------------------------------------------------------------------*
*&      Form  FRM_BACKUP
*&---------------------------------------------------------------------*
FORM frm_backup .
  DATA: lt_ztbackup_conf TYPE TABLE OF ztbackup_conf WITH HEADER LINE.
  DATA: lv_line TYPE i,
        lv_fin  TYPE i,
        lv_pec  TYPE i,
        lv_text TYPE string.
  SELECT *
    INTO TABLE lt_ztbackup_conf
    FROM ztbackup_conf
  WHERE tablename IN s_table.
  IF sy-subrc <> 0.
    MESSAGE '配置表中找不到备份的表'  TYPE 'S' DISPLAY LIKE 'E'.
    REJECT.
  ENDIF.
  DESCRIBE TABLE lt_ztbackup_conf LINES lv_line.
  LOOP AT lt_ztbackup_conf.
    lv_fin = lv_fin + 1.
    lv_text = '正在备份表' && lt_ztbackup_conf-tablename.
    lv_pec = lv_fin / lv_line * 100.
    CALL FUNCTION 'SAPGUI_PROGRESS_INDICATOR'
      EXPORTING
        percentage = lv_pec
        text       = lv_text.
    PERFORM frm_backup_table USING lt_ztbackup_conf-tablename lt_ztbackup_conf-lines.
  ENDLOOP.

ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  SET_FUNCTION_ICON_AND_TEXT
*&---------------------------------------------------------------------*
FORM set_function_icon_and_text .
  DATA ls_dyntxt TYPE smp_dyntxt.
* Icon - common part
  ls_dyntxt-icon_id = icon_change.
*
  ls_dyntxt-icon_text = TEXT-m01.
  sscrfields-functxt_01 = ls_dyntxt.

ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  DEAL_SEL_SCREEN_UCOMM
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->P_SSCRFIELDS_UCOMM  text
*----------------------------------------------------------------------*
FORM deal_sel_screen_ucomm  USING    p_ucomm.
  DATA viewn LIKE tvdir-tabname.
  DATA BEGIN OF sllst OCCURS 0.
  INCLUDE STRUCTURE vimsellist.
  DATA END OF sllst.
  DATA BEGIN OF exclf OCCURS 0.
  INCLUDE STRUCTURE vimexclfun.
  DATA END OF exclf.
  IF p_ucomm = 'FC01'.
    CALL FUNCTION 'VIEW_MAINTENANCE_CALL'
      EXPORTING
        action         = 'U'
        view_name      = 'ZTBACKUP_CONF'
      TABLES
        dba_sellist    = sllst
        excl_cua_funct = exclf
      EXCEPTIONS
        OTHERS         = 01.
  ENDIF.

ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  FRM_SET_SCREEN
*&---------------------------------------------------------------------*
FORM frm_set_screen .

  LOOP AT SCREEN.
    IF p3 = 'X'.
      IF screen-group1 = 'M01'.
        screen-active = '1'.
      ENDIF.
    ELSE.
      IF screen-group1 = 'M01'.
        screen-active = '0'.
      ENDIF.
    ENDIF.
    MODIFY SCREEN.
  ENDLOOP.
ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  FRM_DEL_BACKLOG
*&---------------------------------------------------------------------*
FORM frm_del_backlog .
  DATA: lt_ztbackup_head TYPE TABLE OF ztbackup_head WITH HEADER LINE.

  SELECT *
    INTO TABLE lt_ztbackup_head
    FROM ztbackup_head
    WHERE tablename IN s_table
      AND datum     IN s_datum
      AND uzeit     IN s_uzeit.
  LOOP AT lt_ztbackup_head.
    DELETE FROM ztbackup_head WHERE bc_guid = lt_ztbackup_head-bc_guid.
    DELETE FROM ztbackup_data WHERE bc_guid = lt_ztbackup_head-bc_guid.
  ENDLOOP.
  IF sy-subrc = 0.
    COMMIT WORK AND WAIT.
    MESSAGE '备份数据已删除' TYPE 'S'.
  ELSE.
    MESSAGE '未删除任何备份数据' TYPE 'S'.
  ENDIF.
ENDFORM.

*&---------------------------------------------------------------------*
*&      Form  FRM_PF_STATUS
*&---------------------------------------------------------------------*
FORM frm_set_status USING extab TYPE slis_t_extab.
  SET PF-STATUS 'ZSTANDARD' EXCLUDING extab.

ENDFORM.


FORM frm_user_command2       USING
       i_okcode   LIKE sy-ucomm
       i_selfield TYPE slis_selfield.
  "  BREAK-POINT.
  CASE i_okcode.
    WHEN 'RECOVER'.
      PERFORM frm_recover.
  ENDCASE.
ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  FRM_RECOVER
*&---------------------------------------------------------------------*
FORM frm_recover .
  CASE gt_log-tablename.
    WHEN 'ZTSD0022'.
      PERFORM frm_recover_ztsd0022.

    WHEN 'ZTPL0034'.
      PERFORM frm_recover_ztpl0034.

    WHEN 'ZTFI0182'.
      PERFORM frm_recover_ztfi0182.

*****恢复
    WHEN 'ZTPO1008_10'.
      PERFORM frm_recover_ztpo1008_10.

    WHEN OTHERS.
      MESSAGE '该表没有恢复的逻辑.' TYPE 'I'.

  ENDCASE.


ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  FRM_RECOVER_ZTSD0022
*&---------------------------------------------------------------------*
FORM frm_recover_ztsd0022 .
*  FIELD-SYMBOLS: <fs_tab>  TYPE STANDARD TABLE,
*                 <fs_tab1> TYPE STANDARD TABLE,
*                 <fs_wa>.
  DATA: lt_backup TYPE TABLE OF ztsd0022 WITH HEADER LINE.
  APPEND LINES OF <fs_tab> TO lt_backup.

  LOOP AT lt_backup.
    UPDATE ztsd0022
      SET confirmincomedate = lt_backup-confirmincomedate
      WHERE id = lt_backup-id.
  ENDLOOP.

  COMMIT WORK AND WAIT.
  MESSAGE '数据恢复成功' TYPE 'S'.
ENDFORM.

*&---------------------------------------------------------------------*
*&      Form  FRM_RECOVER_ZTPL0034
*&---------------------------------------------------------------------*
FORM frm_recover_ztpl0034 .
  DATA: lt_backup TYPE TABLE OF ztpl0034 WITH HEADER LINE.
  APPEND LINES OF <fs_tab> TO lt_backup.

  LOOP AT lt_backup.
    UPDATE ztpl0034
      SET zjftz = lt_backup-zjftz
      WHERE pspnr = lt_backup-pspnr.
  ENDLOOP.

  COMMIT WORK AND WAIT.
  MESSAGE '数据恢复成功' TYPE 'S'.
ENDFORM.

FORM frm_recover_ztfi0182.
  DATA: lt_backup TYPE TABLE OF ztfi0182 WITH HEADER LINE.

  LOOP AT <fs_tab> ASSIGNING FIELD-SYMBOL(<fs_tabline>).
    APPEND INITIAL LINE TO lt_backup ASSIGNING FIELD-SYMBOL(<fs_backup>).
    MOVE-CORRESPONDING <fs_tabline> TO <fs_backup> .
  ENDLOOP.
  MODIFY ztfi0182 FROM TABLE lt_backup[].
  COMMIT WORK AND WAIT.
  MESSAGE '数据恢复成功' TYPE 'S'.
ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  FRM_RECOVER_ZTPO1008_10
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
FORM frm_recover_ztpo1008_10 .
  DATA: lt_backup TYPE TABLE OF ztpo1008_10 WITH HEADER LINE.


  LOOP AT <fs_tab> ASSIGNING FIELD-SYMBOL(<fs_tabline>).
    APPEND INITIAL LINE TO lt_backup ASSIGNING FIELD-SYMBOL(<fs_backup>).
    MOVE-CORRESPONDING <fs_tabline> TO <fs_backup> .
  ENDLOOP.

  DELETE lt_backup WHERE zchild_id IS  INITIAL.
  IF NOT lt_backup[] IS INITIAL.
    SELECT rp_guid_i,class
         INTO TABLE @DATA(lt_po1008_02)
         FROM ztpo1008_02
         FOR ALL ENTRIES IN @lt_backup
    WHERE rp_guid_i = @lt_backup-rp_guid_i.
    SELECT lifnr,class,specif,zchild_id,zchild
           INTO TABLE @DATA(lt_po1008_14)
           FROM ztpo1008_14
           FOR ALL ENTRIES IN @lt_backup
    WHERE lifnr  = @lt_backup-lifnr
      AND specif = @lt_backup-specif
      AND zchild = @lt_backup-zchild_id.
  ENDIF.

  SORT lt_po1008_02 BY rp_guid_i.
  SORT lt_po1008_14 BY lifnr class specif zchild.
  LOOP AT lt_backup ASSIGNING <fs_backup>.
    READ TABLE lt_po1008_02 ASSIGNING FIELD-SYMBOL(<fs_po1008_02>) WITH KEY <fs_backup>-rp_guid_i BINARY SEARCH.
    IF sy-subrc EQ 0.
      IF NOT <fs_po1008_02>-class IS INITIAL.
        READ TABLE lt_po1008_14 ASSIGNING FIELD-SYMBOL(<fs_po1008_14>)
                                WITH KEY lifnr  =  <fs_backup>-lifnr
                                         class  =  <fs_po1008_02>-class
                                         specif =  <fs_backup>-specif
                                         zchild = <fs_backup>-zchild_id BINARY SEARCH.
        IF sy-subrc EQ 0.
          <fs_backup>-zchild_id = <fs_po1008_14>-zchild_id.
        ENDIF.
      ENDIF.
    ENDIF.
  ENDLOOP.

  MODIFY ztpo1008_10 FROM TABLE lt_backup[].
  COMMIT WORK AND WAIT.
  MESSAGE '数据恢复成功' TYPE 'S'.


ENDFORM.


步骤:

1.第一步就是复制一个新表出来,改好字段。

2.创建一个程序,以下程序需要输入两个表名,一个旧表一个新表,不多说,上代码。

*&---------------------------------------------------------------------*
*& Report ZP_COPY_DATA
*&---------------------------------------------------------------------*
*& 程序功能:动态备份表数据至新表
*&---------------------------------------------------------------------*
REPORT zp_copy_data.

FIELD-SYMBOLS: <fs_old> TYPE table,
               <fs_new> TYPE table.

DATA: dyn_table_old TYPE REF TO data,
      dyn_table_new TYPE REF TO data.

DATA: structure_name TYPE dd02l-tabname,
      ls_fieldcat    TYPE lvc_s_fcat,
      gt_fieldcat    TYPE lvc_t_fcat.

*&---------------------------------------------------------------------*
*& Selection Screen.
*&---------------------------------------------------------------------*
SELECTION-SCREEN BEGIN OF BLOCK b1 WITH FRAME TITLE TEXT-001.
PARAMETERS: old_tab TYPE char16 OBLIGATORY.
SELECTION-SCREEN SKIP 1.
PARAMETERS: new_tab TYPE char16 OBLIGATORY.
SELECTION-SCREEN END OF BLOCK b1.

*&---------------------------------------------------------------------*
*& START-OF-SELECTION.
*&---------------------------------------------------------------------*
START-OF-SELECTION.
  IF old_tab+0(1) <> 'Z' OR new_tab+0(1) <> 'Z'.
    MESSAGE '请输入自建表名' TYPE 'S' DISPLAY LIKE 'E'.
    EXIT.
  ENDIF.

*****动态创建旧内表********
  structure_name = old_tab.

  CALL FUNCTION 'LVC_FIELDCATALOG_MERGE'
    EXPORTING
      i_structure_name = structure_name
    CHANGING
      ct_fieldcat      = gt_fieldcat.

  CALL METHOD cl_alv_table_create=>create_dynamic_table
    EXPORTING
      it_fieldcatalog = gt_fieldcat
    IMPORTING
      ep_table        = dyn_table_old.

  ASSIGN dyn_table_old->* TO <fs_old>.

*****动态创建新内表******
  structure_name = new_tab.

  REFRESH gt_fieldcat.

  CALL FUNCTION 'LVC_FIELDCATALOG_MERGE'
    EXPORTING
      i_structure_name = structure_name
    CHANGING
      ct_fieldcat      = gt_fieldcat.

  CALL METHOD cl_alv_table_create=>create_dynamic_table
    EXPORTING
      it_fieldcatalog = gt_fieldcat
    IMPORTING
      ep_table        = dyn_table_new.

  ASSIGN dyn_table_new->* TO <fs_new>.

*****把旧表数据拷贝到内表
  SELECT * FROM (old_tab) INTO CORRESPONDING FIELDS OF TABLE <fs_old>.

*****内表数据插入到新表
  IF lines( <fs_old> ) > 0.
    MOVE-CORRESPONDING <fs_old> TO <fs_new>.
    CHECK lines( <fs_new> ) > 0.
    INSERT (new_tab) FROM TABLE <fs_new>.
    IF sy-subrc = 0.
      COMMIT WORK.
      MESSAGE '备份成功' TYPE 'S'.
    ELSE.
      ROLLBACK WORK.
      MESSAGE '备份失败' TYPE 'S' DISPLAY LIKE 'E'.
    ENDIF.
  ENDIF.

3.界面的效果做的比较简单,点击按钮后旧表数据自动备份到新表。
3.1还原的就是旧表就填新的表名,新表填旧的表名即可。

  • 20
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值