Delete field contents from the structure? - abap

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 = ''.

Related

use SELECT on internal table (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 ).

Concatenating strings in SAP Query

I'm creating a BAPI for SAP R/3. The equivalent in MSSQL of what I'm trying to write is this:
select
bkpf.BELNR,
bkpf.BUKRS,
bkpf.GJAHR,
bkpf.AWKEY
into
#tab
from
bkpf
where
exists ( select 1 from #n_tab n where CONCAT(n.BELNR, n.GJAHR) = bkpf.AWKEY )
;
But apparently Open Sql doesn't allow operations in queries. So for what I researched, the table I want to "join" must be retrieved to an in memory table, create a new column in a loop doing the operation and the compare with the #tab table. But I'm struggling with the syntax. What I have so far is something like this:
FUNCTION ZBAPI_TEST.
*"----------------------------------------------------------------------
*"*"Local Interface:
*"----------------------------------------------------------------------
select
bkpf~BELNR
bkpf~BUKRS
bkpf~GJAHR
bkpf~AWKEY
into ITAB_BKPF
from bkpf.
loop at ITAB_BKPF.
ITAB_BKPF-chkey = CONCATENATE BELNR GJAHR.
modify ITAB_BKPF.
endloop.
ENDFUNCTION.
But I'm getting the following errors.
Field "ITAB_BKPF" is unknown. It is neither in one of the
specified tables nor defined by a "DATA" statement.
Field "ITAB_BKPF-GJAHR" is unknown. It is neither in one of
the specified tables nor defined by a "DATA" statement.
Incorrect nesting: Before the statement "ENDFUNCTION", the
control structure introduced by "SELECT" must be concluded with
"ENDSELECT".
Incorrect nesting: Before the statement
"+END-OF-INCLUDE", the control structure introduced by "FUNCTION" must
be concluded with "ENDFUNCTION".
There's clearly an open statement. But I'm not really familiar with the language and don't know where the period is required or if I misplaced any closing statement. Other approach I saw online was with a construct SELECT..ENDSELECT:
FUNCTION ZBAPI_TEST.
*"----------------------------------------------------------------------
*"*"Local Interface:
*"----------------------------------------------------------------------
select
bkpf~belnr
bkpf~bukrs
bkpf~gjahr
bkpf~awkey
into corresponding fields
wa_bkpf
from bkpf.
wa_bkpf-chkey = concatenate belnr gjahr.
append wa_bkpf to itab_bkpf.
endselect.
ENDFUNCTION.
But this generate a new batch of errors:
Field "CORRESPONDING" is unknown. It is neither in one of the
specified tables nor defined by a "DATA" statement. Field
"WA_BKPF-CHKEY" is unknown. It is neither in one of the
specified tables nor defined by a "DATA" statement. Field "WA_BKPF"
is unknown. It is neither in one of the specified tables nor defined
by a "DATA" statement.
I suspect the solutions and examples I found online skip some part where they define some of the structures they use. But I don't really know how to do it. Can someone help?
EDIT:
The final code looks like that:
types: begin of t_bkpf,
belnr type belnr_d,
bukrs type bukrs,
gjahr type gjahr,
awkey type awkey,
chkey type string.
types: end of t_bkpf.
data: itab_bkpf type standard table of t_bkpf.
field-symbols: <wa> type t_bkpf.
select
BELNR
BUKRS
GJAHR
AWKEY
into corresponding fields of table ITAB_BKPF
from bkpf.
loop at ITAB_BKPF assigning <wa>.
CONCATENATE <wa>-BELNR <wa>-GJAHR into <wa>-chkey.
endloop.
manoftheyear.
Let me know if this works for you:
*** Definition of custom type.
TYPES: BEGIN OF ty_bkpf,
belnr TYPE bukrs,
bukrs TYPE belnr_d,
gjahr TYPE gjahr,
awkey TYPE awkey,
chkey TYPE string, " Replace with the type you need to use.
END OF ty_bkpf.
*** Definition of internal table of custom type.
DATA lt_bkpf TYPE STANDARD TABLE OF ty_bkpf.
*** Definition of field symbol (pointer) of custom type.
FIELD-SYMBOLS <lfs_bkpf> TYPE ty_bkpf.
*** Extraction of data from BKPF database table.
SELECT belnr bukrs gjahr awkey
FROM bkpf
INTO CORRESPONDING FIELDS OF TABLE lt_bkpf.
*** Checks if extraction was succesful.
IF sy-subrc IS INITIAL.
UNASSIGN <lfs_bkpf>.
*** Loop internal table...
LOOP AT lt_bkpf ASSIGNING <lfs_bkpf>.
*** ...and create value for field CHKEY.
CONCATENATE <lfs_bkpf>-belnr
<lfs_bkpf>-gjahr
INTO <lfs_bkpf>-chkey. " By using a pointer, there's no need to use MODIFY sentence.
ENDLOOP.
ENDIF.
Cheers.
You can use CONCAT directly on QUERY. Example:
SELECT SINGLE CONCAT( CONCAT( a~name1, a~name2 ), a~name3 )
FROM ( ( adrc AS a
INNER JOIN j_1bbranch AS j ON a~addrnumber = j~adrnr )
INNER JOIN t001w AS t ON j~cgc_branch = t~j_1bbranch
AND j~bukrs = #i_postab-bukrs
AND t~werks = #e_postab-prctr+4(4) )
INTO #e_postab-company_name.

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 ?

Given a field symbol pointing to a table, how do I assign it to a structure field symbol?

I have a field symbol <lt_something> which points to a table. This table has a single line as content. How do I assign that line in the table to a new field symbol, say <ls_something> ?
I tried :
READ TABLE <lt_something> INDEX 1 REFERENCE INTO <ls_something>.
But the above code dumps, what is the right approach to this problem?
You're mixing up field symbols and data references. Use either
DATA lr_foo TYPE REF TO something.
READ TABLE lt_something INDEX 1 REFERENCE INTO lr_foo.
lr_foo->bar = 'baz'.
or
FIELD-SYMBOLS <ls_foo> TYPE something.
READ TABLE lt_something INDEX 1 ASSIGNING <ls_foo>.
<ls_foo>-bar = 'baz'.
but do not merge the two ways.
Are you sure that your field symbol table is assigned before you perform your read? The general structure of your read table looks OK, but you should use ASSIGNING in your read statement:
FIELD-SYMBOLS: <lt_something> TYPE ANY TABLE,
<ls_something> TYPE ANY.
" ... blah blah presume you did some work on <lt_something>...
IF <lt_something> IS ASSIGNED.
READ TABLE <lt_something> INDEX 1 ASSIGNING <ls_something>.
" Check sy-subrc or <ls_something> IS ASSIGNED.
" Do work.
ENDIF.
The field-symbol needs to be the line type of the table, not the table itself.
DATA:
i_vbak type standard table of vbak.
FIELD-SYMBOLS:
<i_vbak> type vbak.
READ TABLE i_vbak ASSIGNING <i_vbak>.

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.