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
hendrik_brandes
Contributor
0 Kudos

Hello Horst,

 

thank you for your  blog-series about the great changes in the ABAP-Language. ( Shortly: WOW! ). Cannot wait until get my fingers dirty on it...

 

Extremly: The new way of constructing tables which are pre-filled directly after definition. No more macros, appends or other methods...

 

What about SY-SUBRC handling: Is this still the same? Or do we have to check it like in other languages?

 

Kind regards,

Hendrik

horst_keller
Product and Topic Expert
Product and Topic Expert

Ooooopsi!

 

Forgot to mention it, I added a line to the blog as follows:

 

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

 

Thanx for notifying.

SuhaSaha
Advisor
Advisor

Looks like i have to re-learn ABAP to get myself accustomed to 740

 

Is there any expression for READ TABLE ... TRANSPORTING?

 

BR,

Suhas

horst_keller
Product and Topic Expert
Product and Topic Expert
0 Kudos

Not yet and good point.

 

It is not recommended to write a lot of

 

itab[ ... ]-col1, itab[ ... ]-col2, ...

 

with the same itab and same line specification inside a program, You would read the same line again and again.

 

-> There are small traps you have to take care of.

hendrik_brandes
Contributor
0 Kudos

No problem 😉 There are a lot of changes, so this is just a small piece lost...

I will be looking forward to get a 740 instance and try out the new features!

 

Keep on remodel ABAP!

Hendrik

BMEIJS
Active Participant
0 Kudos

 

 

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

 

 

 


                   

Is this true for reading by index and reading by key? If yes, this means a lot of try-endtry's in my 7.4 code. Why the choice for raising an exception when reading by key?              

horst_keller
Product and Topic Expert
Product and Topic Expert

Sure, also for key access. What else can one do? Returning a Null value instead? Expressions that can be used in statements shouldn't influence the sy-subrc (bad enough that a functional method call sets sy-subrc for historical reasons).

 

There is one exception:

 

ASSIGN itab[ ... ] TO <fs>.

 

sets sy-subrc.

 

Maybe the new predicate function (I will come back to this later)

 

line_exists( itab[ ... ] )

 

that you can use behind IF is what you need (kind of short form for READ TABLE TRANSPORTING NO FIELDS with subsequent check of sy-subrc). Another new table function

 

line_index( itab[ ... ] )

 

returns 0 if the line is not found.

 

Otherwise, there's still the READ-statement you can use. Note, that table expressions are mainly made for usage at operand positions and not for standalone usage. Therefore, there's hardly another way then exceptions.

Former Member
0 Kudos

were is "group by" for internal tables?

Former Member
0 Kudos

Is it possible to use the addition "BINARY SEARCH"?

Regards, Stefan

horst_keller
Product and Topic Expert
Product and Topic Expert
0 Kudos

Documentation:

 

  • Unlike the statement READ TABLE with a free key specified, no binary searches can be forced for a table expression ...
former_member186584
Participant
0 Kudos

Can table expressions be used in operand positions where functional method call is present?

What I mean is: say "meth" is a functional method that has a RETURNING parameter as a table. Can I get the table row by doing the following:

 

table_row = meth( ..)[ 5 ].

 

Thanks for the great blog.

horst_keller
Product and Topic Expert
Product and Topic Expert

Hi,

 

1:  yes, but there are more positions, see documentation for a list of positions.

 

2: no, itab must be given directly (see the same documentation)

 

Best

 

Horst

ralf_wenzel_heuristika
Active Participant
0 Kudos

There is an expression, I don't understand:

 

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

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

 

This means:

    <itabline> = itab[ col1 = .... ].

works, if <itabline> is declared with data.

 

Can I use it with inline declaration?

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

does not work...

horst_keller
Product and Topic Expert
Product and Topic Expert
0 Kudos

Hello Ralf,

 

In fact you want to write something like

 

FIELD-SYMBOL(<fs2>) = <fs1>.

 

which is not possible. The LHS of an assignment is a declaration position for DATA(...) but not for FIELD-SYMBOL(...).

 

Declaration positions for FIELD-SYMBOL(...) are only behind ASSIGN and ASSIGNING.

 

So you have to write

 

ASSIGN itab[ ... ] TO FIELD-SYMBOL(<line>).

 

In fact, even specifying expressions behind ASSIGN is something special, because the position after ASSIGN is a result position that is reserved for writable expressions.

 

Best

 

Horst

ralf_wenzel_heuristika
Active Participant
0 Kudos

 


So you have to write


 


ASSIGN itab[ ... ] TO FIELD-SYMBOL(<line>).


 


Ahhhhh! *licht aufgeh

 

Thanks!

ralf_wenzel_heuristika
Active Participant
0 Kudos

In case of

 

<wa>-field2 = itab[ field1 = <wa>-field1 ]-field2.  

and itab has no line with field1 = <wa>-field1 (which means: <wa>-field2 has not been changed), no subrc is set and exception CX_SY_ITAB_LINE_NOT_FOUND occurs.

 

Am I right?

 

Or have I to a

 

if line_exists( itab[ field1 = <wa>-field1 ] ).

 

before?

 

And:

 

Does

 

<wa>-field2 = itab[ field1 = <wa>-field1 ]-field2.

 

choose an applicable secondary key of sorted table itab if it is defined? in READ table, I can say "WITH TABLE KEY name COMPONENTS comp1 comp2 comp3"....

horst_keller
Product and Topic Expert
Product and Topic Expert
0 Kudos

no subrc is set and exception CX_SY_ITAB_LINE_NOT_FOUND occurs.


Yes, an expression must not set sy-subrc because you simply cannot handle it at every expression position. From 7.40, SP08 on, you can also catch the exception by defining a default value: VALUE #( itab[  ... ] OPTIONAL|DEFAULT def ).

 


Does


 


<wa>-field2 = itab[ field1 = <wa>-field1 ]-field2.


 


choose an applicable secondary key of sorted table itab if it is defined?


 

No, a table expression does not choose a secondary key itself. As for READ TABLE and for the same reasons you have to do so yourself:

 

itab[ KEY keyname  COMPONENTS ...].

 

You find this also in the documentation ...

deno
Advisor
Advisor

Hello,

I see this blog-series as really cool. I like the new synax in 7.40 too.

 

Is there a new syntax which simplify the loop over a table. For example you have list of flights and you want to loop over only of subset of them (e.g. carrier Lufthansa) instead of all?

 

Best regards,

Mladen

horst_keller
Product and Topic Expert
Product and Topic Expert
0 Kudos

Hi Mladen,

 

With SP08 there will be a GROUP BY addition for LOOP AT (and also for FOR expressions) that will allow you to use freely defined grouping criteria for internal tables. Inside a LOOP with GROUP BY you can then use a new LOOP AT GROUP statement (or FOR IN GROUP expression) to process the subsets.  I guess, that's what you are looking for.

 

Best

 

Horst

ChristianGünter
Contributor
0 Kudos

Hi Horst,

 

i can't see the difference to ordinary where clauses.

Can you please elaborate on this a bit further?

 

Thanks.

 

Christian

 

Btw.: When will SP08 be released?

horst_keller
Product and Topic Expert
Product and Topic Expert
0 Kudos

Well, GROUP BY is a kind of convenience tool that replaces the old AT NEW ... constructs. You could also program the same funtionality by hand (WHEREs and IFs) but much more lengthy. One main benefit of GROUP by will be that you can define the grouping criteria by expressions or method calls with the table lines as arguments.

SP08 will be released very soon (next week or so ...).

 

Horst

ChristianGünter
Contributor
0 Kudos

Thanks for clarification.

 

I'm really looking forward to the ABAP News for Release 7.40 SP08 blog series

 

Christian

deno
Advisor
Advisor

Hi Horst,

 

Thanks for the update. I am impressed. It is really nice to see changes that happen so offen. Is there a place where we can see which improvement comes in which SP?

Best regards,

Mladen

horst_keller
Product and Topic Expert
Product and Topic Expert

In the news section of the  ABAP Kexword Documentation ...

 

Will be updated as soon as SP08 is available.

raphael_almeida
Active Contributor
0 Kudos

I know how you feel Suhas, i have to re-learn too... So many things to read...

Former Member
0 Kudos

Hi Horst,

 

If I use ASSIGN itab[...] TO FIELD-SYMBOL(<FS>) then it is not giving runtime error but if I use MOVE-CORRESPONDING itab[...] TO WA then I am getting runtime error if line does not exist in itab.

 

Why we need runtime error here as we need to write some lines of code for exception handling!!!  Idea is to make ABAP leaner but here it is making fattier.

 

Regards,

Sid

ipravir
Active Contributor
0 Kudos

Nice Blog

Thanks for sharing the valuable Information.

horst_keller
Product and Topic Expert
Product and Topic Expert
0 Kudos

Hi,

 

A table expression - as any expression - cannot set sy-subrc, because it is used at operand positions of statements.

 

You do not get a runtime error for table expressions in ASSIGN, since a dynamic ASSIGN handles the exception itself by setting sy-subrc - as it always did. MOVE-CORRESPONDING did never set sy-subrc - and it doesn´t do it now.

 

But meanwhile there is a workaround: Simply use the possibility to set deault values for table expressions, introduced with 7.40, SP08 - ABAP News for 7.40, SP08 - More for Internal Tables.


Best


Horst

horst_keller
Product and Topic Expert
Product and Topic Expert
Former Member
0 Kudos

Thanks Horst. I understood now.

TimMuchena
Participant
0 Kudos

Hi

 

How do we achieve a BINARY SEARCH using this syntax:

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

 

thank you

horst_keller
Product and Topic Expert
Product and Topic Expert
0 Kudos

see ABAP Keyword Documentation

 

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

What's about

 

 

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

 

This would work, I think, if KEYNAME is a secondary key of itab.

horst_keller
Product and Topic Expert
Product and Topic Expert
0 Kudos

Yes, that is alternative 3 - the table key variant - of the above link to the ABAP Keyword Documentation.

 

The statement cited above is for alternative 2 - the free key variant.

 

Note that a table expression has the same 3 variants as the READ TABLE statement: index access, free key accesss and table key access. But the free key variant can be supported by a secondary table key only for the READ TABLE statement not for the respective table expressions.

Faaiez
Advisor
Advisor
0 Kudos

Hi

 

Thanks for the post.

This is really useful.

Any idea how I can make accessing an internal table using a free key ignore case?

 

Example:

                    Internal table contents:

                    From     To

                    Aaa       bbb

                    AAA      BBB

                    aaa       Bbb

 

Read the internal table with key From = 'aaa'.

 

Should return all 3 rows.

 

Thanks

former_member186584
Participant
0 Kudos

Hi Faaiez,

 

Maybe you can use the statement - FIND ...IN TABLE....[{RESPECTING|IGNORING} CASE]

 

The exact statement should be constructed like:

 

FIND ALL OCCURRENCES OF 'aaa' IN TABLE itab IN CHARACTER MODE IGNORING CASE RESULTS DATA(result_tab).

 

Sincerely,

Muthukumar

horst_keller
Product and Topic Expert
Product and Topic Expert
0 Kudos

TYPES t_tab TYPE TABLE OF string WITH EMPTY KEY.

DATA(itab) = VALUE t_tab( ( `Aaa` ) ( `AAA` ) ( `aaa` ) ( `xxx` ) ).

DATA(jtab) = VALUE t_tab( FOR wa IN itab WHERE ( table_line CS 'aaa' ) ( wa ) ).

cl_demo_output=>display( jtab ).

Former Member
0 Kudos

So .. raise an exception (CX_SY_ITAB_LINE_NOT_FOUND) isn't less performative?

 

And in the end, just writing more...

 

(...)


TRY .

 

     DATA(st_charg) = it_charg[ 1 ].


(...)


   CATCH cx_sy_itab_line_not_found.

 

*........do nothing


ENDTRY.

(...)

horst_keller
Product and Topic Expert
Product and Topic Expert
0 Kudos

DATA(def) = VALUE line( id = 0 value = `not found` ).

 

...

 

DATA(result) = VALUE #( itab[ id = ... ] DEFAULT def ).

 

http://scn.sap.com/community/abap/blog/2014/10/06/abap-news-for-740-sp08--more-for-internal-tables

 

herzelhaimharel_gilor
Participant
0 Kudos

Hello Horst ,

 

it's a pleaser for me to read this .

 

I wonder what about performance issues with this new method of reading data from internal tables .

 

when I write my code i usually keep all the option on the table which means that I can read and write at the same time , like that :

 

field-symbols: <fs_tb_line> type mara.

 

READ TABLE lt_mara[] ASSINGING <fs_tb_line> with key k1 = 'some value'.

 

<fs_tb_line>-col1 = some_value   "write in

 

 

lv_some_var = <fs_tb_line>-col1 .

 

 

 

then the coming up question is whether the new method can support this form of table access ?

 

 

 

thank's for you quick answer

Very Sincerely ,

Harel Gilor.

horst_keller
Product and Topic Expert
Product and Topic Expert
0 Kudos

Hi Harel,

 

Table expressions can be used at LHS positions. And the section "Influencing the result" in the blog says that ASSIGNING is the standard variant for the intermediate result.

 

Therefore

 

lt_mara[ k1 = 'some value' ]-col1 = some_value.

 

is the same as

 

field-symbols: <fs_tb_line> type mara.

 

READ TABLE lt_mara[] ASSINGING <fs_tb_line> with key k1 = 'some value'.

 

<fs_tb_line>-col1 = some_value.

 

Best

 

Horst

TimMuchena
Participant
0 Kudos

Hi Horst

 

Is there a way of changing more than one line of an internal table using table expressions. I tried the above example that you gave and it only changes one line

 

Kind regards

horst_keller
Product and Topic Expert
Product and Topic Expert
0 Kudos

Hi,

 

There is no way of changing more than one line of an internal table using table expressions. A table expression itab[ ... ] is a shortcut for READ TABLE that addresses one line only.

 

Best

 

Horst

ralf_wenzel_heuristika
Active Participant
0 Kudos

I don't like standard tables, in most cases I used sorted tables with keys. But if I call a function module, which expects a table in TABLES expression (in most cases this FMs are from SAP), I have to send a standard table.

 

Is there a way to transfer a sorted table as standard table? Something like "conv #( sorted_table )....?

horst_keller
Product and Topic Expert
Product and Topic Expert
0 Kudos

Is there a way to transfer a sorted table as standard table?


 

 

In fact, it is:

 


CLASS demo DEFINITION.
  PUBLIC SECTION.
    TYPES
      itab TYPE STANDARD TABLE OF i
           WITH EMPTY KEY.
    METHODS:
      meth1 IMPORTING ptab TYPE itab,
      meth2.
ENDCLASS.


CLASS demo IMPLEMENTATION.
  METHOD meth1.
  ENDMETHOD.
  METHOD meth2.
    DATA jtab TYPE SORTED TABLE OF i
           WITH UNIQUE KEY table_line.
    "meth1( jtab ). <--- Syntax error
    meth1( CONV #( jtab ) ).
  ENDMETHOD.
ENDCLASS.


 

But not applicable to TABLES parameters of function modules, since no expressions can be passed to them. You need a helper variable for those.

ralf_wenzel_heuristika
Active Participant
0 Kudos

Horst Keller wrote:


But not applicable to TABLES parameters of function modules, since no expressions can be passed to them. You need a helper variable for those.


 

Hmpf - and this will not be changed in the future? I have this problem quite often....

horst_keller
Product and Topic Expert
Product and Topic Expert
0 Kudos

and this will not be changed in the future?


 

How? TABLES parameters are CHANGING parameters. You can't pass expressions to CHANGING parameters.

Former Member
0 Kudos


    meth1( CONV #( jtab ) ).


 


 

What are the implications for performance and/or memory usage? Does lazy copying occur?

horst_keller
Product and Topic Expert
Product and Topic Expert
0 Kudos

The conversion operator constructs an intermediate result that is passed to the method. It is a syntactical shortcut for creating a helper table, copying the original table, passing the helper table, deleting the helper table.

 

In cases, where a constructor operator works directly on an existing table, it is noted in the documentation, e.g. an itab as LHS of a VALUE-expression .

ralf_wenzel_heuristika
Active Participant
0 Kudos

Perhaps someone can help me with that example coding:

 

data: materials type sorted table of mara with unique key matnr.

data: salv type ref to cl_salv_table.

 

select * into materials from mara up to 30 rows.

 

if salv is not bound.

  cl_salv_table=>factory

    importing r_salv_table = salv

    changing t_table = materials.   "  <=== ERROR

endif.

 

Is there any way to find an ABAP statement, that converts the sorted table into a standard table? Something like

   changing conv standard( materials ). ?