It seems, there once was an ABAP statement like COPY table TO table. that is so obsolete, it isn't mentioned in the ABAP keyword documentation anymore. Anyone having information or examples?
We are writing a tool in Java that parses and transforms ABAP code. We therefore have no intention to write new ABAP code but our tool has to handle all of ABAP, even obsolete statements. Furthermore, I'm not an ABAP expert.
The ABAP language follows the design philosophy that old language constructs might be declared obsolete, or might be illegal in combination with new features. For example, when object-oriented programming was introduced, a lot of older statements became illegal if used within a method of a class.
But the ABAP language development group at SAP always followed the credo that a program which was once legal will always be legal.
Even keywords which were obsolete for ages can still be found in the documentation, just in case someone has to work with legacy code which still uses those language features. But there is no keyword COPY in the alphabetic index. There is only the <tt:copy> node for XML transformations, but that does not seem to be what you are looking for.
So it seems to me that this keyword never existed.
Perhaps you are confusing it with the obsolete MOVE keyword?
MOVE table1 TO table2.
which is an archaic form of writing
table2 = table1.
Assuming your tables are same types and the first one is not empty
You can do:
itab2[] = itab1[]
or, if you have to append rows:
append lines itab1 to itab2
If the table are different you can do:
Loop at itab1 into wa1.
move-corresponding wa1 to wa2.
append wa2 to itab2.
clear wa2.
endloop.
or:
Loop at itab1 into wa1.
wa2-field1 = wa1-field2
...
and so on
...
append wa2 to itab2.
clear wa2.
endloop.
or you can use a field-symbols:
field-symbol: like line of itab1.
Loop at itab1 assigning (if the system is 730, you can declare field symbol in line with assigning field-symbols())
wa2-field1 = -field2
...
and so on
...
append wa2 to itab2.
clear wa2.
endloop.
Related
I'm trying to add data from a internal table to a custom one.
DATA: BEGIN OF TMP_CTRYGRP_T OCCURS 1000,
CTYGR TYPE /SAPSLL/CTYGR,
TEXT1 TYPE /SAPSLL/TEXT60,
END OF TMP_CTRYGRP_T.
SELECT ctygr, text1 FROM /SAPSLL/CTYGPT INTO TABLE #DATA(lt_countryGroupsTable)
LOOP AT lt_countryGroupsTable ASSIGNING FIELD-SYMBOL(<ls_countryGroups>).
APPEND <ls_countryGroups> TO TMP_CTRYGRP_T.
ENDLOOP.
Then I want to add the line in a custom Table Type ZZ_T_TAB
So I've tried to create a field-symbol of this table, creating an internal table from it, but none of the solutions I've tried was permitting me to add lines in that Custom table (even if the one in the program had the lines).
The problem I mainly encountered was:
are not mutually convertible in a Unicode program.
So my questions are:
Why does that error happen? Googling it didn't provide me an understandable answer
For the moment I'm using an internal table limited to 1000 rows. But I don't really know by advance the number of lines the search could provide. Is there any way to improve that?
How to add lines from any solution to my ZZ_T_TAB then? And afterwards how could I add other fields in the same table, for the rows already existing?
As some of you maybe understood, I'm quite a rookie in ABAP.
So if there's any useful link to understand all of that I would be happy if you can share it with me.
Why don't you directly select into the table?
Don't use OCCURS as it is declared obsolete and already forbidden in classes.
Declare your own structure as type and mark your custom internal table as TYPE STANDARD TABLE OF struct_type. This way, there will be no upper bounds
TYPES:
BEGIN OF struct_type,
CTYGR TYPE /SAPSLL/CTYGR,
TEXT1 TYPE /SAPSLL/TEXT60,
END OF struct_type.
DATA tmp_ctrygrp_t TYPE STANDARD TABLE OF struct_type WITH EMPTY KEY.
Why does that error happen? Googling it didn't provide me an
understandable answer
You cannot use APPEND with non-identical structures. You have to "convert" it before. Look up for the command MOVE-CORRESPODING in ABAP help (F1 on command in editor).
For the moment I'm using an internal table limited to 1000 rows. But I
don't really know by advance the number of lines the search could
provide. Is there any way to improve that?
Do not use OCCURS extension it is deprecated (as lausek wrote), old syntax.
How then to add lines from any solution to my ZZ_T_TAB ? And
afterwards how could I add other fields in the same table, for the
rows already existing?
You can modify a DB table various ways.:
1, Use UPDATE statement to directly update a field value.
2, Use MODIFY statement to modify field values from a (for example) pre-selected
structure.
Look up the UPDATE and MODIFY command in ABAP help, there are really helpful code examples.
All tables may be listed with t-code SE16 and table DD02L. But how can that list be accessed programmatically?
It is rarely a good idea to access the database tables directly since you will have to deal with all kinds of technicalities you probably don't even know about - active / inactive versions, for example. You will also bypass all security and authorization checks, which might be irrelevant to you personally, but is undesirable in general. To get a list of tables, you can use the function module RPY_TABLE_SELECT. This function module will take care of the version handling and provide the description in the language of your choice as well.
Improved Alex code in some way and put it as an option:
SELECT tabname
FROM DD02L
INTO TABLE #DATA(itab)
WHERE TABCLASS = 'TRANSP'.
LOOP AT itab ASSIGNING FIELD-SYMBOL(<FS>).
WRITE:/ <FS>.
ENDLOOP.
Several things were refined: incline declarations were utilized, field-symbols added, SELECT * and WHERE IN were omitted and so on. Also tables in SAP have only TRANSP class, INTTAB class belongs to structures.
Note: the sample is functional since ABAP 7.40, SP08.
An ongoing search resulted in the following snippet:
DATA ITAB TYPE TABLE OF DD02L.
SELECT * FROM DD02L INTO TABLE ITAB WHERE TABCLASS IN ('TRANSP', 'INTTAB').
WRITE :SY-SUBRC .
DATA FS TYPE DD02L.
LOOP AT ITAB INTO FS.
WRITE:/ FS-TABNAME.
ENDLOOP.
Table description is given in table DD02T.
I am new in ABAP and I have to modify these lines of code:
LOOP AT t_abc ASSIGNING <fs_abc> WHERE lgart = xyz.
g_abc-lkj = g_abc-lkj + <fs_abc>-abc.
ENDLOOP.
A coworker told me that I have to use a structure and not a field symbol.
How will be the syntax and why to use a structure in this case?
I have no idea why the co-worker wants that you use a structure in this case, because using a field symbol while looping is usually more performant. The reason could be that you are doing some kind of a novice training and he wants you to learn different syntax variants.
Using a structure while looping would like this
LOOP AT t_abc INTO DATA(ls_abc)
WHERE lgart = xyz.
g_abc-lkj = g_abc-lkj + ls_abc-abc.
ENDLOOP.
Your code is correct, because Field symbol functions almost the same as a structure.
For Field symbol
Field symbol is a pointer,
so there is no data copy action for field symbol, and the performance is better
Well if we changed the value via field symbol, the internal table get changed also
For Structure
Structure is a copy of the data, so there is a data copy action, and the performance is bad if the data row is bigger than 200 bytes (based on the SAP ABAP programming guide for performance)
If changed the data in the structure, the original internal table remains the same because there are 2 copies of the data in memory
Can someone simply explain me what happen in field symbols ABAP?
I'm glad if someone can explain the concept and how does it related to inheritance and how does it increasing the performance.
Field Symbols can be said to be pointers. Means, if You assign anything to a fields-symbol, the symbol is strong coupled ( linked ) to the variable, and any change to the fieldsymbol will change the variable immediately. In terms of performance, it comes to use, if You loop over an internal table. Instead of looping into a structure, You can loop into a fieldsymbol. If modifications to the internal table are made, then You can directly modify the fieldsymbol. Then You can get rid of the "modify" instruction,which is used in order to map the changes of the structure back to the corresponding line of the internal table.
"Read Table assigning" also serves the same purpose, like looping into a field-symbol.
Field-Symbol are more recommended then using a "workarea" ( when modifying ) , but references are the thing to go for now. They work almost similar to fieldsymbols.
Could I clarify it for You ?
Field-symbols in ABAP works as pointers in C++.
It has a lot of benefits:
Do not create extra-variables.
You can create a type ANY field-symbol, so you can point to any variable/table type memory space.
...
I hope these lines would be helpful.
Let's have a look at it when it comes to coding. Additionally i would like to throw in data references.
* The 'classic' way. Not recommended though.
LOOP AT lt_data INTO DATA(ls_data).
ls_data-value += 10.
MODIFY TABLE lt_data FROM ls_data.
ENDLOOP.
* Field symbols
LOOP AT lt_data ASSIGNING FIELD-SYMBOL(<fs_data>).
<fs_data>-value += 10.
ENDLOOP.
* Data references
LOOP AT lt_data REFERENCE INTO DATA(lr_data).
lr_data->value += 10.
ENDLOOP.
I personally prefer data references, because they go hand in hand with the OO approach. I have to admit that field symbols are slightly in front when it comes to performance.
The last two should be preferred when talking about modifying. The first example has an additional copy of data which decreases overall performance.
I have an ABAP class method, say, select_something. select_something has an exporting parameter, say, et_result. et_result is of type standard table because the type of et_result cannot be determined until runtime.
The method sometimes gives a short dump saying With ABAP/4 Open SQL array select, the output table is too small at "select * into table et_result from (lv_tablename) where..."
Error analysis:
......in this particular case, the database table is 3806 bytes wide, but the internal table is only 70 bytes wide.
I tried "any table" too and the error is the same.
You could return a data reference. Your query will no longer fail, and you can assign the data to a correctly typed field symbol afterwards.
" Definition
class-methods select_all
importing
!tabname type string
returning
value(results) type ref to data.
...
...
" Implementation
method select_all.
data dref type ref to data.
create data dref type standard table of (tabname).
field-symbols <tab> type any table.
assign dref->* to <tab>.
select * from (tabname) into table <tab>.
get reference of <tab> into results.
endmethod.
Also, I agree with #vwegert that dynamic queries (and programming for that matter) should be avoided when possible.
What you're trying to do looks horribly wrong on many levels. NEVER use SELECT FROM (whatever) unless someone points a gun at your head AND the door is locked tight. You'll loose every kind of static error checking the system might be able to provide you with. For example, the compiler will no longer be able to tell you "Hey, that table you're reading from is 3806 bytes wide." It simply can't tell, even if you use constants. You'll find that out the hard way, producing short dumps, especially when switching between unicode and NUC systems, quite likely some in production systems. No fun.
(Actually there are a few - very very VERY few - good uses for dynamic table names in the SELECT statement. I need them about once every two to three years, and I code quite a lot weird stuff. Just avoid them wherever you can, even at the cost of writing more code. It's just not worth the trouble fixing broken stuff later.)
Then, changing the generic formal parameter type does not do anything to the type of the actual parameter. If you pass a STANRDARD TABLE OF mandt WITH DEFAULT KEY to your method, that table will have lines of 3 characters. It will be a STANDARD TABLE, and as such, it will also be an ANY TABLE, and that's about it. You can twist the generic types anywhere you like, there's no way to enforce correctness using generic types the way you use them. It's up to the caller to make sure that all the right types are used. That's a bad way to fly.
First off, I agree with vwegert's response, try to avoid dynamic sql selections if you can
That said, check the short dump. If the error is an exception class, you can wrap the SELECT statement in a try/catch block and at least stop it from dumping.
You can also try "INTO CORRESPONDING FIELDS OF TABLE et_result". If ET_RESULT is dynamic, you might have to cast it into the proper structure using RTTS. This might give you some ideas...
Couldn't agree more to vwegert, but if there is absolutely no other way (and there usually is) of performing your task than using dynamic select statements and dynamically typed parameters, do some checks on the type of the table and the parameter at runtime.
Use CL_ABAP_TYPEDESCR and its subclasses to do so.
This way, you can handle errors at runtime without your program dumping,
But as vwegert said, this dynamic stuff is pure evil and will most certainly break at some point during runtime. Adding the necessary error handling will most likely be a lot more work and a lot harder than redesigning your code to none dynamic SQL and typed parameters