SAP RFC函数RFC_READ_TABLE使用与优化
RFC_READ_TABLE
第三方系统可通过RFC调用此函数直接访问(查询)SAP R/3系统的数据表。
合理使用此函数可以大幅度减少第三方系统集成数据接口开发量。
查询表结构
查询数据
导入参数
- QUERY_TABLE 表名称(必填)
- DELIMITER 分隔符,默认值空格
在返回数据的DATA表项目中,通过此参数传递的分隔符分隔字段值,传空格则不包含分隔符 - NO_DATA 不传输数据,默认值为空格
如果此项不为空格,则函数不返回表数据,只返回字段信息 - ROWSKIPS 跳行数,默认值0
- ROWCOUNT 行数,默认值0
行数为0则返回所有行
表参数
- OPTIONS 选择条件语句(传入)
- TEXT where语句文本
- FIELDS 字段信息(传入/传出)
- FIELDNAME 字段名
- OFFSET 偏移量
- LENGTH 长度
- TYPE 数据类型
- FIELDTEXT 字段描述
作为传入参数时,只需要传递FIELDNAME字段值,用于选择需要返回的字段;
作为传出参数时,返回字段相关信息
- DATA 表数据(传出)
- WA 行记录数据
优化
1. 分页数据错乱
此函数可通过ROWSKIPS,ROWCOUNT参数实现分页查询,但实际使用时会发现返回的数据并没有排序,导致分页数据错乱。
解决办法
修改程序使用主键排序查询
# SELECT * FROM (QUERY_TABLE) INTO <WA> WHERE (OPTIONS).
SELECT * FROM (QUERY_TABLE) INTO <WA> WHERE (OPTIONS) ORDER BY PRIMARY KEY.
2. DATA数据长度限制
此函数一次性查询的字段不可过多,总长度超过DATA字段类型长度512时将抛出异常DATA_BUFFER_EXCEEDED
解决办法
将返回结果按512长度拆分到多个data table返回
FUNCTION ZRFC_READ_TABLE .
*"----------------------------------------------------------------------
*"*"本地接口:
*" IMPORTING
*" VALUE(QUERY_TABLE) LIKE DD02L-TABNAME
*" VALUE(DELIMITER) LIKE SONV-FLAG DEFAULT SPACE
*" VALUE(NO_DATA) LIKE SONV-FLAG DEFAULT SPACE
*" VALUE(ROWSKIPS) LIKE SOID-ACCNT DEFAULT 0
*" VALUE(ROWCOUNT) LIKE SOID-ACCNT DEFAULT 0
*" TABLES
*" OPTIONS STRUCTURE RFC_DB_OPT
*" FIELDS STRUCTURE RFC_DB_FLD
*" DATA STRUCTURE TAB512
*" DATA1 STRUCTURE TAB512
*" DATA2 STRUCTURE TAB512
*" DATA3 STRUCTURE TAB512
*" DATA4 STRUCTURE TAB512
*" EXCEPTIONS
*" TABLE_NOT_AVAILABLE
*" TABLE_WITHOUT_DATA
*" OPTION_NOT_VALID
*" FIELD_NOT_VALID
*" NOT_AUTHORIZED
*" DATA_BUFFER_EXCEEDED
*"----------------------------------------------------------------------
"
CALL FUNCTION 'VIEW_AUTHORITY_CHECK'
EXPORTING
VIEW_ACTION = 'S'
VIEW_NAME = QUERY_TABLE
EXCEPTIONS
NO_AUTHORITY = 2
NO_CLIENTINDEPENDENT_AUTHORITY = 2
NO_LINEDEPENDENT_AUTHORITY = 2
OTHERS = 1.
IF SY-SUBRC = 2.
RAISE NOT_AUTHORIZED.
ELSEIF SY-SUBRC = 1.
RAISE TABLE_NOT_AVAILABLE.
ENDIF.
* ----------------------------------------------------------------------
* find out about the structure of QUERY_TABLE
* ----------------------------------------------------------------------
DATA BEGIN OF TABLE_STRUCTURE OCCURS 10.
INCLUDE STRUCTURE DFIES.
DATA END OF TABLE_STRUCTURE.
"DATA TABLE_HEADER LIKE X030L.
DATA TABLE_TYPE TYPE DD02V-TABCLASS.
CALL FUNCTION 'DDIF_FIELDINFO_GET'
EXPORTING
TABNAME = QUERY_TABLE
* FIELDNAME = ' '
* LANGU = SY-LANGU
* LFIELDNAME = ' '
* ALL_TYPES = ' '
* GROUP_NAMES = ' '
IMPORTING
* X030L_WA =
DDOBJTYPE = TABLE_TYPE
* DFIES_WA =
* LINES_DESCR =
TABLES
DFIES_TAB = TABLE_STRUCTURE
* FIXED_VALUES =
EXCEPTIONS
NOT_FOUND = 1
INTERNAL_ERROR = 2
OTHERS = 3
.
IF SY-SUBRC <> 0.
RAISE TABLE_NOT_AVAILABLE.
ENDIF.
IF TABLE_TYPE = 'INTTAB'.
RAISE TABLE_WITHOUT_DATA.
ENDIF.
* ----------------------------------------------------------------------
* isolate first field of DATA as output field
* (i.e. allow for changes to structure DATA!)
* ----------------------------------------------------------------------
DATA LINE_LENGTH TYPE I.
FIELD-SYMBOLS <D>.
ASSIGN COMPONENT 0 OF STRUCTURE DATA TO <D>.
DESCRIBE FIELD <D> LENGTH LINE_LENGTH in character mode.
* PSR D1-D4 --------------------
DATA LINE_LENGTH1 TYPE I.
FIELD-SYMBOLS <D1>.
ASSIGN COMPONENT 0 OF STRUCTURE DATA1 TO <D1>.
DESCRIBE FIELD <D1> LENGTH LINE_LENGTH1 in character mode.
DATA LINE_LENGTH2 TYPE I.
FIELD-SYMBOLS <D2>.
ASSIGN COMPONENT 0 OF STRUCTURE DATA2 TO <D2>.
DESCRIBE FIELD <D2> LENGTH LINE_LENGTH2 in character mode.
DATA LINE_LENGTH3 TYPE I.
FIELD-SYMBOLS <D3>.
ASSIGN COMPONENT 0 OF STRUCTURE DATA3 TO <D3>.
DESCRIBE FIELD <D3> LENGTH LINE_LENGTH3 in character mode.
DATA LINE_LENGTH4 TYPE I.
FIELD-SYMBOLS <D4>.
ASSIGN COMPONENT 0 OF STRUCTURE DATA4 TO <D4>.
DESCRIBE FIELD <D4> LENGTH LINE_LENGTH4 in character mode.
DATA TOTALLENGTH TYPE I.
* PSR D1-D4 --------------------
* ----------------------------------------------------------------------
* if FIELDS are not specified, read all available fields
* ----------------------------------------------------------------------
DATA NUMBER_OF_FIELDS TYPE I.
DESCRIBE TABLE FIELDS LINES NUMBER_OF_FIELDS.
IF NUMBER_OF_FIELDS = 0.
LOOP AT TABLE_STRUCTURE.
MOVE TABLE_STRUCTURE-FIELDNAME TO FIELDS-FIELDNAME.
APPEND FIELDS.
ENDLOOP.
ENDIF.
* ----------------------------------------------------------------------
* for each field which has to be read, copy structure information
* into tables FIELDS_INT (internal use) and FIELDS (output)
* ----------------------------------------------------------------------
DATA: BEGIN OF FIELDS_INT OCCURS 10,
FIELDNAME LIKE TABLE_STRUCTURE-FIELDNAME,
TYPE LIKE TABLE_STRUCTURE-INTTYPE,
DECIMALS LIKE TABLE_STRUCTURE-DECIMALS,
LENGTH_SRC LIKE TABLE_STRUCTURE-INTLEN,
LENGTH_DST LIKE TABLE_STRUCTURE-LENG,
OFFSET_SRC LIKE TABLE_STRUCTURE-OFFSET,
OFFSET_DST LIKE TABLE_STRUCTURE-OFFSET,
END OF FIELDS_INT,
LINE_CURSOR TYPE I.
LINE_CURSOR = 0.
* for each field which has to be read ...
LOOP AT FIELDS.
READ TABLE TABLE_STRUCTURE WITH KEY FIELDNAME = FIELDS-FIELDNAME.
IF SY-SUBRC NE 0.
RAISE FIELD_NOT_VALID.
ENDIF.
* compute the place for field contents in DATA rows:
* if not first field in row, allow space for delimiter
IF LINE_CURSOR <> 0.
IF NO_DATA EQ SPACE AND DELIMITER NE SPACE.
MOVE DELIMITER TO DATA+LINE_CURSOR.
ENDIF.
LINE_CURSOR = LINE_CURSOR + STRLEN( DELIMITER ).
ENDIF.
* ... copy structure information into tables FIELDS_INT
* (which is used internally during SELECT) ...
FIELDS_INT-FIELDNAME = TABLE_STRUCTURE-FIELDNAME.
FIELDS_INT-LENGTH_SRC = TABLE_STRUCTURE-INTLEN.
FIELDS_INT-LENGTH_DST = TABLE_STRUCTURE-LENG.
FIELDS_INT-OFFSET_SRC = TABLE_STRUCTURE-OFFSET.
FIELDS_INT-OFFSET_DST = LINE_CURSOR.
FIELDS_INT-TYPE = TABLE_STRUCTURE-INTTYPE.
FIELDS_INT-DECIMALS = TABLE_STRUCTURE-DECIMALS.
* compute the place for contents of next field in DATA rows
LINE_CURSOR = LINE_CURSOR + TABLE_STRUCTURE-LENG.
* PSR D1-D4 --------------------
IF LINE_CURSOR > LINE_LENGTH + LINE_LENGTH1 + LINE_LENGTH2 + LINE_LENGTH3 + LINE_LENGTH4 AND NO_DATA EQ SPACE.
* PSR D1-D4 --------------------
RAISE DATA_BUFFER_EXCEEDED.
ENDIF.
TOTALLENGTH = LINE_CURSOR.
APPEND FIELDS_INT.
* ... and into table FIELDS (which is output to the caller)
FIELDS-FIELDTEXT = TABLE_STRUCTURE-FIELDTEXT.
FIELDS-TYPE = TABLE_STRUCTURE-INTTYPE.
FIELDS-LENGTH = FIELDS_INT-LENGTH_DST.
FIELDS-OFFSET = FIELDS_INT-OFFSET_DST.
MODIFY FIELDS.
ENDLOOP.
* end of loop at FIELDS
* ----------------------------------------------------------------------
* read data from the database and copy relevant portions into DATA
* ----------------------------------------------------------------------
* output data only if NO_DATA equals space (otherwise the structure
* information in FIELDS is the only result of the module)
IF NO_DATA EQ SPACE.
DATA: BEGIN OF WORK, BUFFER(30000), END OF WORK.
* PSR-----------
DATA: DATABUFFER TYPE C LENGTH 30000.
* PSR-----------
FIELD-SYMBOLS: <WA> TYPE ANY, <COMP> TYPE ANY.
ASSIGN WORK TO <WA> CASTING TYPE (QUERY_TABLE).
IF ROWCOUNT > 0.
ROWCOUNT = ROWCOUNT + ROWSKIPS.
ENDIF.
* #CP-SUPPRESS: FP <This FM obolete.note 382318.Hence no need of change>
SELECT * FROM (QUERY_TABLE) INTO <WA> WHERE (OPTIONS) ORDER BY PRIMARY KEY.
IF SY-DBCNT GT ROWSKIPS.
DATABUFFER = ''.
* copy all relevant fields into DATA (output) table
LOOP AT FIELDS_INT.
IF FIELDS_INT-TYPE = 'P'.
ASSIGN COMPONENT FIELDS_INT-FIELDNAME
OF STRUCTURE <WA> TO <COMP>
TYPE FIELDS_INT-TYPE
DECIMALS FIELDS_INT-DECIMALS.
ELSE.
ASSIGN COMPONENT FIELDS_INT-FIELDNAME
OF STRUCTURE <WA> TO <COMP>
TYPE FIELDS_INT-TYPE.
ENDIF.
MOVE <COMP> TO
DATABUFFER+FIELDS_INT-OFFSET_DST(FIELDS_INT-LENGTH_DST).
ENDLOOP.
* end of loop at FIELDS_INT
DATA = DATABUFFER+0(512).
APPEND DATA.
IF TOTALLENGTH > 512 .
DATA1 = DATABUFFER+512(512).
APPEND DATA1.
ENDIF.
IF TOTALLENGTH > 1024.
DATA2 = DATABUFFER+1024(512).
APPEND DATA2.
ENDIF.
IF TOTALLENGTH > 1536.
DATA3 = DATABUFFER+1536(512).
APPEND DATA3.
ENDIF.
IF TOTALLENGTH > 2048.
DATA4 = DATABUFFER+2048(512).
APPEND DATA4.
ENDIF.
IF ROWCOUNT > 0 AND SY-DBCNT GE ROWCOUNT. EXIT. ENDIF.
ENDIF.
ENDSELECT.
ENDIF.
ENDFUNCTION.