一、内表定义

*---------------------------带表头-----------------------------
DATA: BEGIN OF itab OCCURS 0,
        matnr LIKE mara-matnr,
        werks LIKE marc-werks,
      END OF itab .

DATA: otab LIKE TABLE OF itab WITH HEADER LINE.

DATA: BEGIN OF itab OCCURS 0.
        INCLUDE STRUCTURE ztmm001.         "表内包含其他结构或表
DATA: str(10) TYPE c.
DATA: END OF itab.

*---------------------------无表头-----------------------------
DATA: BEGIN OF itab OCCURS 0,
        matnr LIKE mara-matnr,
        werks LIKE marc-werks,
      END OF itab .

TYPES: BEGIN OF gs_alv.                   "结构
        INCLUDE STRUCTURE ztmm001.    
TYPES: zterm TYPE dzterm,        
       sel   TYPE c.
TYPES: END OF gs_alv.

二、内表&数据库表常用语句

*---------------------------Insert----------------------------
***插入数据到数据库表
INSERT db_table FROM TABLE itab ACCEPTING DUPLICATE KEYS.
INSERT db_table FROM TABLE itab.
INSERT dbtab FROM wa.
INSERT into dbtab values wa.
COMMIT WORK.

***插入数据到内表
INSERT wa INTO TABLE itab.
INSERT wa INTO itab INDEX n.
INSERT LINES OF itab1 INTO TABLE itab2 INDEX 1.
INSERT sy-index INTO TABLE itab.

*---------------------------Append-----------------------------
APPEND LINES OF itab_temp TO itab.                 "多行
APPEND LINES OF itab_temp FROM 2 TO 3  TO itab.    "多行-指定行
APPEND itab_temp TO itab.                          "单行

*---------------------------Delete-----------------------------
***删除数据库表数据
DELETE FROM ztco33_sr WHERE gjahr = p_gjahr       "按条件删除
                        AND monat IN s_monat.

DELETE ztco33_sr FROM wa.
DELETE ztco33_sr FROM TABLE itab[].                 "按主键删除
COMMIT WORK AND WAIT.

***删除内表数据
LOOP AT gt_item INTO gs_item .
  DELETE gtitem[] .                      "删除内表当前行
ENDLOOP .

DELETE TABLE itab FROM wa.               "按主键删除
DELETE gt_item INDEX 20 .                "不建议在loop循环中使用,会影响内表的行索引
DELETE itab WHERE matnr NOT IN s_matnr.

SORT itab BY werks matnr.
DELETE ADJACENT DUPLICATES FROM itab COMPARING werks matnr.     "删除重复行,保留第一条数据

*---------------------------Modify-----------------------------
***修改数据库
MODIFY dbtab FROM wa.
MODIFY dbtab FROM TABLE itab[].        "按主键决定是更新还是插入
COMMIT WORK.

***修改内表-Loop外
MODIFY TABLE itab FROM wa.  "工作区修改内表必须有主键,按主键修改

***修改内表-Loop内
MODIFY itab.
MODIFY itab FROM wa.          
MODIFY itab FROM wa INDEX 1.     "修改行
MODIFY itab FROM wa TRANSPORTING  f1 f2 f3  WHERE f  = '1235' . "按工作区某个字段值更新内表

WA_MATNR-LGORT = 'SP02'.
APPEND WA_MATNR TO EX_TAB.

CLEAR WA_MATNR.
WA_MATNR-MATNR = IM_MATNR.
MODIFY EX_TAB FROM WA_MATNR TRANSPORTING MATNR WHERE MATNR IS INITIAL.    


**用指针修改
LOOP AT gt_alv ASSIGNING FIELD-SYMBOL(<fs_alv>) WHERE SELXXX eq 'X' .
    <fs_alv>-LES_DEL = 'X'.     "内表更新
    UPDATE ZTSD0010 SET LES_DEL = 'X' WHERE ID = <fs_alv>-ID.  "透明表更新
ENDLOOP.
COMMIT WORK AND WAIT.

*---------------------------Update-----------------------------
UPDATE dbtab FROM wa.
UPDATE dbtab FROM TABLE itab[].
UPDATE db_table
   SET matnr = t_flag
       chgby = sy-uname
 WHERE werks = c_value1.
COMMIT WORK.

*---------------------------Read-----------------------------
READ TABLE itab INTO gs_itab WITH KEY matnr = '1001' werks = '1000'.
READ TABLE itab INDEX 1.

**二分法(使用前一定要先排序,二分法查找会反复将查找区间对半划分)
SORT itab BY matnr werks.
READ TABLE itab INTO DATA(gs_itab) WITH KEY matnr = '1001' werks = '1000' BINARY SEARCH.   

*---------------------------Collect-----------------------------
SORT itab_temp BY matnr.
LOOP AT itab_temp.
  COLLECT itab_temp INTO itab_col.
ENDLOOP.

三、数据库表常用查询语句

-------------------------------------获取一笔数据-----------------------------------------
SELECT SINGLE * FROM t001w WHERE werks = itab-werks.

SELECT SINGLE verpr peinh INTO (itab-verpr,itab-peinh)
     FROM mbew
      WHERE matnr = itab-matnr
        AND bwkey = itab-werks
        AND ( lfgja < g_lfgja OR ( lfgja = g_lfgja AND lfmon <= g_lfmon ) ) .

SELECT SINGLE *
  INTO CORRESPONDING FIELDS OF TABLE itab
  FROM ztmm_config.

SELECT
   EKPO~NETPR   "按数量单位的价格
   EKPO~PEINH   "数量单位
   EKKO~WAERS
   EKKO~AEDAT
   EKPO~EBELN
   EKPO~EBELP
  INTO (Z_NETPR,Z_PEINH,Z_WAERS,Z_AEDAT,Z_EBELN,Z_EBELP)
  FROM EKPO INNER JOIN EKKO ON EKKO~EBELN = EKPO~EBELN
  UP TO 1 ROWS
  WHERE EKKO~BUKRS = ZBUKRS
    AND EKKO~EKORG = I_TAB1-EKORG
    AND EKKO~LIFNR = I_TAB1-LIFNR
    AND EKPO~MATNR = I_TAB1-MATNR
    AND EKKO~AEDAT >= Z_DATE         "当年1月1号
    AND EKPO~LOEKZ <> 'X'     "删除
    AND EKPO~RETPO <> 'X'     "退货
  ORDER BY EKKO~AEDAT ASCENDING.          "获取创建日期最小的一笔
ENDSELECT.

---------------------------------------获取多笔数据---------------------------------------
IF ITAB_TEMP2[] IS NOT INITIAL.
  SELECT MBLNR MJAHR ZEILE EBELN EBELP MATNR MENGE BWART  
        FROM MSEG
        INTO CORRESPONDING FIELDS OF TABLE ITAB_MSEG
        FOR ALL ENTRIES IN ITAB_TEMP2                   "for all entries in ...
        WHERE EBELN = ITAB_TEMP2-EBELN
          AND EBELP = ITAB_TEMP2-EBELP.
ENDIF.

SELECT werks matnr
    INTO CORRESPONDING FIELDS OF TABLE itab
    FROM marc
    WHERE werks = '1000'.

SELECT werks matnr
    INTO CORRESPONDING FIELDS OF itab
    FROM marc
    WHERE werks = '1000'.
  APPEND itab.
  CLEAR itab.
ENDSELECT.

  SELECT * INTO TABLE it_pl FROM dd07t
    WHERE domname = 'ZZBDPL'
    AND ddlanguage = 1
    AND domvalue_l NOT IN ('C00','C99','C12','C13','C14','C88')
    AND domvalue_l NOT LIKE 'CZ%'.

  SELECT * INTO TABLE lt_data FROM zthr_swmx   "屏幕输入月份 - 1
    WHERE zoaid IN s_zoaid
      AND gjahr = lv_gjahr
      AND monat = lv_monat
      AND bukrs IN s_bukrs
      AND zbm   IN s_zbm
      AND ( zrzxz LIKE 'YT%' or zrzxz LIKE 'YL%' )
      AND zdflag <> 'D'.

----------------------------------多表连接-----------------------------------------------
SELECT b~matnr a~lifnr b~ebelp b~ebeln
    INTO (itab-matnr,itab-lifnr,itab-ebelp,itab-ebeln)
    FROM ekko AS a INNER JOIN ekpo AS b ON a~ebeln = b~ebeln
    WHERE b~werks IN s_werks
      AND b~matnr IN s_matnr
      AND a~lifnr IN s_lifnr.

------------------------------------数量汇总---------------------------------------------
SELECT SUM( menge ) SUM( wemng )
    INTO (l_menge,l_wemng)
    FROM eket
    WHERE ebeln = itab-ebeln
      AND ebelp = itab-ebelp.

------------------------------------取最大值--------------------------------------------
SELECT MAX( budat ) INTO p_budat       "取最后一笔入库的时间
  FROM mseg INNER JOIN mkpf ON mkpf~mblnr = mseg~mblnr
                           AND mkpf~mjahr = mseg~mjahr
  WHERE mseg~matnr = itab-matnr
    AND mseg~werks = p_werks
    AND mseg~lifnr <> ''
    AND mseg~bwart IN ('103','105').

--------------------------------------Range---------------------------------------------
RANGES: p_auart FOR aufk-auart.
SELECT value INTO p_auart-low
    FROM ztmm_config
    WHERE werks IN i_werks
      AND catgy = 'ZMMR013_01'.
  p_auart-sign = 'I'.
  p_auart-option = 'EQ'.
  APPEND p_auart.
  CLEAR p_auart.
ENDSELECT.

四、字符串处理

CONCATENATE year1 month1 day1 INTO p_date1 SEPARATED BY '/'.    "拼接

SEARCH p_string FOR x.           "查找字符

CONDENSE p_string NO-GAPS.        "去空格

REPLACE 'ST' WITH 'PC' INTO p_string.  "用PC替换ST

SPLIT c1 AT c2 INTO c3 c4 c5 c6.       "分割字符串

SPLIT p_name AT '/' INTO name1 name2.   "分割字符串到字段

SPLIT lv_string AT ',' INTO TABLE lt_table.   "分割字符串到内表

CONCATENATE LINES OF itab INTO result SEPARATED BY ','.   "将内表用符号分割到字段(内表只有一个字段)

p_len = STRLEN( p_name ).               "获取字符串长度

SHIFT p_name BY 35 PLACES LEFT.         "去掉字符串的前n个位置的字符(LEFT:从左边截断;RIGHT:从右边截断)

SHIFT p_name UP TO 'S' LEFT.            "去掉字符串中在字母S左边之前的字符

SHIFT P_LINE LEFT DELETING LEADING '0'.    "去除左侧前导零

SHIFT P_LINE RIGHT DELETING TRAILING '0'.  "去除右侧后缀零

TRANSLATE p_name TO UPPER CASE.         "转换成大写

TRANSLATE p_name TO LOWER CASE.         "转换成小写

五、指针常见用法

-----------------------------------语法-------------------------------------------
*分配某个变量给指针
   ASSIGN var TO <fs>.
   
*分配结构中的某个字段的地址给指针 
  ASSIGN COMPONENT pos OF STRUCTURE struc TO <fs>.
   
*分配整个内表行给指针(指针必须定义为有栏位结构的类型)   
  READ TABLE itab INDEX/WITH KEY .. ASSIGNING <fs>.
   
  LOOP AT itab
    ASSIGNING  <fs>.
   ENDLOOP.
   
*分配类的方法或接口给指针
  ASSIGN dref->* TO <fs>.

--------------------------------用指针修改内表字段的值--------------------------------
FIELD-SYMBOLS <FA1> TYPE ANY.    "定义指针
DATA: Z_FIELD1 TYPE STRING.

LOOP AT GT_OUT.
  READ TABLE LT_OUT INTO LS_OUT WITH KEY ZTYPE = GT_OUT-ZTYPE ZXH = GT_OUT-ZXH.
  IF SY-SUBRC = 0.
    CONCATENATE 'LS_OUT-ZJE' Z_MON INTO Z_FIELD1.

    ASSIGN (Z_FIELD1) TO <FA1>.
    IF SY-SUBRC = 0.
      <FA1> = GT_OUT-ZJE.    "金额
    ENDIF.

    MODIFY LT_OUT FROM LS_OUT INDEX GT_OUT-ZXH.
  ENDIF.
ENDLOOP.

-------------------------------用指针修改屏幕字段的值---------------------------------
FIELD-SYMBOLS: <FS> TYPE ANY.      "定义指针
DATA: LV_FIELD TYPE STRING.
DATA: Z_ISM04 TYPE I VALUE 10.

LV_FIELD = '(SAPLXCOF)AFRUD_IMP-ISM04'.    "字段名称
ASSIGN (LV_FIELD) TO <FS>.     
IF <FS> IS ASSIGNED.
  <FS> = Z_ISM04.                "给指针赋值,修改屏幕字段值
ENDIF.

**&---------------------------------------------------------------------*
* * * 指针定义
**&---------------------------------------------------------------------*
FIELD-SYMBOLS: <FS_TABLE> TYPE STANDARD TABLE,
               <FS_AREA>  TYPE ANY,
               <FS_FIELD> TYPE ANY.

FIELD-SYMBOLS: <FS_TABLE_ALV> TYPE STANDARD TABLE,
               <FS_AREA_ALV>  TYPE ANY,
               <FS_FIELD_ALV> TYPE ANY.

IT_WAGE[] = <FS_TABLE>.

LOOP AT <FS_TABLE> INTO <FS_AREA>.
  ASSIGN COMPONENT 'ZOAID' OF STRUCTURE <FS_AREA> TO <FS_FIELD>.
  IF <FS_FIELD>+0(1) = '0'.
    SHIFT <FS_FIELD> BY 1 PLACES LEFT.    "去除左边第一位0
  ENDIF.

  MOVE-CORRESPONDING <FS_AREA> TO IT_YFGS.
  IF IT_YFGS-ZRZXZ+0(2) = 'YT'.
    MOVE-CORRESPONDING IT_YFGS TO IT_05.
    APPEND IT_05.
  ENDIF.
  MODIFY <FS_TABLE> FROM <FS_AREA>.
  CLEAR: IT_YFGS,IT_05.
ENDLOOP.
MODIFY (P_TAB) FROM TABLE <FS_TABLE>.

六、使用指针FIELD-SYMBOLS)定义动态内表

1. 基本动态内表定义

DATA: lv_tabname TYPE tabname VALUE 'MARA'.

FIELD-SYMBOLS: <fs_table> TYPE STANDARD TABLE. "定义表指针

"创建动态内表
CREATE DATA lr_data TYPE TABLE OF (lv_tabname).
ASSIGN lr_data->* TO <fs_table>. "将指针指向动态内表

2. 完全动态内表(结构和字段都动态)

DATA: lt_fields TYPE TABLE OF dfies,
      lr_struct TYPE REF TO data,
      lr_table  TYPE REF TO data.

"获取表结构(例如从数据字典)
CALL FUNCTION 'DDIF_FIELDINFO_GET'
  EXPORTING
    tabname   = 'MARA'
  TABLES
    dfies_tab = lt_fields.

"创建动态结构
CALL METHOD cl_alv_table_create=>create_dynamic_table
  EXPORTING
    it_fieldcatalog = lt_fields
  IMPORTING
    ep_table        = lr_table.

"分配给字段符号
FIELD-SYMBOLS: <fs_dyn_table> TYPE ANY TABLE.
ASSIGN lr_table->* TO <fs_dyn_table>.

3. 基于类型描述的动态内表

DATA: lr_type TYPE REF TO cl_abap_structdescr,
      lr_table TYPE REF TO data.

"获取类型描述
lr_type ?= cl_abap_structdescr=>describe_by_name( 'MARA' ).

"创建动态表类型
DATA(lr_table_type) = cl_abap_tabledescr=>create( lr_type ).

"创建动态内表
CREATE DATA lr_table TYPE HANDLE lr_table_type.

"分配给字段符号
FIELD-SYMBOLS: <fs_dyn_tab> TYPE ANY TABLE.
ASSIGN lr_table->* TO <fs_dyn_tab>.

4. 动态内表操作示例

"填充动态内表
SELECT * FROM (lv_tabname) INTO TABLE <fs_table> UP TO 10 ROWS.

"读取动态内表数据
FIELD-SYMBOLS: <fs_line> TYPE any.
LOOP AT <fs_table> ASSIGNING <fs_line>.
  "访问动态字段
  ASSIGN COMPONENT 'MATNR' OF STRUCTURE <fs_line> TO FIELD-SYMBOL(<fs_field>).
  IF sy-subrc = 0.
    WRITE: / <fs_field>.
  ENDIF.
ENDLOOP.

5. 动态内表与ALV结合使用

DATA: lo_alv TYPE REF TO cl_salv_table.

"创建ALV显示动态内表
TRY.
    cl_salv_table=>factory(
      IMPORTING
        r_salv_table = lo_alv
      CHANGING
        t_table      = <fs_dyn_table> ).
  CATCH cx_salv_msg.
ENDTRY.

"显示ALV
lo_alv->display( ).

6. 动态内表字段操作

"动态访问内表字段
ASSIGN COMPONENT 'FIELDNAME' OF STRUCTURE <fs_line> TO FIELD-SYMBOL(<fs_value>).

"动态修改字段值
IF sy-subrc = 0.
  <fs_value> = 'New Value'.
ENDIF.

7. 高级用法:动态内表与RTTS

DATA: lo_struct TYPE REF TO cl_abap_structdescr,
      lo_table  TYPE REF TO cl_abap_tabledescr,
      lr_data   TYPE REF TO data.

"创建动态结构
lo_struct ?= cl_abap_structdescr=>describe_by_name( 'BSEG' ).

"创建动态表类型
lo_table = cl_abap_tabledescr=>create( p_line_type = lo_struct ).

"创建动态内表
CREATE DATA lr_data TYPE HANDLE lo_table.
FIELD-SYMBOLS: <fs_dyn_tab> TYPE ANY TABLE.
ASSIGN lr_data->* TO <fs_dyn_tab>.

持续更新~~

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐