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_DATA的参考值,改为我们的数据源表。
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.