如何调整ABAP程序的性能(copy) 1、使用where语句 不推荐 Select * from zflight. Check : zflight-airln = ‘LF’ and zflight-fligh = ‘BW222’. Endselect. 推荐 Select * from zflight where airln = ‘LF’ and fligh = ‘222’. Endselect. 2、使用聚合函数 不推荐 Maxnu = 0. Select * from zflight where airln = ‘LF’ and cntry = ‘IN’. Check zflight-fligh > maxnu. Maxnu = zflight-fligh. Endselect. 推荐 Select max( fligh ) from zflight into maxnu where airln = ‘LF’ and cntry = ‘IN’.
3、使用视图代替基本表查询 不推荐 Select * from zcntry where cntry like ‘IN%’. [Page] Select single * from zflight where cntry = zcntry-cntry and airln = ‘LF’. Endselect. 推荐 Select * from zcnfl where cntry like ‘IN%’ and airln = ‘LF’. Endselect.
4、使用INTO table 代替select endselect 不推荐 Refresh: int_fligh. Select * from zflight into int_fligh. Append int_fligh. Clear int_fligh. Endselect. 推荐 Refresh: int_fligh. Select * from zflight into table int_fligh.
5、使用批量修改内表代替逐行修改 不推荐 Loop at int_fligh. If int_fligh-flag is initial. Int_fligh-flag = ‘X’. Endif. Modify int_fligh. Endloop. 推荐 Int_fligh-flag = ‘X’. Modify int_fligh transporting flag where flag is initial.
7、两个内表添加使用批量增加代替逐行 不推荐 Loop at int_fligh1. Append int_fligh1 to int_fligh2. Endloop. 推荐 Append lines of int_fligh1 to int_fligh2.
8、使用table buffering Use of buffered tables is recommended to improve the performance considerably. The buffer is bypassed while using the following statementsSelect distinct Select … for update Order by, group by, having clause Joins Use the Bypass buffer addition to the select clause in order to explicitly bypass the buffer while selecting the data.
9、 使用FOR ALL Entries 不推荐 Loop at int_cntry. Select single * from zfligh into int_fligh where cntry = int_cntry-cntry. Append int_fligh. Endloop. 推荐 Select * from zfligh appending table int_fligh For all entries in int_cntry Where cntry = int_cntry-cntry.
10、正确地使用where语句,使查询能使用索引When a base table has multiple indices, the where clause should be in the order of the index, either a primary or a secondary index To choose an index, the optimizer checks the field names specified in the where clause and then uses an index that has the same order of the fields. One more tip is that if a table begins with MANDT, while an index does not, there is a high possibility that the optimizer might not use that index.
11、正确地使用MOVE语句
Instead of using the move-corresponding clause it is advisable to use the move statement instead. Attempt should be made to move entire internal table headers in a single shot, rather than moving the fields one by one.
12、正确地使用inner joinLet us take an example of 2 tables, zairln and zflight. The table zairln has the field airln, which is the airline code and the field lnnam, which is the name of the airline. The table zflight has the field airln, the airline code and other fields which hold the details of the flights that an airline operates. [Page] Since these 2 tables a re logically joined by the airln field, it is advisable to use the inner join. Select a~airln a~lnnam b~fligh b~cntry into table int_airdet From zairln as a inner join zflight as b on a~airln = b~airln. In order to restrict the data as per the selection criteria, a where clause can be added to the above inner join.
先是用TYPES关键字定义一个行(row)的类型.如下: TYPES: BEGIN OF line, field1 TYPE i, field2 TYPE i, END OF line. 这里的line,就相当于一个自定义的类型,表示一行(row)的字段(field). 这里一行有两个字段field1和field2.
然后是声明一个work area: DATA wa TYPE line. 我用C++(还是对cpp最有好感^^)的概念理解就是, line是一个class,而wa是一个object.
接着是声明一个每一行的类型是line的internal table: DATA itab TYPE line OCCURS 0. 我在暂时把OCCURS作为了区别工作区和内表的标志. OCCURS应该有更深层次的意义,但我目前只能领悟至此... 当我们用以上这个方法来声明一个iternal table时,可以选择是否有无header line. 上面这句就是没有header line的.改成如下就有了: DATA itab TYPE line OCCURS 0 WITH HEADER LINE. 有无header line的区别就是,header line可以当作一个work area来使用(参照我之前的一个日志). 有一下两种方式操作itab: 1). wa-field1 = 1. wa-field2 = 2. APPEND wa TO itab. 2). itab-field1 = 1. itab-field2 = 2. APPEND itab. 这里wa就是上面那个已经定义的work area. 有header line的时候,这两种都可以. 无header line的时候,只能用第1种. 第2种里,itab的意义是一个header line,而不是内表. 因为"DATA itab TYPE line OCCURS 0 WITH HEADER LINE."这样的声明, 已经隐式声明了一个与内表同名的header line. 所以OCCURS用来声明内表可能造成二义性(ambiguous). 于是,OCCURS被认为是old的东西,采用一下方式声明一个内表比较好: DATA itab TYPE STANDARD TABLE OF line.
还有一种声明内表的方法: DATA: BEGIN OF itab OCCURS 0, field1 TYPE i, field2 TYPE i, END OF itab. 这样的itab就自动有了一个同名的header line. 好像不会有 WITHOUT HEADER LINE 或者 NOT WITH HEADER LINE 这样的用法... 如果没有OCCURS 0,比如这样: DATA: BEGIN OF itab, field1 TYPE i, field2 TYPE i, END OF itab. 那么这个itab就不是内表咯,只是一个structure,可以作为itab的work area.
======================================================= ABAP Work Area & Header Line -
1. Difference between Work Area and Header Line 工作区与标题行的不同之处 原文地址: http://www.sap-img.com/abap/difference-between-work-area-and-header-line.htm 我翻译下,嘿嘿 在对内表进行一些操作的时候,比如增加或者取回一条记录.我们必须暂时保存这条记录. 这条记录就保存在内表的工作区里(work area).内表的工作区必须和内表有相同的结构. 内表由主体(body)和一个可选的标题行(head line)组成. 标题行是一个隐式的(implicit)工作区.在内表声明的时候,可以选择有无标题行. e.g. data: begin of itab occurs 10, ab type c, cd type i, end of itab. 这样的内表itab,是有标题行的. data: wa_itab like itab. 这样的wa_itab是显式(explicit)声明的一个itab的工作区. data: itab1 like itab occurs 10. 这样的内表itab1,是没有标题行的.
DATA: BEGIN OF line, col1(1) TYPE c, col2(1) TYPE c, END OF line. DATA itab LIKE TABLE OF line WITH HEADER LINE. line-col1 = 'A'. line-col2 = 'B'. APPEND line TO itab. loop at itab. write : itab-col1. endloop. clear itab. "在这里可以尝试CLEAR ITAB[],FREE ITAB,REFRESH ITAB,看看效果是不是如上所说这样。 IF itab IS INITIAL. WRITE 'ITAB is empty'. ENDIF.
很多程序BUG,就是这一类 不起眼的东西引起的~ ********************************************************************* *-------- Clear & Refresh Internal Table. ------------------------- ********************************************************************* 1. with headerline. CLEAR itab. : Clear the headerline of the Internal Table only. CLEAR itab[]. : Clear the contents of the Internal Table except the headerline. REFRESH itab. : Same as CLEAR itab[]. REFRESH itab[]. : Same as CLEAR itab[]. 2. without headerline. ( all four commands have same functionality ) CLEAR itab. : Clear all contents of the Internal Table. CLEAR itab[]. : Same as CLEAR itab. REFRESH itab. : Same as CLEAR itab. REFRESH itab[]. : Same as CLEAR itab.
如何一次性的给内表的一列赋值,不用LOOP循环来做,比如把第一列都给设置成空.
CLEAR 对应工作区清空 MODIFY 内表 FROM 内表对应工作区 TRANSPORTING 修改字段 WHERE 修改字段 <> SPACE.
http://help.sap.com/saphelp_sm32/helpdata/en/fa/09715a543b11d1898e0000e8322d00/frameset.htm DATA: it_bdcdata TYPE TABLE OF bdcdata, wa_bdcdata TYPE bdcdata. wa_bdcdata-program = 'SAPLBTCH'. wa_bdcdata-dynpro = '2170'. wa_bdcdata-dynbegin = 'X'. APPEND wa_bdcdata TO it_bdcdata. CLEAR wa_bdcdata. wa_bdcdata-fnam = 'BTCH2170-JOBNAME'. wa_bdcdata-fval = '*'. APPEND wa_bdcdata TO it_bdcdata. wa_bdcdata-fnam = 'BTCH2170-USERNAME'. wa_bdcdata-fval = sy-uname. APPEND wa_bdcdata TO it_bdcdata. CALL TRANSACTION 'SM37' USING it_bdcdata. -------------------------------------------------------- Submit to executable program via selection options -------------------------------------------------------- SUBMIT zrmm0001 VIA SELECTION-SCREEN AND RETURN WITH p_matnr = itab-matnr WITH p_werks = itab-werks WITH p_lgort = itab-lgort WITH s_charg = itab-charg WITH p_num = p_label WITH p_dest = p_print.
程序的效率是每个程序员都应该重视的,无论是采用的哪一种语言进行开发. 在我做过的一个项目中,一个几万条数据的运行,在没有考虑效率,对代码没有进行优化前的运行时间是7个小时,当对代码进行一系列的优化修改后,运行的时间就只剩一个小时,由此可见,代码的优化是多么的重要。 那么,我们在写ABAP程序时,怎样的语句才能提高到效率呢,下面是我总结到的几点: 1、抽取数据时,避免使用SELECT *, 尽量使用SELECT A B INTO TABLE ITAB这样的语句。 2、不要使用SELECT...ENDSELECT语句。 3、尽量避免在LOOP中访问数据库。可以在之前先把数据取到内表,在LOOP中用READ TABLE WITH KEY ... BINARY SEARCH.进行读取对应的数据。 4、用SORT代替ORDER BY。 5、避免使用嵌套的循环。 6、尽量不要使用JOIN进行多表连接。把一个表的数据先取到内表,然后使用FOR ALL ENTRIES语句再进行抽取。 7、使用二分查找法。 READ TABLE的之前使用SORT TABLE BY对内表进行排序, 然后使用READ TABLE WITH KEY ...BINARY SEARCH. 8、避免使用SELECT DISTINCT语句。在抽取数据到内表后用DELETE ADJACENT DUPLICATES语句来消除重复行。 9、尽量加多WHERE语句进行条件抽取。 以上,说的还不全,会进行不断更新。 另外,可以通过TCODE:ST05 SE30 进行程序和SQL语句性能和效率的分析 sap 在ABAP 中 MOVE ... TO 和 WRITE ... TO 的区别
WRITE ... TO 把源的格式 附值到目标。
MOVE ... TO 直接把源的值附到目标。
示例:
data: gv_char1(20) type c, gv_char2(20) type c, dec1(10) type p decimals 2 value '22345.89'.
start-of-selection. * date * write:/ 'date variable'. write sy-datum to gv_char1. write:/ 'write to', gv_char1. move sy-datum to gv_char2. write:/ 'move to', gv_char2. skip 1. * decimal * write:/ 'decimal variable'. write dec1 to gv_char1. write:/ 'write to', gv_char1. move dec1 to gv_char2. write:/'move to', gv_char2.
Assigning Values with MOVE
To assign the value of a data object source to a variable destination, use the following statement:
MOVE source TO destination.
or the equivalent statement
destination = source.
The content of source remains unchanged, source does not therefore have to be a variable - it can also be a literal, a text symbol, or a constant. You must always specify decimal points with a period (.), regardless of the user’s personal settings.
Multiple assignments
f4 = f3 = f2 = f1.
are also possible. ABAP processes them from right to left as follows:
MOVE f1 TO f2. MOVE f2 TO f3. MOVE f3 TO f4.
In the MOVE statement (or when you assign one value to another with the equal sign), it is not possible to specify the field names dynamically as the contents of other fields. If you need to do this, you must use field symbols .
The source and target fields can be of different data types. The result of the value assignment depends on whether these data types are compatible and whether a type conversion can be performed. If there is no conversion rule between the data types in question, no assignment can be made.
DATA: t(10) TYPE c, number TYPE p DECIMALS 2, count TYPE i.
t = 1111. MOVE '5.75' TO number. count = number.
Following these assignments, the fields t, number and count have the values ‘1111 ’, 5.75, and 6 respectively. When you assign the number literal 1111 to T, it is converted into a character field with length 10. When you assign number to count , the decimal number is rounded to an integer (as long as the program attribute Fixed pt. arithmetic has been set). Assigning Values Between Components of Structures
The rules for value assignments between data objects also apply to structures. With the command
DATA: struct1 TYPE structure, struct2 TYPE structure. struct1 = struct2.
two structures of the same type can be assigned to one another without difficulty. Here, the entire source structure is seen as a unit and copied to the source structure. It is then possible to access the components individually again. If the structures in question are not compatible, see the conversion rules for structures.
In practice, however, you will often only need to assign certain components of a structure to be certain components of another structure. ABAP has a special statement for this purpose:
MOVE-CORRESPONDING sourcestruct TO destinationstruct.
This statement assigns the contents of the components of structure sourcestruct to the components of the destinationstruct structure that have identical names.
When it is executed, it is broken down into a set of MOVEstatements, one for each pair of fields with identical names, as follows:
MOVE sourcestruct-comp1 TO destinationstruct-comp1.
MOVE sourcestruct-comp2 TO destinationstruct-comp2.
...
Any necessary type conversions are performed individually.
DATA: BEGIN OF address, firstname(20) TYPE c VALUE 'Fred', surname(20) TYPE c VALUE 'Flintstone', initials(4) TYPE c VALUE 'FF', street(20) TYPE c VALUE 'Cave Avenue', number TYPE i VALUE '11', postcode(5) TYPE n VALUE '98765', city(20) TYPE c VALUE 'Bedrock', END OF address.
DATA: BEGIN OF name, surname(20) TYPE c, firstname(20) TYPE c, initials(4) TYPE c, title(10) TYPE c VALUE 'Mister', END OF name.
MOVE-CORRESPONDING address TO name.
In this example, the values of name-surname, name-firstname and name-initials are set to 'Flintstone’, ‘Fred’, and 'FF'. name-title always has the value ‘Mister’.
CREATE DATA dref {TYPE type}|{LIKE dobj}这种语句创建的对象没有名称,只有地址变量指向该内存变量;在申明参考变量时,未指定类型则必须加{TYPE type}|{LIKE dobj}说明。
有时需要动态创建动态类型数据对象,语法如下
CREATE DATA dref TYPE (name).
3、将数据地址赋值给数据参考变量(GET REFERENCE)
GET REFERENCE OF dobj INTO dref.
4、访问数据参考变量指定的数据
访问数据参考变量指定的数据有两种情况:
1) 对于使用DATA dref TYPE REF TO DATA_TYPE来声明的数据参考变量,程序可以直接通过->*运算符直接访问数据;
代码样例
types: begin of STRUC_1, A type I, B type ref to SFLIGHT, C type P, end of STRUC_1. data: S1 type STRUC_1. types: begin of STRUC_2, X(10) type C, Y type ref to STRUC_1, Z type I, end of STRUC_2. data: S2 type STRUC_2, R2 type ref to STRUC_2. if S1-A > 10. create data S1-B. S1-B->CARRID = 'LH'. S1-B->PAYMENTSUM = 1000. endif.