SAP RFC函数RFC_READ_TABLE使用与优化

RFC_READ_TABLE

第三方系统可通过RFC调用此函数直接访问(查询)SAP R/3系统的数据表。
合理使用此函数可以大幅度减少第三方系统集成数据接口开发量。

查询表结构

在这里插入图片描述

查询数据

在这里插入图片描述

导入参数

  • QUERY_TABLE 表名称(必填)
  • DELIMITER 分隔符,默认值空格
    在返回数据的DATA表项目中,通过此参数传递的分隔符分隔字段值,传空格则不包含分隔符
  • NO_DATA 不传输数据,默认值为空格
    如果此项不为空格,则函数不返回表数据,只返回字段信息
  • ROWSKIPS 跳行数,默认值0
  • ROWCOUNT 行数,默认值0
    行数为0则返回所有行

表参数

  • OPTIONS 选择条件语句(传入)
  1. TEXT where语句文本
  • FIELDS 字段信息(传入/传出)
  1. FIELDNAME 字段名
  2. OFFSET 偏移量
  3. LENGTH 长度
  4. TYPE 数据类型
  5. FIELDTEXT 字段描述
    作为传入参数时,只需要传递FIELDNAME字段值,用于选择需要返回的字段;
    作为传出参数时,返回字段相关信息
  • DATA 表数据(传出)
  1. 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.

posted on 2020-09-15 15:18  路过君  阅读(896)  评论(0编辑  收藏  举报

导航