ABAP提供了IMPORT/EXPORT 和 SET/GET PARAMETER语句,可对用户内存/服务器内存/数据库进行存储和访问。
详细请参照《数据共享与传递.docx》文档
EXPORT 语句
EXPORT{p1= dobj1 p2 = dobj2 ...} |{p1FROM dobj1 p2 FROM dobj2 ...} | (ptab)
TO | { MEMORY ID id }
| { DATABASEdbtab(ar) [FROM wa] [CLIENT cl] ID id }
| { SHARED MEMORY dbtab(ar) [FROM wa] [CLIENT cl] ID id }
| { SHARED BUFFERdbtab(ar) [FROM wa] [CLIENT cl] ID id }
1. {p1 = dobj1p2 = dobj2 ...}与 {p1 FROM dobj1 p2 FROM dobj2 ...}的意义一样,只是写法不一样,dobj1、dobj2…变量将会以p1、p2…名称存储到内存或数据库中。p1、p2…名称随便取,如果p1、p2…与将要存储的变量名相同时,只需写变量名即可,即等号与 FROM 后面可以省略。p1、p2…这些名称必须与IMPORT语句中相一致,否则读取不出
2. (ptab):为动态指定需要存储的变量,ptab内表结构要求是这样的:只需要两列,列名任意,但类型需要是字符型;第一列存储如上面的p1、p2…名称,第二列为上面的dobj1、dobj2…变量,如果变量与名称相同,则也可以像上面一样,省略第二列的值。两列的值都必需要大写,实例如下:
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内存中
4. DATABASE:将变量存储到数据库中;dbtab为簇数据库表的名称(如系统提供的标准表INDX);ar的值为区域ID,它将数据库表的行分成若干区域,它必须被直接指定,且值是两位字符,被存储到簇数据库表中的RELID字段中;id 的值会存储到簇数据表中的RELID字段的下一用户自定义字段中:
.
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'.
实例二:
.
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.
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应用服务器上的SAP Memory中,可共同一服务上的所有程序访问。两种的作用是一样的,最大不同是在数据达到最大内存限制时的处理方式不同:最大内存限制值分别是通过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 wa:wa工作区类型可以参照簇数据库dbtab类型,也可定义成的用户数据)的值,然后在Export时将相应的字段存储到SRTF2字段与CLUSTR字段间的相应字段中去。如果使用“TABLES dbtab.”定义语句,可以省略“[FROM wa]”,也会默认将其存储到数据库表中,但如果没有“TABLES dbtab.”这样的定义语句,也没有“[FROM wa]”选项时,将不会有数据存储到簇数据库表中的用户字段中去
7. CLIENT cl:默认为当前客户端,存储到簇数据库表中的MANDT字段中
IMPORT语句
IMPORT {p1 = dobj1 p2 = dobj2 ...} | {p1 TO dobj1 p2 TO dobj2 ...} | (ptab)
FROM | { MEMORY ID id }
| { DATABASEdbtab(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.
实例二:
.
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
IMPORT DIRECTORY语句
IMPORT DIRECTORY INTO itabFROM DATABASE dbtab(ar) [TO wa] [CLIENT cl] ID id.
该语句的作用用来读取存储到簇数据表中的变量信息,如存储名是什么、以什么样的类型存储的、数据长度等(有点类似反射)。itab 为cdir词典类型的内表,其结构与各字段作用:
Component |
Type |
Meaning |
NAME |
CHAR(30) |
Name of the parameter under which a data object was saved. |
OTYPE: |
CHAR(1) |
General type of the data object saved. The following values are permitted: "F" for elementary, flat data objects, "G" for strings, "R" for flat structures, "S" for deep structures, "T" for internal tables with flat row type and "C" for tables with a deep row type. |
FTYPE |
CHAR(1) |
More specific type of the data object saved. For elementary data objects and internal tables with a elementary row type, the data or row type is returned in accordance with the table of return values fromDESCRIBE FIELD ... TYPE ("a", "b", "C", "D", "e", "F", "g", "I", "N", "P", "s", "T", "X", "y"). In the case of flat structures and internal tables with flat structured row types, "C" is returned. In the case of deepstructures and internal tables with deep structured row types, "v" is returned. In the case of a table that has an internal table as a row type, "h" is returned. |
TFILL |
INT4 |
Length filled of the saved data object. For strings the length of the content in bytes is returned and for internal tables the number of rows is returned. The value 0 is returned for other data objects. |
FLENG |
INT2 |
Length of saved data object or saved table row in bytes. The value 8 is returned for strings. |
DATA: f1 TYPE decfloat16,
f2 TYPE TABLE OF i,
f3 TYPE spfli.
DATA itab TYPE STANDARD TABLE OF cdir.
DO 10 TIMES.
APPEND sy-index TO f2.
ENDDO.
EXPORT par1 = f1 par2 = f2 par3 = f3 TO DATABASE demo_indx_table(hk) ID 'HK'.
IMPORT DIRECTORY INTO itab FROM DATABASE demo_indx_table(hk) ID 'HK'.
NAME |
OTYPE: |
FTYPE |
TFILL |
FLENG |
"PAR1" |
"F" |
"a" |
0 |
8 |
"PAR2" |
"T" |
"I" |
10 |
4 |
"PAR3" |
"R" |
"C" |
0 |
168 |
DELETE FROM语句
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语句的存储的数据
其中DELETE FROM MEMORY ID id.与FREE MEMORY ID id.作用一样
IMPORT p1 = text2 p2 = text1 FROM SHARED BUFFER demo_indx_table(xy) ID id.
ABAP Memory(同一用户的同一窗口Session)
l 保存数据
EXPORT<f1>[FROM <g1>]<f2> [FROM <g2>] ... TO MEMORY ID <key>.
如果省略了FROM <g1>选项,则被存储的数据源就来自于程序中与f1自已同名的变量,否则数据源为g1指定的变量(或者g1本身就是字符常量);key 用来标示ABAP内存。可以将多个变量存储在同一个<key>中,它们是通过<fi>来区别的。IMPORT中的<fi>必须与EXPORT中的<fi>名称相同。
) VALUE 'Exporting'.
DATA itab LIKE sbook OCCURS 10 WITH HEADER LINE.
DO 5 TIMES.
itab-bookid = 100 + sy-index.
APPEND itab.
ENDDO.
"将 text1 与 text2都存储到 text ID的名下
EXPORT text1 "数据来源于上面定义的 text1变量,并以text1名分类存储
text2 FROM 'Literal'"数据直接来源于From后面指定的常量字符串,也以text1名分类存储
TO MEMORY ID 'text'.
"将前面定义的itab存储到以table为ID的内存中,并以itab名分类存储
EXPORT itab TO MEMORY ID 'table'.
l 读取数据
IMPORT <f1> [TO <g1>] <f2> [TO <g2>] ... FROM MEMORY ID <key>.
如果忽略选项TO<gi>,则将内存中的数据对象<fi>赋给程序中的同名数据对象;如果使用此选项,则将内存中的数据对象<fi>写入字段<gi>中。IMPORT中的<fi>必须与EXPORT中的<fi>名称相同。
不必读取存在特定ID<key>下的所有对象,在读取时可以通过指定名称<fi>中进行有选择性的读取。如果内存中不包含指定ID<key>下的对象,则将SY-SUBRC设置为4,但是如果内存中存在带此ID的数据簇,无论数据对象<fi>是否也存在,SY-SUBRC之值总是为0。如果簇中不存在数据对象<fi>,则目标字段保持不变(gi或fi本身)。
) VALUE 'TEST1'.
DATA itab LIKE sbook OCCURS 10 WITH HEADER LINE.
DO 5 TIMES.
itab-bookid = 100 + sy-index.
APPEND itab.
ENDDO.
EXPORT text1"被存储的数据来自text1变量
text2 FROM 'Literal'"被存储的数据直接来自FORM后面字符串常量
"将'TEST1'与'Literal'存储到ID为text的ABAP内存中,并且分别以
"text1和text2标签来分类存储
TO MEMORY ID 'text'.
EXPORT itab"被存储的数据来自itab变量所对应的内存
TO MEMORY ID 'table'.
SUBMIT zjzjimpt1 AND RETURN."调用其他程序并等待返回
),
text3 LIKE text1.
"从ID为text的ABAP内存区域读取分类存储标签为text1
"的内存数据并存储到text1变量中去
IMPORT text1 FROM MEMORY ID 'text'.
WRITE: / sy-subrc, text1.
"从ID为text的ABAP内存区域读取分类存储标签为text2
"的内存数据并存储到text3变量中去
IMPORT text2 TO text3 FROM MEMORY ID 'text'.
WRITE: / sy-subrc, text3.
DATA jtab LIKE sbook OCCURS 10 WITH HEADER LINE.
"从ID为table的ABAP内存区域读取分类存储标签为itab
"的内存数据并存储到jtab变量中去
IMPORT itab TO jtab FROM MEMORY ID 'table'.
LOOP AT jtab.
WRITE / jtab-bookid.
ENDLOOP.
* 0 TEST1
* 0 Literal
*00000101
*00000102
*00000103
*00000104
*00000105
l 删除数据
FREE MEMORY [ID <key>].
与DELETE FROM MEMORY ID id.等效
如果不附加ID<key>,则此语句删除整个内存,包括此前用EXPORT存储到ABAP/4内存中的所有数据簇。附加ID<key>之后,该语句只删除用此名称命名的数据簇。
用户登陆后,最多一个系统可以开6个窗口,这在SAP中称为External Mode。而同一个窗口中,运行某程序后,可以通过CALL TRANSACTION/SUBMIT或其他代码跳转到其他程序,这个称为Internal Mode。Internal Mode的调用栈最多为9层。那么ABAP Memory,它是属于Internal Mode间可以共享的数据,而External Mode间无法共享。所以,ABAP Memorcy只能在同一窗体*享,这与浏览器中的Session是一样的。
SAP Memory(同一用户的不同窗口Session)
更多请参考《数据共享与传递.docx》中的SAP Memory语句章节
同一客户端的不同窗体(External Mode)它们之间共享数据必须通过SET/GET PARAMETER语句,不再是EXPORT/IMPORT的模式。
例子. 创建程序A,输入:
DATA matnr TYPE matnr.
GET PARAMETER ID 'ytest' FIELD matnr.
WRITE matnr.
创建程序B,输入:
DATA: matnr TYPE matnr.
matnr = '000000000000012345'.
SET PARAMETER ID 'YTEST' FIELD matnr.
在窗口1运行程序B并关闭后,在窗口2运行程序A,发现程序A仍然读到了SAP Memory的值。
说明:
1、 调试时,可通过点击Goto->System Area->SAP Memory,查看到YTEST及其对应的值。
2、 SET/GET PARAMETER的值与本次登陆有关,当用户注销后才失效。在用户登陆的时候,系统会根据每个用户System->User Profile->Own Data->Parameter下的设置,载入到SAP Memory。
3、 在Data Element中可以看到Further Characteristics下可定义PARAMETER ID,代表该字段作为屏幕元素时,可读取该PARAMETER ID作为默认值。比如VA03会自动显示刚刚创建的订单号。
SHARED MEMORY/SHARED BUFFER(不同Client、Job)
前面介绍的都是用户内存,那么不同用户间如何实现数据共享呢?可以用SHARED MEMORY或SHARED BUFFER,它们是服务器上的某片所有用户共享的内存。关于SHARED MEMORY和SHARED BUFFER的区别,可以F1查看帮助。如果EXPORT SHARED BUFFER,则必须IMPORT SHARED BUFFER才能读到,用IMPORT SHARED MEMORY是读不到的。反过来也是。
例子. 创建程序A,输入:
DATA matnr TYPE matnr.
IMPORT matnr FROM SHARED BUFFER indx(aa) ID 'YTEST_MATNR '.
WRITE matnr.
创建程序B,输入:
DATA: matnr TYPE matnr.
matnr = '000000000000123456'.
EXPORT matnr TO SHARED BUFFER indx(aa) ID 'YTEST_MATNR'.
先在用户1的电脑上运行程序B,然后在用户2的电脑上运行程序A,发现用户2可以读取到值。
说明:
1、 既然是服务器上的所有用户共享空间,那么该值将保存到服务器关机重启为止,除非用户用DELETE语句清除它。其实这个跟ENQUEUE/DEQUEUE有点相似之处。
2、 数据库也可共享数据,不过服务器共享肯定速度快些。
3、 INDX是系统中存在的符合特定格式要求的表。但这不代表该EXPORT/IMPORT语句将在表INDX中增加记录,仅仅代表服务器借用了INDX的结构来管理该片共享内存。
删除:
DELETE FROMSHARED BUFFER dbtab(ar) [CLIENT cl] ID id
DELETE FROMSHARED MEMORY dbtab(ar) [CLIENT cl] ID id
更具体的实例请参考《操作设置.docx》文档中的“通过程序创建Job”小节实例
Smartform中使用全局自定义表
在开发smartform的时候可以通过指针来调用全局自定义的表,而不用在系统中创建一个永久的结构。
【1】:在SmartForm中定义一个结构,这个结构要和程序中使用的结构完全相同。
【2】:定义报表中全局的表和工作空间,
【3】:定义指针,指向程序中的某个内表,然后获取该内表。
其实如果也想这样动态调用某函数里的全局变量,先找到这个函数所在的函数组,再找到该函数组所对应的主程序名,然后像上面那样使用即可:
动态访问主调程序中的全局变量
DATABASE
上面说了SHARED BUFFER并不访问(存储)数据库,而要访问数据库就应该用DATABASE。
EXPORT DATABASE与普通数据库操作的不同之处是,它适合大数据量的操作,系统自动将其拆分成多条记录并存储到数据库中,比如图片或文档(甚至是程序中的某个内表,请参考后面的实例)。而用IMPORT DATABASE的过程则相反,系统将把这些条相关记录又自动组合起来成为一个整体。
如果要自定义INDX这样的表,需要按以下表结构顺序来定义:
1、可以有也可以无 MANDT字段
2、除开第一个字段MANDT(如果有的情况下),下一个字段必须是RELID,类型为CHAR 2,它是用来存储area ID,系统会根据用户在使用EXPORT语句保存数据时指定的area ID来填充它。
3、紧接下一个字段是一个任意长度(根据自己的需要定)的CHAR字段,名字也可以是随便取的,该字段用为主键的一部分来使用,该字段的值也是在使用EXPORT语句保存数据时使用ID选项指定的值。
4、下一个字段的名字必须是SRTF2,类型为INT4,用来存储数据行号(大数据对象——如图片、文件、程序中的内表对象等,要分成多行来存储)。由于某个数据可能很大,需要多行来存储,理念是可能达到2**31行,该字段会自动的由系统填充。
5、在SRTF2字段的后面,你可以包括任意数量及类型的数据字段,这些字段是用来管理大对象的相应信息(如文件名、文件类型、创建者等),当你在保存数据时系统不会自动的填充这些字段,所以在保存这些字段时,需要通过一个结构传递需要存储的值(即EXPORT语句中的From选项所带的结构)。
6、倒数第二个字段的名必须为CLUSTR,类型为INT2,它存储了最后一个字段CLUSTD所存储数据的长度(字节数),在使用EXPORT语句保存数据时系统会自动填充
7、最后一个字段的名必须是CLUSTD,并且数据类型为LRAW,其长度表示能最大存储多少个字节的内容,如果大数据对象很大(一行存储不下时),会分成多行来存储,行号就存储在前面的SRTF2字段中。
将文件存入表中
注意:上面这个表中的SRTFD实际上没用上,因为Export时,ID选项的值实质上存储到了它前面的ZZKEY中了,所以可以去掉这个字段(一般会留名为SRTFD字段而去掉ZZKEY字段)。
.
MESSAGE 'Success' TYPE 'S'.
ENDIF.
上面是直接将读取到的文件的二进制数据内表存储到簇数据库表中,我也也可通过SCMS_BINARY_TO_XSTRING函数将读取的二进制数据内表拼接成只有一行的二进制串,然后再存储这个被转换后的二进制串也可:
no_batch
selection_cancel
selection_error
.
MESSAGE 'Success' TYPE 'S'.
ENDIF.
从表中读取文件
.
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.
与存储文件一样,如果存储的是拼接好的二进制串,则要使用) TYPE x.
DATA: tab_xstring TYPE TABLE OF hex512 WITH HEADER LINE.
"将Xstring以X类型视图存储到内表中
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语句中读取了,但其他字段还得要
"通过SQL来查询。注:也可使用 IMPORT语句的TO选项来直接读取
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[].