【应用场景】重要的业务数据表结构需要调整,某个字段的长度需要修改等,但数据库表中已经存在很多数据,冒然直接改表字段可能会导致数据丢失,这种问题的后果可能非常严重。
【解题思路】复制出一个新表,在新表里改好字段长度,然后把旧表的数据插入到新表,这一步就是备份数据,再修改旧表的字段长度,如果旧表数据丢失,可以立马把新表的数据复制回旧表,这样就可以解决一些不能预见的的问题。最后数据切换成功运行一段时间后,再把备份的表和数据删除。
【核心逻辑】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还原的就是旧表就填新的表名,新表填旧的表名即可。