Folgende Info ist nicht verifiziert:
SE11 Technical Settings / Log Data Changes
Setting Systeme Profile Paraemter Rec/Client (DEFAULT OFF)
Setting Rec/Client Parameter for Logging
SCU3 View Table Logging of all tables which have got Log Data Changes ON
oder
SCDO
Change log for Z-Table Maintenance (via SCDO)
Generally we don’t need table logging for custom table maintenance (SM30), but it is important and needed for some cases. All customizing tables are automatically recorded by default but if you use regular Application tables (master and transaction data), you’re about to get your hands dirty .)
Sample Z-Table
Automatic table change logging
Actually this is not suitable for our case because we want to log particular tables but it’s good to know..
You can use Automatic table change logging by setting the “Log Data Changes” flag under the table “Technical Settings” in SE11 (p.s. You must activate the table again after saving it, otherwise it will not be effective).
Next, to be able to log the table changes you must activate the system profile parameter Rec/Client. The default setting is OFF (no changes are logged). BASIS Team can assist you in this.
Setting Rec/Client Parameter for Logging
However, SAP recommends this option only in systems where this is worthwhile, because all tables with “Log data changes” option will be logged, so this has a major impact on performance (Even for one client)
You can now view the changes via SCU3 (Table: DBTABLOG)
SCU3-Logs
Logging using Change Document Objects (SCDO)
To log changes for particular tables in SM30 Maintenance, we can use change document objects and its associated functions.
Let’s do it step by step;
- Go to SCDO and create a Change Document Object (Choose Yes for opening Namespace Pop-ups)
- Insert the entries and choose Utilities → Generate update pgm.
- In the opening pop-up, give function group name (it will be created if it doesn’t exist) and generate the update program for the object by clicking Activate.
- In the Data Element → Further Characteristics Tab, set the “Change Document” flag for the objects which you want to track changes. As you recognise, many SAP standard data elements come with the selected flag.
- You can now insert appropriate calls in the corresponding programs, for our example we will use Table Maintenance Events.
- Under the table maintenance (SE56) go to Environment → Modification → Events.
Give the events & subroutine names as shown in the figure and click the Editor icon to create suggested include (L<fg_name>F01).
Now, you can just copy and paste the code snippet (link is below) into the created include. It will begin to create logs in CDHDR-CDPOS tables. You can now view the changes via reports CHANGEDOCU_READ & RSSCD100.
SCDO-Logs
*&----------------------------------------------------------------*
*& Form F_BEFORE_SAVE
*&----------------------------------------------------------------*
FORM f_before_save ##CALLED.
TYPES: BEGIN OF ty_tcdrp,
object TYPE cdobjectcl,
reportname TYPE cdreport,
END OF ty_tcdrp,
BEGIN OF ty_view_tab,
object TYPE cdobjectcl,
tabname TYPE cdtabname,
END OF ty_view_tab.
DATA: lt_ptab TYPE STANDARD TABLE OF string,
lv_prog TYPE string,
lv_mess TYPE string,
lv_sid TYPE string,
lt_obj TYPE STANDARD TABLE OF ty_view_tab,
lt_tcdrp TYPE STANDARD TABLE OF ty_tcdrp,
lv_fugn TYPE funct_pool,
lv_table TYPE cdtabname,
lv_namesfunc TYPE namespace,
lv_funcgroup TYPE progname,
lv_namesprog TYPE namespace,
lv_program TYPE progname,
lrt_tabname TYPE RANGE OF tabname,
lt_dd26v TYPE TABLE OF dd26v,
lv_object TYPE cdobjectcl.
" Get tabnames
" DD: Interface for reading a view from the ABAP/4 Dictionary
CALL FUNCTION 'DDIF_VIEW_GET'
EXPORTING
name = vim_view_name
TABLES
dd26v_tab = lt_dd26v
EXCEPTIONS
illegal_input = 1
OTHERS = 2.
IF sy-subrc IS NOT INITIAL.
MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.
IF lt_dd26v IS INITIAL.
APPEND INITIAL LINE TO lrt_tabname ASSIGNING FIELD-SYMBOL(<lrs_tabname>).
<lrs_tabname>-sign = 'I'.
<lrs_tabname>-option = 'EQ'.
<lrs_tabname>-low = vim_view_name.
ELSE.
SORT lt_dd26v BY tabname.
DELETE ADJACENT DUPLICATES FROM lt_dd26v COMPARING tabname.
"*-
LOOP AT lt_dd26v INTO DATA(ls_dd26v).
APPEND INITIAL LINE TO lrt_tabname ASSIGNING <lrs_tabname>.
<lrs_tabname>-sign = 'I'.
<lrs_tabname>-option = 'EQ'.
<lrs_tabname>-low = ls_dd26v-tabname.
ENDLOOP.
ENDIF.
" Objects for change document creation
SELECT object tabname
FROM tcdob
INTO TABLE lt_obj
WHERE tabname IN lrt_tabname
##WARN_OK.
IF sy-subrc IS NOT INITIAL.
" No change document objects found
MESSAGE i899(cd).
RETURN.
ENDIF.
" Information on Include Reports Generated by RSSCD000
SELECT object reportname
FROM tcdrp
INTO TABLE lt_tcdrp
FOR ALL ENTRIES IN lt_obj
WHERE object EQ lt_obj-object
##WARN_OK.
IF sy-subrc IS NOT INITIAL.
" Update program does not yet exist
MESSAGE i446(m2).
RETURN.
ENDIF.
" View Directory
SELECT SINGLE area
FROM tvdir
INTO lv_fugn
WHERE tabname EQ vim_view_name.
"*-
LOOP AT lt_obj ASSIGNING FIELD-SYMBOL(<ls_obj>).
READ TABLE lt_tcdrp ASSIGNING FIELD-SYMBOL(<ls_tcdrp>)
WITH KEY object = <ls_obj>-object.
IF sy-subrc IS NOT INITIAL.
CONTINUE.
ENDIF.
" Split namespace
CLEAR: lv_namesprog, lv_program.
lv_program = <ls_tcdrp>-reportname.
CALL FUNCTION 'RS_NAME_SPLIT_NAMESPACE'
EXPORTING
name_with_namespace = lv_program
IMPORTING
namespace = lv_namesprog
name_without_namespace = lv_program
EXCEPTIONS
delimiter_error = 1
OTHERS = 2.
IF sy-subrc <> 0.
lv_program = <ls_tcdrp>-reportname.
ENDIF.
CLEAR: lv_namesfunc, lv_funcgroup.
lv_funcgroup = lv_fugn.
CALL FUNCTION 'RS_NAME_SPLIT_NAMESPACE'
EXPORTING
name_with_namespace = lv_funcgroup
IMPORTING
namespace = lv_namesfunc
name_without_namespace = lv_funcgroup
EXCEPTIONS
delimiter_error = 1
OTHERS = 2.
IF sy-subrc <> 0.
lv_funcgroup = lv_fugn.
ENDIF.
" Namespace conversion
lv_object = <ls_obj>-object.
IF lv_object(1) = '/'.
SHIFT lv_object LEFT DELETING LEADING '/'.
REPLACE FIRST OCCURRENCE OF '/' IN lv_object WITH '_'.
ENDIF.
lv_table = <ls_obj>-tabname.
IF lv_table(1) = '/'.
SHIFT lv_table LEFT DELETING LEADING '/'.
REPLACE FIRST OCCURRENCE OF '/' IN lv_table WITH '_'.
ENDIF.
" Subroutine pool
APPEND ##NO_TEXT:
`PROGRAM SUBPOOL.` TO lt_ptab,
` INCLUDE ` && lv_namesprog && `F` && lv_program && `CDT.` TO lt_ptab,
` INCLUDE ` && lv_namesprog && `F` && lv_program && `CDC.` TO lt_ptab,
` FORM f_process.` TO lt_ptab,
` TYPES: BEGIN OF total.` TO lt_ptab,
` INCLUDE STRUCTURE ` && vim_view_name && `.` TO lt_ptab,
` INCLUDE STRUCTURE vimflagtab.` TO lt_ptab,
` TYPES: END OF total.` TO lt_ptab,
` FIELD-SYMBOLS: <fs_total> TYPE ANY TABLE,` TO lt_ptab,
` <fs_total_wa> TYPE total,` TO lt_ptab,
` <fs_x_namtab> TYPE ANY TABLE,` TO lt_ptab,
` <fs_x_namtab_wa> TYPE vimnamtab,` TO lt_ptab,
` <fs_field> TYPE any.` TO lt_ptab,
` DATA: lv_tabname(40) TYPE c VALUE '(` && lv_namesfunc && `SAPL` && lv_funcgroup && `)TOTAL[]',` TO lt_ptab,
` lv_cond_line TYPE string,` TO lt_ptab,
` lv_cond_line2 TYPE string.` TO lt_ptab,
` ASSIGN (lv_tabname) TO <fs_total>.` TO lt_ptab,
` LOOP AT <fs_total> ASSIGNING <fs_total_wa> CASTING.` TO lt_ptab,
` CASE <fs_total_wa>-action.` TO lt_ptab,
` WHEN 'U'. " Update` TO lt_ptab,
` lv_tabname = '(` && lv_namesfunc && `SAPL` && lv_funcgroup && `)X_NAMTAB[]'.` TO lt_ptab,
` ASSIGN (lv_tabname) TO <fs_x_namtab>.` TO lt_ptab,
` lv_cond_line2 = |keyflag EQ 'X' AND viewfield NE 'MANDT'|.` TO lt_ptab,
` LOOP AT <fs_x_namtab> ASSIGNING <fs_x_namtab_wa> WHERE (lv_cond_line2).` TO lt_ptab,
` ASSIGN COMPONENT <fs_x_namtab_wa>-viewfield OF STRUCTURE <fs_total_wa> TO <fs_field>.` TO lt_ptab,
` IF sy-subrc IS INITIAL.` TO lt_ptab,
` lv_cond_line = lv_cond_line && |AND | && ` TO lt_ptab,
` <fs_x_namtab_wa>-viewfield && | EQ '| && <fs_field> && |' |.` TO lt_ptab,
` objectid = objectid && <fs_field>.` TO lt_ptab,
` UNASSIGN <fs_field>.` TO lt_ptab,
` ENDIF.` TO lt_ptab,
` ENDLOOP.` TO lt_ptab,
` IF sy-subrc IS INITIAL.` TO lt_ptab,
` SHIFT lv_cond_line LEFT BY 3 PLACES.` TO lt_ptab,
` SELECT SINGLE *` TO lt_ptab,
` FROM ` && <ls_obj>-tabname TO lt_ptab,
` INTO *` && <ls_obj>-tabname TO lt_ptab,
` WHERE (lv_cond_line).` TO lt_ptab,
` MOVE-CORRESPONDING <fs_total_wa> TO ` && <ls_obj>-tabname && `.` TO lt_ptab,
` objectid = objectid.` TO lt_ptab,
` tcode = sy-tcode.` TO lt_ptab,
` udate = sy-datum.` TO lt_ptab,
` utime = sy-uzeit.` TO lt_ptab,
` username = sy-uname.` TO lt_ptab,
` cdoc_upd_object = 'U'.` TO lt_ptab,
` upd_` && lv_table && ` = 'U'.` TO lt_ptab,
` PERFORM cd_call_` && lv_object && `.` TO lt_ptab,
` ENDIF.` TO lt_ptab,
` WHEN 'N'. " New` TO lt_ptab,
` lv_tabname = '(` && lv_namesfunc && `SAPL` && lv_funcgroup && `)X_NAMTAB[]'.` TO lt_ptab,
` ASSIGN (lv_tabname) TO <fs_x_namtab>.` TO lt_ptab,
` lv_cond_line2 = |keyflag EQ 'X' AND viewfield NE 'MANDT'|.` TO lt_ptab,
` LOOP AT <fs_x_namtab> ASSIGNING <fs_x_namtab_wa> WHERE (lv_cond_line2).` TO lt_ptab,
` ASSIGN COMPONENT <fs_x_namtab_wa>-viewfield OF STRUCTURE <fs_total_wa> TO <fs_field>.` TO lt_ptab,
` IF sy-subrc IS INITIAL.` TO lt_ptab,
` objectid = objectid && <fs_field>.` TO lt_ptab,
` UNASSIGN <fs_field>.` TO lt_ptab,
` ENDIF.` TO lt_ptab,
` ENDLOOP.` TO lt_ptab,
` IF sy-subrc IS INITIAL.` TO lt_ptab,
` MOVE-CORRESPONDING <fs_total_wa> TO ` && <ls_obj>-tabname && `.` TO lt_ptab,
` objectid = objectid.` TO lt_ptab,
` tcode = sy-tcode.` TO lt_ptab,
` udate = sy-datum.` TO lt_ptab,
` utime = sy-uzeit.` TO lt_ptab,
` username = sy-uname.` TO lt_ptab,
` cdoc_upd_object = 'I'.` TO lt_ptab,
` upd_` && lv_table && ` = 'I'.` TO lt_ptab,
` PERFORM cd_call_` && lv_object && `.` TO lt_ptab,
` ENDIF.` TO lt_ptab,
` WHEN 'D'. " Delete` TO lt_ptab,
` lv_tabname = '(` && lv_namesfunc && `SAPL` && lv_funcgroup && `)X_NAMTAB[]'.` TO lt_ptab,
` ASSIGN (lv_tabname) TO <fs_x_namtab>.` TO lt_ptab,
` lv_cond_line2 = |keyflag EQ 'X' AND viewfield NE 'MANDT'|.` TO lt_ptab,
` LOOP AT <fs_x_namtab> ASSIGNING <fs_x_namtab_wa> WHERE (lv_cond_line2).` TO lt_ptab,
` ASSIGN COMPONENT <fs_x_namtab_wa>-viewfield OF STRUCTURE <fs_total_wa> TO <fs_field>.` TO lt_ptab,
` IF sy-subrc IS INITIAL.` TO lt_ptab,
` objectid = objectid && <fs_field>.` TO lt_ptab,
` UNASSIGN <fs_field>.` TO lt_ptab,
` ENDIF.` TO lt_ptab,
` ENDLOOP.` TO lt_ptab,
` IF sy-subrc IS INITIAL.` TO lt_ptab,
` MOVE-CORRESPONDING <fs_total_wa> TO *` && <ls_obj>-tabname && `.` TO lt_ptab,
` objectid = objectid.` TO lt_ptab,
` tcode = sy-tcode.` TO lt_ptab,
` udate = sy-datum.` TO lt_ptab,
` utime = sy-uzeit.` TO lt_ptab,
` username = sy-uname.` TO lt_ptab,
` cdoc_upd_object = 'D'.` TO lt_ptab,
` upd_` && lv_table && ` = 'D'.` TO lt_ptab,
` PERFORM cd_call_` && lv_object && `.` TO lt_ptab,
` ENDIF.` TO lt_ptab,
` ENDCASE.` TO lt_ptab,
` CLEAR: lv_cond_line, lv_cond_line2, objectid, ` && <ls_obj>-tabname && `, *` && <ls_obj>-tabname && `.` TO lt_ptab,
` ENDLOOP.` TO lt_ptab,
` ENDFORM.` TO lt_ptab.
"*-
GENERATE SUBROUTINE POOL lt_ptab NAME lv_prog
MESSAGE lv_mess
SHORTDUMP-ID lv_sid.
IF sy-subrc = 0.
PERFORM ('F_PROCESS') IN PROGRAM (lv_prog) IF FOUND.
ELSEIF sy-subrc = 4.
MESSAGE lv_mess TYPE 'I'.
ELSEIF sy-subrc = 8.
MESSAGE lv_sid TYPE 'I'.
ENDIF.
CLEAR: lt_ptab.
ENDLOOP.
ENDFORM.
*&----------------------------------------------------------------*
*& Form F_AFTER_SAVE
*&----------------------------------------------------------------*
FORM f_after_save ##CALLED.
COMMIT WORK AND WAIT.
ENDFORM.