[SAP ABAP开发技术总结]ABAP程序之间数据共享与传递

 

19.         数据共享与传递

image382

19.1.     程序调用、会话、SAP/ABAP内存 关系

image383

“被调用程序插入型”是指:主调用程序(calling program)并不结束,当遇到Link 语句时,会去执行被调用程序(called program),当被调用程序结束后,调用程序回到调用处继续执行;

“调用程序中止型”是指:调用程序(calling program)当遇到Link 语句时会立即中止,然后去执行被调用程序(called program),即使被调用程序执行完毕后,也不会返回到主调程序的调用处继续执行;

SUBMIT<program> AND RETURN中断不终止)当前运行的程序,启动新的被调用程序<program>,当<program>运行完后,控制权又返回到被中断的调用程序,继续执行

CALL TRANSACTION <TCode>:可以插入一个具有事务代码的ABAP程序,中断当前运行的程序,待被调程序执行完后,再继续执行主调程序

SUBMIT <program>结束当前运行的程序,启动新的被调用程序<program>

LEAVE TO TRANSACTION <TCode>结束当前运行的程序,并启动由事务码<TCode>指定的ABAP程序。在程序中使用该语句的效果等同于用户直接在命令行输入“/n<TCode>”并执行的效果。

 

使用LEAVE TO TRANSACTION <TCode>调用另一程序时,可以在主调程序中使用SET PARAMETER ID将被传递的数据存储到SAP memory中,在被调用的Tcode中可以使用GET PARAMETER ID来获取,另外,也可以为被调用Tcode屏幕参数的data element设置parameter ID这样会自动的获取与存储该屏幕参数(只设置Data Element中的Parameter ID是不起作用的,请看后面)

 

只有LEAVE TO TRANSACTION <TCode> 不能使用ABAP MEMORY共享数据(其它调用方式均可以),而应该使用SAP Memory;注,SUBMIT <program>调用后虽然不会返回到主调程序,但也是可以通过ABAP memory来传递数据

异步的Link Program:当遇到这种Function时,将会重新打开一个external session(外部会话,窗口会话),它并行地、独立于当前的external session.

三种会话:image384

一个External session(外部会话,一个窗口就是一个外部会话)对应着一个ABAP MEMORY内存,所以同一个Window中的所有Internal session(内部会话,一个程序的调用就是一个内部会话)共用着同一个ABAP MEMORY,同一user logon session(用户终端会话,登录就会产生)中不同的window共用一个SAP MEMORY内存:

image385

同一窗口中的不同程序共享同一个ABAP memory,同一用户的不同窗口之间共享同一个SAP memory

当系统用户登录后,就会产生一个与该用户对应的“用户终端会话”(User Terminal Session),用户可以开辟很多外部会话(即窗口,最多可打开6个窗口),在每个窗口会话(外部会话)中又可以先后执行多个ABAP程序(调用一个程序就会产生一个内部会话)

每一个外部会话都有一个叫ABAP Memory的内存区域,在该会话内部可以通过“EXPORT TO MEMORY”和IMPORT FROM MEMORY在该会话中的多个运行程序之间(即多个内部会话之间)进行数据共享,并可使用“FREE MEMORY ID”语句将共享数据从ABAP Memory中清除

SAP Memory是所有的会话(指同一用户登录会话中)都可以访问的内存区域,因此可以通过“SET PARAMETER”与“GET PARAMETER”把数据保存在SAP内存中进行数据共享

所以,在同一个external sessionLink program我们使用ABAP Memory进行传递数据;而在不同的external session间的Link program我们使用SAP Memory进行数据传递。

19.2.     ABAP Memory数据共享

19.2.1.           EXPORT

EXPORT {p1 = dobj1 p2 = dobj2 ...} | {p1 FROM dobj1 p2 FROM dobj2 ...} | (ptab) TO 
  | { MEMORY ID id 
}
  | {
DATABASE      dbtab(ar) [FROM wa] [CLIENT cl] ID id }
  | {
SHARED MEMORY dbtab(ar) [FROM wa] [CLIENT cl] ID id 
}
  | {
SHARED BUFFER dbtab(ar) [FROM wa] [CLIENT cl] ID id 
}

1.        {p1 = dobj1 p2 = dobj2 ...} {p1 FROM dobj1 p2 FROM dobj2 ...}的意义一样,只是写法不一样,dobj1dobj2…变量将会以p1p2…名称存储到内存或数据库中。p1p2…名称随便取,如果p1p2…与将要存储的变量名相同时,只需写变量名即可,即等号与 FROM 后面可以省略。p1p2…这些名称必须与IMPORT语句中相一致,否则读取不出

2.        (ptab):为动态指定需要存储的变量,ptab内表结构要求是这样的:只需要两列,列名任意,但类型需要是字符型;第一列存储如上面的p1p2…名称,第二列为上面的dobj1dobj2…变量,如果变量与名称相同,则也可以像上面一样,省略第二列的值。两列的值都必需要大写,实例如下:

TYPES:BEGIN OF tab_type,
    para
TYPE string,"列的名称任意,类型为字符型
    dobj
TYPE string,
 
END OF tab_type.
DATA:text1 TYPE string VALUE `TXT1`,
  text2
TYPE string VALUE `TXT2`,
 
line  TYPE tab_type,
  itab 
TYPE STANDARD TABLE OF tab_type.
line-para = 'P1'."值都需要大写
line-dobj = 'TEXT1'."值都需要大写
APPEND line TO itab.
line-para = 'P2'.
line-dobj = 'TEXT2'.
APPEND line TO itab.
EXPORT (itab) TO MEMORY ID 'TEXTS'.
IMPORT p1 = text2 p2 = text1 FROM MEMORY ID 'TEXTS'.
WRITE: / text1,text2."TXT2 TXT1
CLEAR: text1,text2.
IMPORT (itab) FROM MEMORY ID 'TEXTS'.
WRITE: / text1,text2."TXT1 TXT2

3.        MEMORY ID:将变量存储到ABAP MEMORY内存(同一用户的同一窗口Session

4.        DATABASE:将变量存储到数据库中;dbtab为簇数据库表的名称(如系统提供的标准表INDX);ar的值为区域ID,它将数据库表的行分成若干区域,它必须被直接指定,且值是两位字符,被存储到簇数据库表中的RELID字段中;id 的值会存储到簇数据表中的RELID字段的下一用户自定义字段中:

TYPES:BEGIN OF tab_type,
    col1
TYPE i,
    col2
TYPE i,
 
END OF tab_type.
DATA:wa_indx TYPE demo_indx_table,
  wa_itab
TYPE tab_type,
  itab 
TYPE STANDARD TABLE OF tab_type.
WHILE sy-index < 100.
  wa_itab
-col1 = sy-index.
  wa_itab
-col2 = sy-index ** 2.
 
APPEND wa_itab TO itab.
ENDWHILE.
wa_indx
-timestamp = sy-datum && sy-uzeit.
wa_indx
-userid    = sy-uname
.
EXPORT tab = itab TO DATABASE demo_indx_table(sq) FROM wa_indx ID 'TABLE'.

数据导入请参考后面IMPORT中的实例

image386

image387

TABLES: indx.
DATA: BEGIN OF i_tab OCCURS 100,
  col1
TYPE i,
  col2
TYPE i,
END OF i_tab.
DO 3000 TIMES.
  i_tab
-col1 = sy-index.
  i_tab
-col2 = sy-index ** 2.
 
APPEND i_tab.
ENDDO.
indx
-aedat = sy-datum.
indx
-usera = sy-uname.
indx
-pgmid = sy-repid.
"省略了FROM选项,因为已经使用TABLES indx语句定义了名为indx的结构变量了
"Export时会自动将表工作区indx变量中的用户字段存储到簇数据库表中
EXPORT i_tab TO DATABASE indx(HK) ID 'Key'.

WRITE: ' SRTF2',AT 20 'AEDAT',AT 35 'USERA',AT 50 'PGMID'.
ULINE.
"注:下面完全可以使用 IMPORT FROM DATABASE TO wa 语句来读取用户区字段
SELECT * FROM indx WHERE relid = 'HK'AND srtfd = 'Key'.
 
WRITE: / indx-srtf2 UNDER 'SRTF2',
  indx
-aedat UNDER 'AEDAT',
  indx
-usera UNDER 'USERA',
  indx
-pgmid UNDER 'PGMID'.
ENDSELECT.

数据导入请参考后面IMPORT中的实例

SRTF2             AEDAT          USERA          PGMID

        0          2011.10.12     ZHENGJUN       YJZJ_TEST2

        1          2011.10.12     ZHENGJUN       YJZJ_TEST2

        2          2011.10.12     ZHENGJUN       YJZJ_TEST2

        3          2011.10.12     ZHENGJUN       YJZJ_TEST2

        4          2011.10.12     ZHENGJUN       YJZJ_TEST2

5.        SHARED MEMORY/BUFFER :将数据存储到SAP应用服务器上的内存中,可共同一服务上的所有程序访问两种的作用是一样的,最大不同是在数据达到最大内存限制时的处理方式不同:最大内存限制值分别是通过rsdb/esm/buffersize_kb (SHARED MEMORY)rsdb/obj/buffersize (SHARED BUFFER)来设置的,当内存占用快满时,SHARED MEMORY必须通过DELETE FROM SHARED MEMORY来手动清理,而SHARED BUFFER会自动删除很少被使用到的数据(当然也可以通过DELETE FROM SHARED BUFFER手动及时的删除不用的数据)

6.        FROM wawa工作区类型可以参照簇数据库dbtab类型,也可定义成只含有用户数据字段的结构,它是用来设置簇数据库表中SRTF2 CLUSTR两个字段之间的用户数据字段参见簇数据表图中的编号为5的用户数据的值,然后在Export时将相应的字段存储到SRTF2字段与CLUSTR字段间的相应字段中去。如果使用“TABLES dbtab.”定义语句,可以省略“[FROM wa]”,也会默认将其存储到数据库表中,但如果没有“TABLES dbtab.”这样的定义语句,也没有“[FROM wa]”选项时,将不会有数据存储到簇数据库表中的用户字段中去

7.        CLIENT cl:默认为当前客户端,存储到簇数据库表中的MANDT字段中

19.2.2.           IMPORT

IMPORT {p1 = dobj1 p2 = dobj2 ...} | {p1 TO dobj1 p2 TO dobj2 ...} | (ptab) FROM 
  | { MEMORY ID id 
}
  | {
DATABASE      dbtab(ar) [TO wa] [CLIENT cl] ID id }
  | {
SHARED MEMORY dbtab(ar) [TO wa] [CLIENT cl] ID id 
}
  | {
SHARED BUFFER dbtab(ar) [TO wa] [CLIENT cl] ID id 
}

从簇数据表中读取数据,各项参数与EXPORT是一样的,请参考EXPORT各项解释

TYPES:BEGIN OF tab,
    col1
TYPE i,
    col2
TYPE i,
 
END OF tab.
DATA:wa_indx TYPE demo_indx_table,
  wa_itab
TYPE tab,
  itab   
TYPE STANDARD TABLE OF tab
.
IMPORT tab = itab FROM DATABASE demo_indx_table(sq) TO wa_indx ID 'TABLE'.
WRITE: wa_indx-timestamp, wa_indx-userid.
ULINE.
LOOP AT itab INTO wa_itab.
 
WRITE: / wa_itab-col1, wa_itab-col2.
ENDLOOP.

 

 

TABLES indx.
DATA: BEGIN OF jtab OCCURS 100,
  col1
TYPE i,
  col2
TYPE i,
END OF jtab.
"注意:i_tab的名称不能是其他的,必须与EXPORT语句中的分类存储标签名一样。如果i_tab本身又是一个jtab类型的内表,则TO后面的jtab可以省略
IMPORT i_tab TO jtab FROM DATABASE indx(hk) ID 'Key'.
"注:在该程序中并没有明显的为indx工作区设置值,但由于使用了TABLES indx.语句定义了与indx簇数据库表同名的结构变量,所以上面IMPORT会默认加上使用TO indx 选项
WRITE
: / 'AEDAT:', indx-aedat,
      /
'USERA:', indx-usera,
      /
'PGMID:', indx-pgmid.
SKIP.
WRITE 'JTAB:'.
LOOP AT jtab FROM 1 TO 5.
 
WRITE: / jtab-col1, jtab-col2.
ENDLOOP.

AEDAT: 2011.10.12

USERA: ZHENGJUN

PGMID: YJZJ_TEST2

 

JTAB:

         1           1

         2           4

         3           9

         4          16

         5          25

19.2.3.           DELETE

DELETE FROM { {MEMORY ID id}
            | {
DATABASE      dbtab(ar) [CLIENT cl] ID
id}
           
| {
SHARED MEMORY dbtab(ar) [CLIENT cl] ID id}
            | {
SHARED BUFFER dbtab(ar) [CLIENT cl] ID id} }
. 

用来清理EXPORT语句的存储的数据。如果是针对MEMORY ID,则还可以使用 FREE MEMORY IDid DELETE FROM MEMORY ID id 作用一样

DATA: id    TYPE c LENGTH 4 VALUE 'TEXT',
      text1
TYPE string     VALUE 'Tina',
      text2
TYPE string     VALUE 'Mike'.
EXPORT p1 = text1 p2 = text2 TO SHARED BUFFER demo_indx_table(xy) ID id.
IMPORT p1 = text2 p2 = text1 FROM SHARED BUFFER demo_indx_table(xy) ID id.
DELETE FROM SHARED BUFFER demo_indx_table(xy) ID id.
"此语句会执行后,sy-subrc返回4
IMPORT p1 = text2 p2 = text1 FROM SHARED BUFFER demo_indx_table(xy) ID id.

19.3.     SAP MEMORY数据共享

19.3.1.           PARAMETERS/SELECT-OPTIONS选项MEMORY ID

Data Element中的Parameter ID的作用只是在屏幕设计时,起到一个辅助填充的作用,例如:当给某个屏幕字段命令时,如果这个字段的名称为“表名(或结构)- 字段名形式时,回车时系统会提示:

image388 image389

当点击Yes后,该字段的Parameter ID属性会自动的设置为 MARA-MATNR字段所对应Data Element所设置的Parameter ID MAT,另外,From dict.也会自动被钩上,但时,SET ParameterGET Parameter 没有自动钩上,如果需要通过SAP Memory传递值,则还需要将这两个手动钩上(如上图)

 

Data Element中的Parameter ID对选择屏幕是没有任何作用的,如下面的语句不能用来在SAP Memory中传递值:

PARAMETERS: m TYPE mara-matnr.

除非使用MEMORY ID 选项才起作用:

PARAMETERS: m TYPE mara-matnr MEMORY ID mat.

所以选择屏幕中的参数选项 MEMORY ID的作用就等同于对话屏幕中的SET/GET Parameter,它们是作用是相同的,只不过一个用于选择屏幕中,一个用于屏幕计中。

REPORT ztest_sap_memory_1.
*PARAMETERS: p_spa TYPE zdele_1 MEMORY ID zpara1.或者是下面这种写法,根本不用参照zdele_1这个Data Element,因为Data Element中的Parameter ID对选择屏幕参数没有任何意义,所以只需要通过MEMORY ID选项动态的创建Parameter ID即可,不需要先选通过SE80SM30来事先创建好
PARAMETERS: p_spa(10
) MEMORY ID zpara1.
START-OF-SELECTION.
 
LEAVE TO TRANSACTION 'zsap_mem_2
'.

zsap_mem_2事务码对应的报表程序为:

DATA: mem(10).
GET PARAMETER ID 'ZPARA1' FIELD mem.

19.3.2.           GET/SET PARAMETER ID

除了通过上面MEMORY ID 同一用户下不同窗口之间自动传递选择屏幕参数外,也可以通过以下语句来手动传递屏幕参数以及非屏幕参数:

REPORT  ztest_sap_memory_3.
PARAMETERS: p_spa TYPE zdele_1.
START-OF-SELECTION.

 
SET PARAMETER ID ’ZPARA1’ FIELD p_spa.
 
LEAVE TO TRANSACTION ’ztest_sap_memory_4’.

使用SE91为下面ztest_sap_memory_4程序创建了Tcode为:ztest_sap_memory_4

REPORT  ztest_sap_memory_4.
PARAMETERS: p_spa TYPE zdele_1.
AT SELECTION-SCREEN OUTPUT."

 
GET PARAMETER ID ’ZPARA1’ FIELD p_spa.

GET/SET PARAMETER ID还可以与对话屏幕Parameter ID一起使用,如通过MM02输入物料后,可以在程序中直接读取:

DATA: material TYPE mara-matnr.
GET PARAMETER ID 'MAT' FIELD material.
WRITE:/ material.

19.4.     DATABASE

SHARED BUFFER并不访问(存储)数据库,而要存放在数据库就应该用DATABASE

EXPORT DATABASE与普通数据库操作的不同之处是,它适合大数据量的操作,系统自动将其拆分成多条记录并存储到数据库中,比如图片或文档(甚至是程序中的某个内表,请参考后面的实例),而用IMPORT DATABASE的过程则相反,系统将把这些条相关记录又自动组合起来成为一个整体。

image390

如果要自定义INDX这样的表,需要按以下表结构顺序来定义:

image391

该数据库表结构要求:

、可以有也可以无 MANDT字段

、除开第一个字段MANDT(如果有的情况下),下一个字段必须是RELID,类型为CHAR 2,它是用来存储area ID,系统会根据用户在使用EXPORT语句保存数据时指定的area ID来填充它。

、紧接下一个字段是一个任意长度(根据自己的需要定)的CHAR字段,名字也可以是随便取的,该字段用为主键的一部分来使用,该字段的值也是在使用EXPORT语句保存数据时使用ID选项指定的值。

、下一个字段的名字必须是SRTF2,类型为INT4,用来存储数据行号(大数据对象——如图片、文件、程序中的内表对象等,要分成多行来存储)。由于某个数据可能很大,需要多行来存储,理念是可能达到2**31行,该字段会自动的由系统填充。

、在SRTF2字段的后面,你可以包括任意数量及类型的数据字段,这些字段是用来管理大对象的相应信息(如文件名、文件类型、创建者等),当你在保存数据时系统不会自动的填充这些字段,所以在保存这些字段时,需要通过一个结构传递需要存储的值(即EXPORT语句中的From选项所带的结构)。

、倒数第二个字段的名必须为CLUSTR,类型为INT2,它存储了最后一个字段CLUSTD所存储数据的长度(字节数),在使用EXPORT语句保存数据时系统会自动填充

、最后一个字段的名必须是CLUSTD,并且数据类型为LRAW,其长度表示能最大存储多少个字节的内容,如果大数据对象很大(一行存储不下时),会分成多行来存储,行号就存储在前面的SRTF2字段中。

19.4.1.           将文件存入表中

image392

注意:上面这个表中的SRTFD实际上没用上,因为Export时,ID选项的值实质上存储到了它前面的ZZKEY中了,所以可以去掉这个字段(一般会留名为SRTFD字段而去掉ZZKEY字段)。

PARAMETERS: p_file TYPE string OBLIGATORY.
AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_file.
 
CALL FUNCTION 'WS_FILENAME_GET'
   
EXPORTING
      def_filename    
= '*.*'
      def_path        
= 'c:\'
     
mask             = ',*'
     
mode             = 'O'
     
title            = 'File select'
   
IMPORTING
      filename        
= p_file.
START-OF-SELECTION.
 
DATA: il_data LIKE solix OCCURS 0 WITH HEADER LINE,
        l_len
TYPE i.
**Upload file
 
REFRESH: il_data.
 
CLEAR l_len.
 
CALL FUNCTION 'GUI_UPLOAD'
   
EXPORTING
      filename  
= p_file
      filetype  
= 'BIN'

   
IMPORTING
      filelength
= l_len
   
TABLES

      data_tab  
= il_data."ABAP没有二进制类型,X类型代替
 
EXPORT il_data TO DATABASE indx(YY) ID 'ZZZ' .

image393

上面是直接将读取到的文件的二进制数据内表存储到簇数据库表中,我也也可通过SCMS_BINARY_TO_XSTRING函数将读取的二进制数据内表拼接成只有一行的二进制串,然后再存储这个被转换后的二进制串也可:

PARAMETERS: p_file TYPE string OBLIGATORY,
            p_id
LIKE ybc_file-zzkey OBLIGATORY,
            p_ftype
LIKE ybc_file-mimetype OBLIGATORY,
            p_fname
LIKE ybc_file-filename OBLIGATORY.
AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_file.
 
CALL FUNCTION 'WS_FILENAME_GET'
   
EXPORTING
      def_filename    
= '*.*'
      def_path        
= 'c:\'
     
mask             = ',*'
     
mode             = 'O'
     
title            = 'File select'
   
IMPORTING
      filename        
= p_file.
START-OF-SELECTION.
 
DATA: il_data LIKE solix OCCURS 0 WITH HEADER LINE,
        l_len
TYPE i.
**Upload file
 
REFRESH: il_data.
 
CLEAR l_len.
 
CALL FUNCTION 'GUI_UPLOAD'
   
EXPORTING
      filename  
= p_file
      filetype  
= 'BIN'

   
IMPORTING
      filelength
= l_len
   
TABLES
      data_tab  
= il_data."X类型内表

 
CHECK il_data[] IS NOT INITIAL.
**Convert data
 
DATA: l_xstr TYPE xstring.
 
CLEAR l_xstr.
 
"将内表以X类型拼接成XString字符串
 
CALL FUNCTION
'SCMS_BINARY_TO_XSTRING'
   
EXPORTING
      input_length
= l_len
   
IMPORTING
     
buffer       = l_xstr
   
TABLES

      binary_tab  
= il_data.
**Save data
 
"wl_file用于填充ybc_file表中非规定字段
 
DATA: wl_file LIKE ybc_file.
  wl_file
-uname = sy-uname.
  wl_file
-aedtm = sy-datum.
  wl_file
-pgmid = sy-cprog.
  wl_file
-mimetype = p_ftype.
  wl_file
-filename = p_fname.
 
DATA: l_answer TYPE c.
 
EXPORT l_xstr = l_xstr TO DATABASE ybc_file(bc) FROM wl_file ID p_id .

19.4.2.           从表中读取文件

DATA: il_data LIKE solix OCCURS 0.
IMPORT il_data  FROM  DATABASE indx(YY) ID 'ZZZ'.
CALL METHOD cl_gui_frontend_services=>gui_download
 
EXPORTING

  
" bin_filesize            = l_bytes
    filename               
= 'c:\1.jpg'
    filetype               
= 'BIN'
 
CHANGING
    data_tab               
= il_data.

与存储文件一样,如果存储的是拼接好的二进制串,则要使用SCMS_XSTRING_TO_BINARY函数来还原后再下载:
PARAMETERS: p_key LIKE ybc_file-zzkey.
DATA: l_xstr TYPE xstring.
IMPORT l_xstr = l_xstr FROM DATABASE ybc_file(bc) ID p_key.
DATA: l_xstring         TYPE xstring,
      l_xcnt           
TYPE i,
      l_bytes
TYPE i.
TYPES:     hex512(512) TYPE x.
DATA: tab_xstring        TYPE TABLE OF hex512 WITH HEADER LINE.
"XstringX类型视图存储到内表中
CALL FUNCTION
'SCMS_XSTRING_TO_BINARY'
 
EXPORTING buffer     = l_xstr
 
TABLES binary_tab = tab_xstring.


DATA: l_ftype LIKE yhr_attach-mimetype,
      l_fname
LIKE yhr_attach-filename.
"二进内容需使用IMPORT语句中读取,但其他字段除了可使用 IMPORT语句的TO选项来直接读取外,还可以通过SQL直接查询
SELECT SINGLE mimetype filename INTO (l_ftype,l_fname) FROM ybc_file
 
WHERE relid = 'BC' AND zzkey = p_key.

DATA: l_file_name  TYPE string.
CONCATENATE 'C:\' l_fname '.' l_ftype INTO l_file_name.
CALL METHOD cl_gui_frontend_services=>gui_download
 
EXPORTING

    bin_filesize           
= l_bytes
    filename               
=
l_file_name
    filetype               
= 'BIN'

 
CHANGING
    data_tab               
= tab_xstring[].

19.5.     JOB间数据传递

有两种方式:

l  SHARED MEMORY/SHARED BUFFER

l  通过Cluster Databases

posted @ 2015-02-01 15:18  江正军  阅读(6975)  评论(0编辑  收藏  举报