Application Development Blog Posts
Learn and share on deeper, cross technology development topics such as integration and connectivity, automation, cloud extensibility, developing at scale, and security.
cancel
Showing results for 
Search instead for 
Did you mean: 
horst_keller
Product and Topic Expert
Product and Topic Expert

Table expressions with the syntax

... itab[ ... ] ...

are a new way for accessing table lines in operand positions. You can view a table expression simply as a short form of a READ TABLE statement. The result of a table expression is a single table line. All you have to know is the syntax that does the same as a given READ TABLE statement.

If a table line is not found, the exception CX_SY_ITAB_LINE_NOT_FOUND is raised. No sy-subrc from expressions, of course.

The operand positions where table expressions can be used are read positions but also some write positions where you can modify the resulting table line. Table expressions are LHS-expressions!

Specifiying the line

Index access using the primary index

The assignment of the table expression

wa = itab[ idx ].

does the same as

READ TABLE itab INDEX idx INTO wa.

Index access using a secondary index

The assignment of the table expression

wa = itab[ KEY key INDEX idx ].

does the same as

READ TABLE itab INDEX idx USING KEY key INTO wa.

Access using a free key

The assignment of the table expression

wa = itab[ col1 = ... col2 = ... ].

does the same as

READ TABLE itab WITH KEY col1 = ... col2 = ...  INTO wa.

Key access using a table key

The assignment of the table expressions

wa = itab[ KEY key col1 = ... col2 = ... ].

wa = itab[ KEY key COMPONENTS col1 = ... col2 = ... ].

do the same as

READ TABLE itab WITH TABLE KEY key COMPONENTS col1 = ... col2 = ...  INTO wa.

Influencing the result

With READ TABLE you can read into a work are, assign a field symbol or set a reference. The result of table expressions can be influenced accordingly.

  • ... itab[ ... ] ...
    as a rule works like READ TABLE ... ASSIGNING ... . The temporary result of the expression is a field symbol.

  • ... VALUE type( itab[ ... ] ) ...
    forces the expression to work like READ TABLE ... INTO ... . The temporary result of the expression is a data object.

  • ... REF type( itab[ ... ] ) ...
    forces the expression to work like READ TABLE ... REFERENCE INTO ... . The temporary result of the expression is a reference variable.

While the third case is important, if you want to work with references to table lines, the results of the other two cases are normally transparent to the user. You don't have to care how the intermediate result is represented internally. But there are some performance considerations. The same rules when to use what hold for table expressions as for READ TABLE. Therfeore, the syntax checker might kindly remind you from time to time to place the VALUE operator in front of a table expression (or to leave it away ...).

Chainings

The following chainings with table expressions are possible:

  • ... itab[ ...]-comp
  • ... struct-comp[ ... ] ...
  • ... itab[ ... ][ ... ] ...

and combinations of those

Fun example

TYPES:
  BEGIN OF struc1,
    col1 TYPE i,
    col2 TYPE i,
  END OF struc1,
  itab1 TYPE TABLE OF struc1 WITH EMPTY KEY,
  itab2 TYPE TABLE OF itab1 WITH EMPTY KEY,
  BEGIN OF struc2,
    col1 TYPE i,
    col2 TYPE itab2,
  END OF struc2,
  itab3 TYPE TABLE OF struc2 WITH EMPTY KEY.

DATA(itab) = VALUE itab3(
   ( col1 = 1  col2 = VALUE itab2(
                       ( VALUE itab1(
                           ( col1 = 2 col2 = 3 )
                           ( col1 = 4 col2 = 5 ) ) )
                       ( VALUE itab1(
                           ( col1 = 6 col2 = 7 )
                           ( col1 = 8 col2 = 9 ) ) ) ) )
   ( col1 = 10 col2 = VALUE itab2(
                       ( VALUE itab1(
                           ( col1 = 11 col2 = 12 )
                           ( col1 = 13 col2 = 14 ) ) )
                       ( VALUE itab1(
                           ( col1 = 15 col2 = 16 )
                           ( col1 = 17 col2 = 18 ) ) ) ) ) ).

* Reading the column with value 13 with READ TABLE statements

READ TABLE itab     INTO DATA(wa1) INDEX 2.
READ TABLE wa1-col2 INTO DATA(wa2) INDEX 1.
READ TABLE wa2      INTO DATA(wa3) INDEX 2.
DATA(num1) = wa3-col1.

* Reading the column with value 13 with chained table expressions

DATA(num2) = itab[ 2 ]-col2[ 1 ][ 2 ]-col1.

Unbelievable, is this still ABAP?

111 Comments
horst_keller
Product and Topic Expert
Product and Topic Expert
0 Kudos

Maybe second example under CONV?

ralf_wenzel_heuristika
Active Participant
0 Kudos

I added into  my coding:

 

types: materials_type type standard table of mara.

 

and changed the following line to

 

changing t_table = conv t_materials_type( materials ).

 

syntax check says, that I the value of a generic table can not be constructed.

 

Next question: In user command method after sorting the table (with the standard SAP button), do I have a problem? Because the table materials is type sorted and can not be sorted.

ChristianGünter
Contributor
0 Kudos

You can't construct data objects at changing position of method calls. So you have to use an auxiliary variable like this. And you have to fully specify the table key for constructor expressions.

 

 


TYPES: materials_type TYPE STANDARD TABLE OF mara
                      WITH DEFAULT KEY.

DATA(std_materials) = CONV materials_type( materials ).

cl_salv_table=>factory(
  IMPORTING
    r_salv_table  = DATA(alv)
  CHANGING
    t_table        = std_materials ).





ChristianGünter
Contributor
0 Kudos

The parameter t_table of the factory method is typed as "table" which means in fact standard table. So you can't pass anything else than a standard table.

 

 

ralf_wenzel_heuristika
Active Participant
0 Kudos

Works as suspected. Thanks for this information.

amadeusgrabmayer
Participant
0 Kudos

I found some restriction regarding the chaining of table expressions.

Maybe somebody can tell me what I'm doing wrong (or maybe it's not yet supported in ABAP - I'm on a System with SAP_BASIS 740 SP12). Maybe there is a special reason why this doesn't work, just would be interesting to know.

 

It seems that it is not possible to access attributes of a data-reference through a table expression chain.

 

     TYPES:

       BEGIN OF s_struct,

         field      TYPE string,

         r_material TYPE REF TO mara,

       END OF s_struct.

     TYPES:

       ts_table TYPE SORTED TABLE OF s_struct WITH UNIQUE KEY field.

 

     DATA table TYPE ts_table.

 

     DATA: matl_type TYPE mtart.

 

     matl_type = table[ field = `FIRST` ]-r_material->mtart.

 

 

Also dereferencing a generic data reference doesn't work in a table expression chain:

 

     TYPES:

       BEGIN OF s_data_struct,

         field  TYPE string,

         r_data TYPE REF TO data,

       END OF s_data_struct.

     TYPES:

       ts_data_table TYPE SORTED TABLE OF s_data_struct WITH UNIQUE KEY field.

 

     DATA data_table TYPE ts_data_table.

 

     FIELD-SYMBOLS: <table> TYPE ANY TABLE.

 

     ASSIGN data_table[ field = 'FIRST' ]-r_data->* TO <table>.


 

It seems that the operator is not recognized and therefore the component, the operator and the attribute/star are interpreted as the component name of the structure of the table.

horst_keller
Product and Topic Expert
Product and Topic Expert
0 Kudos

Hi Amadeus,

 

Yes, that's a restriction in release 7.40 and it was not documented that it should work.

 

The restriction is suspended in Release 7.50, see point 4.

 

The respective 7.50 documentation is enhanced compared to the 7.40 version.

 

Horst

amadeusgrabmayer
Participant
0 Kudos

Hi Horst,

 

thank you for clarifying!

Although it wasn't stated that it would work, I hoped so - because it makes the code much shorter for such cases.

 

Good to know that in the next release it is possible.

 

BR, Amadeus

0 Kudos

Hi Horst,

  Any plans to make similar improvements for assignment of structures components to field symbols?

 

Hypothetically so that something like this...


     ASSIGN COMPONENT <fs_acct_assgn_dimension>-dimension
     
OF STRUCTURE <fs_aco_address>
     
TO <fs_dimension_value>.

 

... could be something like this...

 

ASSIGN <fs_aco_address>[<fs_acct_assgn_dimension>-dimension] TO <fs_dimension_value>.

 

Or even better allow off-by one correction of INCREMENT when using SY-INDEX/SY-TABIX without creating a temporary variable. So this...

 

DATA: lv_inc TYPE int2.


DO 2 TIMES.
      lv_inc
= sy-index - 1.
     
ASSIGN <fs_override_dimension>-msgv3 INCREMENT lv_inc TO <fs_acct_assgn_dimension>.
...
ENDDO.

 

....could be rephrased as something like this...

 

ASSIGN <fs_override_dimension>-msgv3[sy-index - 1] TO <fs_acct_assgn_dimension>.

 

 




 


horst_keller
Product and Topic Expert
Product and Topic Expert
0 Kudos

Believe it or not, but I made the same proposal to development some time ago.

 

But for some reasons, it was turned down

former_member210296
Participant
0 Kudos

Would like to know that are those new expressions efficient to use where we use read statement with Binary search?

former_member186584
Participant
0 Kudos

Hi Anusha,

 

The documentation says the following:

"Unlike the statement READ TABLE with a free key specified, no binary searches can be forced for a table expression and it is not possible to specify explicit table key for optimizing searches using secondary keys."

ralf_wenzel_heuristika
Active Participant
0 Kudos

BINARY SEARCH ist so 80s and needs to sort the table (which needs time). Developers should use sorted tables with secondary keys for different access strategies.

 

In conclusion, you asked the wrong question.

horst_keller
Product and Topic Expert
Product and Topic Expert
0 Kudos

See discussion above  ...

former_member210296
Participant
0 Kudos

thanks !

ennowulff
Active Contributor

Would be cool if there was an expression to identify multiple result lines to a read:

TRY.
DATA(line) = itab[ field = 'AAA' ] EXPECTING CLEARNESS.
cl_demo_output=>display_text( 'Entry found' ).

CATCH CX_SY_ITAB_MULTIPLE_RESULTS.
cl_demo_output=>display_text( 'More than 1 entry!' ).

CATCH CX_SY_ITAB_LINE_NOT_FOUND.
cl_demo_output=>display_text( 'Entry does not exist' ).
ENDTRY.

 

david_kunz2
Advisor
Advisor
0 Kudos
Hi Horst!

I would like to have something like

field-symbol(<result>) = itab[ ... ].

 

However, this does not work, though ABAP should know the type of a line of itab.

Instead, I have to manually define the field-symbol including its type.

 

Can you comment on that?

 

Thanks and best regards

David
horst_keller
Product and Topic Expert
Product and Topic Expert
 
ASSIGN itab[ ... ] TO FIELD-SYMBOL(<fs>).
david_kunz2
Advisor
Advisor
0 Kudos
Thanks for the answer!

 

The 'problem' with this statement is, that the newly created structure is on the right of the expression. I find it a lot cleaner if all created structures are on the left.
horst_keller
Product and Topic Expert
Product and Topic Expert
 

Well yes, but
<fs> = itab[ ... ].

means value semantics where the itab line is assigned to the data object <fs> is pointing to.

We'd need to invent a new assignment operator to replace the ASSIGN statement. And inventing a new short meaningful operator in ABAP isn't that simple. I already tried to convince my dev buddies to have something like += to replace ADD, but ...
david_kunz2
Advisor
Advisor
0 Kudos

Yes I see.

Keep convincing your dev buddies to implement += and have an assign operator ?

former_member214867
Participant
0 Kudos
Hi Horst.

And why your dev buddies refuse to implement +=?

This is very conveniently for development.

 
Former Member
0 Kudos
Hi Horst,

 

When i use Table expressions instead of  Read Table with Binary search, I am facing ATC issue

saying 'Low performance on internal table' .

And also wanted to know what kind of searching technique table expressions use to fetch record

as i  guess linear search and how to implement searching techniques while using them to increase

performance.

 

Regards,

Naga
horst_keller
Product and Topic Expert
Product and Topic Expert
0 Kudos
BINARY SEARCH is not supported for table expressions. As an educative measure, ABAP wants you to use sorted keys instead.
UweFetzer_se38
Active Contributor
0 Kudos
As we can rewrite
READ TABLE flights INDEX 1 ASSIGNING FIELD-SYMBOL(<flight>).

as
ASSIGN flights[ 1 ] TO FIELD-SYMBOL(<flight>).

I thought we could replace
READ TABLE flights INDEX 1 REFERENCE INTO DATA(flight).

with
GET REFERENCE OF flights[ 1 ] INTO DATA(flight).

But unfortunatelly this is not (yet?)  possible. On my wishlist.
horst_keller
Product and Topic Expert
Product and Topic Expert

For that, you use the REF operator, see alternative 3 

UweFetzer_se38
Active Contributor
0 Kudos
(Mist), should have known this ...

Thank you.
former_member209914
Participant
0 Kudos

Hi Horst,

 

ASSIGN itab1[ KEY key col1 = ‘ABC’ ] TO <fs_wa1>.

Above statement is replacement of one single READ. If entry not found it is returning sy-subrc, No Dump. I am good here.

ASSIGN itab1[ KEY key col1 = ‘ABC’ col2 = itab2[ col1 = 123]-col2 ] TO <fs_wa1>.

Above statement is replacement of two READ statements. If itab2 don’t have entry with col1 = 123 I am getting DUMP, it is not returning sy-subrc. Do I need to use line_exists statement?. If entry found in itab2 but entry not found in itab1, I am not getting dump, it returns sy-subrc.

I am not interested to use line_exists statements as it sequentially search for the record two times if record found. Please correct me if I am wrong.

 

I am no more using READ statement in my program. Can completely forgot about READ statement?.

Recently I came across a situation I need to READ a data from internal table based on different cases(5 READ’s on diff columns). Do we need to declare one internal 5 diff secondary keys if we use table expressions?.

Thanks,

Vinod

 

 

 

 

RaminS
Participant
0 Kudos
As much as I love the new 7.4/7.5 notations, I still have to question this again:...

The READ TABLE statement seems quicker and safer to me that both the TRY/CATCH and the field-symbol assign methods

      assign lt_table[ seq to field-symbol(<ls_fs>).


      if sy-subrc 0.


        ls_rec <ls_fs>.


      endif.


vs.


      read table lt_table into ls_rec with key seq 3.


      check sy-subrc 0.


 

And we didn't have so many issues now with developers forgetting to put table access in TRY/CATCH when everyone was using READ TABLE. Is this another example of SAP making things more complicated inadvertently?

 
RaminS
Participant
0 Kudos
Why couldn't

    lt_table[ seq ]


simply return blank if not found?
horst_keller
Product and Topic Expert
Product and Topic Expert
0 Kudos
You simply miss the important fact that table expressions are, well, expressions that can be used in operand positions and can prevent unnecessary helper variables.
RaminS
Participant
0 Kudos
That is exactly my point. The programmer should not have to do VALUE + DEFAULT ' ', or TRY+CATCH, or ASSIGN+FIELD_SYMBOL  every time they want to access a table entry. It should be the default behaviour...

 

Instead of

   data(ls_rec1) = value #lt_table[ seq DEFAULT ''  ).


I should be able to just do

   data(ls_rec1) = lt_table[ seq ]


 

It is obvious that ls_rec1 will be null if seq = 3 does not exist. It's just natural, it's the way it works in other languages.

Am I wrong?

 
horst_keller
Product and Topic Expert
Product and Topic Expert
0 Kudos

Compare with strings. Internal tables as well as strings are dynamic data objects.


What happens if you access a position in a string that's not there? Sic.
RaminS
Participant
Yes, the way Abap handles strings is also out-dated. Accessing a non-existence position in a string should just return blank, or "undefined", or "null"... It should definitely not dump.

My point is, if we're now moving Abap towards more modern notations, we have to also modernize the behaviour.

Arrays in Javascript for example:

var cars = ["Saab", "Volvo", "BMW"]

Then cars[6] simply returns "undefined"

Same for strings:

var myCar = "BMW"

then myCar[6] is "undefined"

In Abap this causes a runtime error, and clients screaming at developers 😉

It's just not natural, we've modernized the notation but the behaviour remains out-dated. A lot of developers continue to have issues with this. I've seen it in multiple clients.

Just sharing my experience and opinion.

 

 
horst_keller
Product and Topic Expert
Product and Topic Expert
I appreciate your experience and opinion.

Well, yes then there's not much left to say. In fact, "we’ve modernized the notation but the behaviour remains out-dated". And I'm afraid, that's that. No booleans, no Null values (maybe Open SQL will do something about that), and so on.

Problem is, besides a few guys like you there are not too many stakeholders for a real face-lifted ABAP, especially not inside SAP and not in leading positions. I tried to address this for years but to no avail (hey, I'm only a documentation writer). Let's be happy that at least we have the expression enabled syntax, despite the flaws.
RaminS
Participant
0 Kudos
Agreed. Thanks for the insight.
Former Member
0 Kudos
Hi Horst,

 

Currently I am at GUI 7.5 and i tried using

wa = itab[ 1 ].

instead of READ

READ TABLE itab INDEX 1 INTO wa.

but is is giving me syntax error. Do you have any idea why?
horst_keller
Product and Topic Expert
Product and Topic Expert
0 Kudos
You really want to say GUI 7.5 ???
anmol_bhat112
Explorer
0 Kudos
Hi Former Member  Hi horst.keller ,

As Binary search is not possible with new syntax and you suggested to create sorted tables but we are not created Internal tables manually anymore right?

With the select query the table is generated automatically, is that table is sorted kind of...

If not what else we can do to improve reading internal table.

 

Thanks,

Anmol Bhat
RAF
Active Contributor
0 Kudos
Hi,

Unfortunately the following is not working

SET PARAMETER ID 'MAT' FIELD lt_table component = '0010' ]-matnr.

I have to use a variable in between, which is not a concise as i hopped.

 

Best Regards

Robert

 
horst_keller
Product and Topic Expert
Product and Topic Expert
0 Kudos
 

The operand position behind SET PARAMETER ID is not documented as an expression position.

As a rule, in the documentation you find for each operand position which kind of operands are allowed and there are even overview pages:

https://help.sap.com/http.svc/rc/abapdocu_752_index_htm/7.52/en-US/index.htm?file=abenexpression_pos...
amy_king
Active Contributor
0 Kudos
Hi Horst,

I read through all the comments and hopefully didn't miss an answer for this, but am I correct that this notation won't work for a field-symbol that points to an internal table. For example...
ASSIGN itab[ data_table 'DATA' TO FIELD-SYMBOL(<a_table>). " OK

DATA(my_value) = <a_table>[1]-field.  " illegal

Cheers,

Amy

 
horst_keller
Product and Topic Expert
Product and Topic Expert
0 Kudos
If the field symbol is typed as an internal table, it should work.

But in your example, the field symbol points to a line of table itab which most probably isn’t tabular but structured (as seen in the ASSIGN statement).
amy_king
Active Contributor
0 Kudos
Hi Horst,

Thanks. In my scenario, the field-symbol points to a table of parameter object references held by a Web Dynpro event (type ref to CL_WD_CUSTOM_EVENT). I can't find a way of making the <itab>[ index ]-field syntax work in this scenario but was able to achieve what I need with slightly less concise code...

FIELD-SYMBOLS <result_tab> TYPE ANY TABLE.

ASSIGN wdevent->parameters[ name 'RESULT_TAB' TO FIELD-SYMBOL(<ref_tab>).
ASSIGN <ref_tab>-value->TO <result_tab>.

LOOP AT <result_tab> ASSIGNING FIELD-SYMBOL(<line>).
   ASSIGN COMPONENT 'VARIANT' OF STRUCTURE <line> TO FIELD-SYMBOL(<variant>).
ENDLOOP" <line>



I'm trying to make the transition to the new 740 syntax and it's a lot to absorb. Your blogs have been very helpful.

Cheers.

 
horst_keller
Product and Topic Expert
Product and Topic Expert
 

Amy,

“I’m trying to make the transition to the new 740 syntax “, Like!

Therefore, I’m going back to your first example.

If everything is typed and coded properly, the syntax works, as the following example shows:
TYPES:
scarr_tab TYPE TABLE OF scarr WITH EMPTY KEY,
BEGIN OF scarr_struc,
key TYPE i,
scarr_tab TYPE scarr_tab,
END OF scarr_struc.
DATA
scarr_struc_tab TYPE HASHED TABLE OF scarr_struc WITH UNIQUE KEY key.

ASSIGN scarr_struc_tab[ key = 1 ]-scarr_tab TO FIELD-SYMBOL(<scarr_tab>).

DATA(carrid) = <scarr_tab>[ 1 ]-carrid.

Remember, that also in the old world, field symbols (or formal parameters) must be typed properly in order to carry out table operations.

Best

Horst
amy_king
Active Contributor
0 Kudos
Thanks Horst. 🙂

 
0 Kudos
Hi! Great post!

 

What if I want to do something like this:

itab1[] = itab2[ col1 = 'A' ]

 

I'm aware that "The result of a table expression is a single table line. " but what are my options?

The good old 'loop where'?

 

Thanks!
horst_keller
Product and Topic Expert
Product and Topic Expert
0 Kudos
It is not clear what you want to achieve.

The syntax shows the assignment of a stuctured table line to a table body. This is of course not possible.

Maybe it is an operator like REDUCE or VALUE, you are looking for?
srikar_poshetti
Discoverer
0 Kudos
Hi Horst Keller,

Thanks for an informative article!

I have a requirement where the READ statement  is

READ itab WHERE KEY = 123 TRANSPORTING NO FIELDS.

Now, how can we rewrite this above read statement using new syntax?

 

Regards,

Srikar Poshetti