use SELECT on internal table (ABAP) - abap

I am still very inexperienced with SAP ABAP.
I have an internal table that I want to filter further and further based on whether data is present.
I have tried the following, but unfortunately I cannot apply a SELECT to an internal table.
How can I solve this problem?
Hope I have explained my problem clearly enough!
"Here I'm getting the hole database into my internal table
SELECT * FROM TABLE
INTO CORRESPONDING FIELDS OF TABLE #itab.
"This should be my first filter if iv_name is not initial
IF iv_name IS NOT INITIAL.
SELECT * FROM itab
WHERE NAME = #iv_name
INTO CORRESPONDING FIELDS OF TABLE #itab.
ENDIF.
"This should be my second filter if iv_age is not initial
IF iv_age IS NOT INITIAL.
SELECT * FROM itab
WHERE AGE = #iv_age
INTO CORRESPONDING FIELDS OF TABLE #itab.
ENDIF.

There are several ways in ABAP to achieve your goal.
You can use the DELETE keyword to filter the data in an internal table:
IF iv_name IS NOT INITIAL
DELETE itab WHERE name NE iv_name.
ENDIF.
Another possibility is to use the FILTER keyword, but the prerequisite is, that the internal table is TYPE SORTED or HASHED:
itab = FILTER #( itab WHERE name = iv_name ).

Related

Delete field contents from the structure?

I want to clear that field from a structure.
First I am reading a row from the database into my structure ls_mara:
SELECT SINGLE mfrpn, ean11, matnr, prdha FROM mara INTO #DATA(ls_mara)
WHERE matnr EQ #lv_matnr.
I have a table : ZADOBE_CODE and it involved matnr and prdha.
I need to check matnr and prdha and if I find same data in ZADOBE_CODE, then I must delete the field ls_mara-mfrpn. I wrote that:
SELECT SINGLE matnr, prdha FROM zadobe_code INTO #DATA(ls_zadobe_code)
WHERE matnr EQ #ls_mara-matnr OR prdha EQ #ls_mara-prdha.
IF ls_zadobe_code IS NOT INITIAL.
"DELETE mfrpn FROM ls_mara.
ELSE.
ENDIF.
But my delete row is wrong. How can I write?
The DELETE statement is for deleting whole rows from a table (either database or internal, depending on how you write it). According to your comments, that's not what you want to do.
If you want to clear a field from a structure in memory, then you can do that either with CLEAR ls_mara-mfrnp. or by simply assigning an empty string to it with ls_mara-mfrnp = ''.

Change field depending on if field value is contained in other table

So my goal is to change a field in a table for those entries that the value is contained in some other table.
So for example.
If the name "John" from table_abc is contained in the table l_t_xyz then change the value to "ABC".
My approach to this:
SELECT * FROM table_xyz INTO TABLE #DATA(l_t_xyz).
Let's say one of the field of table_xyz is NAME.
And i have a second table, also with the field NAME where I want to change one of the fields
LOOP AT table_abc ASSIGNING FIELD-SYMBOL(<abc_line>) WHERE name in table_xyz-name.
<abc_line>-name = 'ABC'
ENDLOOP.
But this gives me an error that table_xyz is a table without a header line, therefore has no component called "NAME".
How do I solve this. Also I can't find any documentation on the keyword IN. Maybe I am using it wrong in this case.
So I have found another solution, which was inspired by Eray answer.
Basing on ranges
SELECT 'I' AS sign,
'EQ' AS option,
name as low
name as high
into table #DATA(range_table)
LOOP AT table_abc[] ASSIGNING FIELD-SYMBOL(<abc_line>) WHERE name in range_table.
<abc_line>-name = 'abc'
ENDLOOP.
You should define a range for name values which stored in table_xyz.
That's quick example:
TYPES lr_name_range_type TYPE RANGE OF name. "you should define appropriate data type
DATA : lr_name_range TYPE lr_name_range_type.
//define macro
DEFINE fill_range.
lr_name_range = VALUE #( BASE lr_name_range( sign = 'I' option = 'EQ' low = &1 ) ).
END-OF-DEFINITION.
//fill range according to table_xyz values
LOOP AT table_xyz ASSIGNING FIELD-SYMBOL(<fs_xyz>).
fill_range <fs_xyz>-name.
ENDLOOP.
//Now you can use IN keyword for your loop
LOOP AT table_abc ASSIGNING FIELD-SYMBOL(<abc_line>) WHERE name in lr_name_range.
<abc_line>-name = 'ABC'
ENDLOOP.
It's faster:
data lt_name type hashed table of table_xyz-name with unique default key.
SELECT * FROM table_xyz INTO TABLE #DATA(l_t_xyz).
lt_name = value #( for group fgv_name of <fs_xyz> in l_t_xyz
group by <fs_xyz>-name
( fgv_name )
).
LOOP AT table_abc ASSIGNING FIELD-SYMBOL(<fs_line>).
if line_exists( lt_name[ table_line = <fs_line>-name ] )
<fs_line>-name = 'ABC'.
endif.
ENDLOOP.

A short syntax to fill ABAP table from another table?

In the old ABAP syntax I have to loop over the source table, and inside of the loop append value to the table.
For example:
DATA:
it_source_table type table of mara,
et_result_table type table of matnr.
loop at it_source_table into data(ls_source_table).
append ls_source_table-matnr to et_result_table.
endloop.
Is there with a new ABAP syntax (750, 752) ("move-corresponding", "value#") a way to achieve the same in less sentences?
You can use the VALUE operator with the FOR ... IN addition:
et_result_table = VALUE #( FOR material IN it_source_table ( material-matnr ) ).

From which table does for all enteries makes a select?

I have two standard tables, VBAP and MAKT.
I want elements of MAKT-MAKTX, where MAKT-MATNR = VBAP - MATNR.
SELECT MATNR FROM VBAP INTO IT_VBAP.
SELECT MATNR MAKTX FROM MAKT INTO IT_MAKT FOR ALL ENTRIES WHERE MATNR = IT_VBAP.
Does this code choose values in it_makt where only those matnr fields are equal?
What exactly does for all entries does.
Thank you.
select field_1 field_2 field_n from table into internal_table for all
entries in another_internal_table where some_field_in_table = another_internal_table-same_field_in_another_internal_table.
You use for all entries when you want to fill an internal table according to values in another internal table.
You can try using the following
select matnr from vbap into it_vbap.
select maktx from makt into it_makt for all entries in it_vbap where matnr = it_vbap-matnr.
For all entries is the the exact thing, You might think, as You read it. It is like this:
"For all entries in" allows You to use a subset of an internal table as where condition in a select statement by the possibility to provide the fields of this internal table as where condition-parameters in the select statement.
So, internally it is also only a loop, You can use the sql-monitor transaction, and mostly will see, that for all entries really behaves like a select inside a loop if I remember correctly. It is quite helpful, and usually used relatively often.
If the subset-table, which is used as parameter-table is empty, then You perform a full table select (full table scan), if You only use the tables fields as where parameters. So always pay attention to the select which fills Your where-table or check its contents with if lines( the_table ) > 0. Nevertheless take a look at vwegert's link, it describes the pros and cons of for all entries. Do You need more info ?

How to set dynamic key for READ TABLE?

I'm trying to work out a way to read an internal table that has to be created dynamically. I have created the following report that fills a dynamic internal table with data.
On the last line, I'm trying to read it with a key (mandt for example), but I I get this syntax error:
The specified type has no structure and therefore no component called MANDT
I have debugged and I can see that <any_tab> has been populated successfully and the structure of the table (field names) are correct. The problem presents itself when I try to read the table into a work area. Maybe I'm doing this wrong, but it seems like something that should be possible to do, and I have a feeling I'm missing something small.
The reason I am trying this out is that I have found identical selects happening in a program and want to buffer records in memory and read them from there to avoid DB accesses. This is easy to implement, however I haven't done this when the table, where clause and into clause of the OPEN SQL statement I'm trying to optimize are dynamic.
How to correct the syntax error?
DATA: t681_rep TYPE TABLE OF t681 , wa_681 LIKE LINE OF t681_rep,
tabref TYPE REF TO data , waref TYPE REF TO data.
FIELD-SYMBOLS: <any_tab> TYPE ANY TABLE,
<any_wa> TYPE ANY,
<var1> TYPE ANY.
"fill t681_rep
SELECT *
FROM t681
INTO TABLE t681_rep
UP TO 1 ROWS WHERE kotab = 'A002'.
READ TABLE t681_rep INTO wa_681 WITH KEY kotab = 'A002'.
IF sy-subrc = 0.
"if A002 is found create a table of that type and fill it
CREATE DATA tabref TYPE TABLE OF (wa_681-kotab).
ASSIGN tabref->* TO <any_tab>.
SELECT * UP TO 10 ROWS
FROM (wa_681-kotab)
INTO TABLE <any_tab>.
ENDIF.
CREATE DATA waref TYPE a002.
ASSIGN waref->* TO <any_wa>.
READ TABLE <any_tab> ASSIGNING <any_wa> WITH KEY mandt = '800'. <- problem area
IF sy-subrc = 0.
"do stuff with <any_wa>...
ENDIF.
You just need to put the field name in parentheses.
data: field type string.
field = 'MANDT'.
READ TABLE <any_tab> ASSIGNING <any_wa> WITH KEY (field) = '800'.
IF sy-subrc = 0.
"do stuff with <any_wa>...
ENDIF.
AFAIK, you have to do it the 'long way round':
FIELD-SYMBOLS: <any_field> TYPE any.
LOOP AT <any_tab> ASSIGNING <any_wa>.
ASSIGN COMPONENT 'MANDT' OF STRUCTURE <any_wa> TO <any_field>.
IF <any_field> <> 800.
CONTINUE.
ENDIF.
" do stuff with <any_wa> - you will have to assign <any_field> again to access fields.
ENDLOOP.
You are trying to beat a database in efficiency, it is a loosing battle.
Just go to SE11, select your table, go to technical settings and change the technical settings ( buffering & buffering type ), you do not require an object modification key for this. You can also make sure that the size category is correct.
You can use RTTS to get the table keys.
data table_name type string.
table_name = 'A002'.
" Dynamically create the table type
data the_table type ref to data.
create data the_table type table of (table_name).
" Use RTTS to get table keys
data typedescription type ref to cl_abap_tabledescr.
typedescription ?= cl_abap_tabledescr=>describe_by_data_ref( the_table ).
data keys type abap_table_keydescr_tab.
keys = typedescription->get_keys( ).
REPORT y_test_dynamic_table.
DATA: table_name TYPE string,
typedescription TYPE REF TO cl_abap_tabledescr,
keys TYPE abap_keydescr_tab,
ls_key TYPE abap_keyname.
table_name = 'ZYFRM_STG'.
" Dynamically create the table type
DATA the_table TYPE REF TO data.
CREATE DATA the_table TYPE TABLE OF (table_name).
" Use RTTS to get table keys
typedescription ?= cl_abap_tabledescr=>describe_by_data_ref( the_table ).
keys = typedescription->KEY.
loop at keys INTO ls_key.
***
ENDLOOP.