BW中自定義資料來源的Delta機制

fog911811發表於2012-07-26

轉載:http://blog.sina.com.cn/s/blog_5d3b01030100jvei.html

引用:http://mfg.kingdee.com/pages/chunguangz/blog/archive/2010/03/18/401671.aspx

BW提供了在R3端,自定義資料來源的功能,與FILE和WEBSERVICE相比,可以方便ABAP人員開發維護,並且,輕鬆實現了DELTA 的功能。

自定義的資料來源的資料提取方式分為3種:
1)資料庫/檢視:SAP提供的這種提取方式,系統為你定義好了提取程式,通過在資料庫中,設定增量相關欄位(如:時間戳、日期、數字),來輕鬆實現DELTA(增量)抽取,是BW中最常用的自定義資料來源,一般是通過程式將資料寫入表中。
2) 資訊集:即:SAP QUERY。可以設定表間相關的邏輯,相當於JOIN語句,把關聯的欄位作為資料來源。
3) FUNCTION MODULE:通過程式控制資料的提取,可以設定增量欄位,也可以不設定,通過一定邏輯將資料抽取,可以實現前兩種方式的自定義開發。這是最靈活的自定義資料來源。

下面,我們以資料庫和FM的方式為例,介紹自定義資料來源的應用:
資料庫/檢視
1. 建立用於資料來源的資料表:(SE11將允許表 維護勾選,方便測試)
其中,UPT_TIMESTAMP是我們設定的增量相關欄位:
 
2. 建立自定義資料來源:(RSO2)
創 建ZRSO01資料來源,點選“建立”:
 
按以下引數輸入,提取結構不允許輸入,啟用後,系統會為資料來源自動建立,點選“一般增量”按鈕:
 
按 以下螢幕輸入引數,並儲存:
增量欄位名:這個欄位在資料庫中存放了錄入時間戳(或日期或數字),資料抽取程式會按照BW請求的時間引數從資料庫中 抽取資料。
時間標記:通過時間戳方式實現增量,即:YYYYMMDDhhmmss格式。
日曆天數:按照天為單位實現增量。
數字指 針:按照數字增量抽取。
安全間隔上限:如果“時間標記”或“日曆天數”勾選,那麼此次可以設定,表示將請求時間戳 減去上限設定的間隔後的時間戳作為資料抽取條件。
舉例如下:
BW最後一個抽取時間戳為 20100101120000,下次抽取時間為20100101123000,使用者在12:25分做了一個記錄,直到12:35才儲存。這樣,這個記錄將不被抽取到BW中。我們設定的間隔上限,就是為了防止這樣的情況,如我們設定3600,表示在123000抽取的時候,將1小時之前的記錄再次抽取一遍,這樣防止資料的遺漏。重複抽取的資料只能將對DELTA抽取有影響,我們只能使用通過DSO上載的方式才能保證上載的資料正確。具體的解釋將在DELTA 抽取原理文章中介紹。同理,對於資料指標,我們不是設定上限,而是設定下限,請根據您的需求具體設定。
實時的啟用:SAP解釋是是否適用於RDA 方式的資料來源。
更改記錄的新狀態/附加增量:更改記錄的新狀態即表示使用後映象(AIE)的方式上載資料。附加增量表示以ADD方式上載資料。也是DELTA原理的內容,以後在介紹,我們這裡選擇AIE的方式上載。(簡單說就是以最後更改的記錄為準上載。ADD即將改變的差額上載)
 
3. 執行資料來源:
接下來,我們要在BW資料來源中複製目錄下的後設資料,並啟用資料來源,然後建立資訊包,此處不再贅述。其中,初始化資訊包公司程式碼被限制為 1003。
向資料庫中手工新增資料(SE16):
 
執行初始化資訊包:
我們會在RSA7中,檢視多了ZDSO01的初始 化記錄和統計資訊
 
點選 ,檢視統計記錄:
從中,我們可以看出BW系統請求的時間戳為20100318002659。
 
查 看資料來源的請求記錄,生成以下記錄:
表示資料來源中,1003的4條記錄被抽取到BW中:
 
接下來,我們在資料庫中在錄入2條記 錄,如下:
 
然後執行增量抽取資訊包,結果如下,只將一條記錄上載
我用的版本比較低,在這裡,安全間隔沒有起作用。
在上 載前可以使用RSA3測試,可以在FM RSA3_GEN_GET_DATA上設定斷點,檢視SELECT語句:
* Open Cursor for dynamical SELECT
          open cursor with hold g_cursor for
          select * from (g_s_oltpsource-extractor)
                 where (l_t_dynamic_select).
        endif.
* Fetch first data package
        fetch next cursor g_cursor
                     appending corresponding fields of table e_t_data
                     package size g_s_interface-maxsize.

 

使用Function Module抽取資料
基本與以上步驟相同,我們以提取上例中的表資料為例,在資料來源設定FM:
 
下面介紹FM的建立:
到 SE80中複製FUNCTION GROUP  RSAX,到新的FG:
 
選擇RSAX_BIW_GET_DATA_SIMPLE,選擇 複製,
複製到我們自己的FM Z_GET_DATA_FM
 
對FM進行修改,要點如下:
1)將TABLES中的 E_T_DA他的參考值,改為我們的資料來源表。
 
2)修改源程式:程式中,註明MY COMMENT的地方是需要我們修改的位置。大家可以通過RSA3測試跟蹤下效果,此處不再贅述,其他與資料庫資料來源是一樣的。
FUNCTION Z_GET_DATA_FM.
*"----------------------------------------------------------------------
*"*"Local interface:
*"  IMPORTING
*"     VALUE(I_REQUNR) TYPE  SRSC_S_IF_SIMPLE-REQUNR
*"     VALUE(I_DSOURCE) TYPE  SRSC_S_IF_SIMPLE-DSOURCE OPTIONAL
*"     VALUE(I_MAXSIZE) TYPE  SRSC_S_IF_SIMPLE-MAXSIZE OPTIONAL
*"     VALUE(I_INITFLAG) TYPE  SRSC_S_IF_SIMPLE-INITFLAG OPTIONAL
*"     VALUE(I_READ_ONLY) TYPE  SRSC_S_IF_SIMPLE-READONLY OPTIONAL
*"     VALUE(I_REMOTE_CALL) TYPE  SBIWA_FLAG DEFAULT SBIWA_C_FLAG_OFF
*"  TABLES
*"      I_T_SELECT TYPE  SRSC_S_IF_SIMPLE-T_SELECT OPTIONAL
*"      I_T_FIELDS TYPE  SRSC_S_IF_SIMPLE-T_FIELDS OPTIONAL
*"      E_T_DATA STRUCTURE  ZZC_TEST02 OPTIONAL
*"  EXCEPTIONS
*"      NO_MORE_DATA
*"      ERROR_PASSED_TO_MESS_HANDLER
*"----------------------------------------------------------------------

* Example: DataSource for table SFLIGHT
*  tables: sflight.          "MY COMMNET
  TABLES: ZZC_TEST02.

* Auxiliary Selection criteria structure
  DATA: L_S_SELECT TYPE SRSC_S_SELECT.

* Maximum number of lines for DB table
  STATICS: S_S_IF TYPE SRSC_S_IF_SIMPLE,

* counter
          S_COUNTER_DATAPAKID LIKE SY-TABIX,

* cursor
          S_CURSOR TYPE CURSOR.
* Select ranges
*  RANGES: L_R_CARRID  FOR SFLIGHT-CARRID,   "MY COMMENT
*          L_R_CONNID  FOR SFLIGHT-CONNID.   "MY COMMENT
RANGES: L_R_BUKRS FOR T001-BUKRS.
RANGES: L_R_TIMES FOR ZZC_TEST02-UPT_TIMESTAMP.
* Initialization mode (first call by SAPI) or data transfer mode
* (following calls) ?
  IF I_INITFLAG = SBIWA_C_FLAG_ON.

************************************************************************
* Initialization: check input parameters
*                 buffer input parameters
*                 prepare data selection
************************************************************************

* Check DataSource validity
    CASE I_DSOURCE.
*      when '0SAPI_SFLIGHT_SIMPLE'.       "MY COMMENT
      WHEN 'ZRSO02'.

      WHEN OTHERS.
        IF 1 = 2. MESSAGE E009(R3). ENDIF.
* this is a typical log call. Please write every error message like this
        LOG_WRITE 'E'                  "message type
                  'R3'                 "message class
                  '009'                "message number
                  I_DSOURCE   "message variable 1
                  ' '.                 "message variable 2
        RAISE ERROR_PASSED_TO_MESS_HANDLER.
    ENDCASE.

    APPEND LINES OF I_T_SELECT TO S_S_IF-T_SELECT.

* Fill parameter buffer for data extraction calls
    S_S_IF-REQUNR    = I_REQUNR.
    S_S_IF-DSOURCE = I_DSOURCE.
    S_S_IF-MAXSIZE   = I_MAXSIZE.

* Fill field list table for an optimized select statement
* (in case that there is no 1:1 relation between InfoSource fields
* and database table fields this may be far from beeing trivial)
    APPEND LINES OF I_T_FIELDS TO S_S_IF-T_FIELDS.

  ELSE.                 "Initialization mode or data extraction ?

************************************************************************
* Data transfer: First Call      OPEN CURSOR + FETCH
*                Following Calls FETCH only
************************************************************************

* First data package -> OPEN CURSOR
    IF S_COUNTER_DATAPAKID = 0.

* Fill range tables BW will only pass down simple selection criteria
* of the type SIGN = 'I' and OPTION = 'EQ' or OPTION = 'BT'.
*   MY COMMENT
*      loop at s_s_if-t_select into l_s_select where fieldnm = 'CARRID'.
*        move-corresponding l_s_select to l_r_carrid.
*        append l_r_carrid.
*      endloop.
*
*      loop at s_s_if-t_select into l_s_select where fieldnm = 'CONNID'.
*        move-corresponding l_s_select to l_r_connid.
*        append l_r_connid.
*      endloop.
*
      LOOP AT S_S_IF-T_SELECT INTO L_S_SELECT WHERE FIELDNM = 'BUKRS'.
        MOVE-CORRESPONDING L_S_SELECT TO L_R_BUKRS.
        APPEND L_R_BUKRS.
      ENDLOOP.
      LOOP AT S_S_IF-T_SELECT INTO L_S_SELECT WHERE FIELDNM =
       'UPT_TIMESTAMP'.
        MOVE-CORRESPONDING L_S_SELECT TO L_R_TIMES.
        APPEND L_R_TIMES.
      ENDLOOP.

 

* Determine number of database records to be read per FETCH statement
* from input parameter I_MAXSIZE. If there is a one to one relation
* between DataSource table lines and database entries, this is trivial.
* In other cases, it may be impossible and some estimated value has to
* be determined.
      OPEN CURSOR WITH HOLD S_CURSOR FOR
*      SELECT (S_S_IF-T_FIELDS) FROM SFLIGHT            "MY COMMENT
*                               WHERE CARRID  IN L_R_CARRID AND
*                                     CONNID  IN L_R_CONNID.

      SELECT * FROM ZZC_TEST02
                        WHERE BUKRS         IN L_R_BUKRS
                        AND   UPT_TIMESTAMP IN L_R_TIMES.

    ENDIF.                             "First data package ?

* Fetch records into interface table.
*   named E_T_'Name of extract structure'.
    FETCH NEXT CURSOR S_CURSOR
               APPENDING CORRESPONDING FIELDS
               OF TABLE E_T_DATA
               PACKAGE SIZE S_S_IF-MAXSIZE.

    IF SY-SUBRC <> 0.
      CLOSE CURSOR S_CURSOR.
      RAISE NO_MORE_DATA.
    ENDIF.

    S_COUNTER_DATAPAKID = S_COUNTER_DATAPAKID + 1.

  ENDIF.              "Initialization mode or data extraction ?

ENDFUNCTION.

 

相關文章