Skip to Content
Author's profile photo Horst Keller

ABAP News for Release 7.40 – Table Expressions

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?

Assigned tags

      109 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Hendrik Brandes
      Hendrik Brandes

      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

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      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.

      Author's profile photo Hendrik Brandes
      Hendrik Brandes

      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

      Author's profile photo B. Meijs
      B. Meijs

       

       

      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?              

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      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.

      Author's profile photo Ralf Wenzel
      Ralf Wenzel

      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"....

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

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

      Author's profile photo Former Member
      Former Member

      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

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      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

      Author's profile photo Former Member
      Former Member

      Thanks Horst. I understood now.

      Author's profile photo Former Member
      Former Member

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

       

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

       

      BR,

      Suhas

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      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.

      Author's profile photo Raphael Pacheco
      Raphael Pacheco

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

      Author's profile photo Former Member
      Former Member

      were is "group by" for internal tables?

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author
      Author's profile photo Former Member
      Former Member

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

      Regards, Stefan

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      Documentation:

       

      • Unlike the statement READ TABLE with a free key specified, no binary searches can be forced for a table expression ...
      Author's profile photo Muthukumar Pasupathy
      Muthukumar Pasupathy

      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.

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      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

      Author's profile photo Ralf Wenzel
      Ralf Wenzel

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

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      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

      Author's profile photo Ralf Wenzel
      Ralf Wenzel

       

      So you have to write

       

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

       

      Ahhhhh! *licht aufgeh

       

      Thanks!

      Author's profile photo Mladen Droshev
      Mladen Droshev

      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

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      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

      Author's profile photo Christian Guenter
      Christian Guenter

      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?

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      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

      Author's profile photo Christian Guenter
      Christian Guenter

      Thanks for clarification.

       

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

       

      Christian

      Author's profile photo Mladen Droshev
      Mladen Droshev

      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

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

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

       

      Will be updated as soon as SP08 is available.

      Author's profile photo Praveer Sen
      Praveer Sen

      Nice Blog

      Thanks for sharing the valuable Information.

      Author's profile photo Timothy Muchena
      Timothy Muchena

      Hi

       

      How do we achieve a BINARY SEARCH using this syntax:

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

       

      thank you

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      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.

      Author's profile photo Ralf Wenzel
      Ralf Wenzel

      What's about

       

       

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

       

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

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      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.

      Author's profile photo Faaiez Sallie
      Faaiez Sallie

      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

      Author's profile photo Muthukumar Pasupathy
      Muthukumar Pasupathy

      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

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      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 ).

      Author's profile photo Former Member
      Former Member

      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.

      (...)

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      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

       

      Author's profile photo Harel Gilor
      Harel Gilor

      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.

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      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

      Author's profile photo Timothy Muchena
      Timothy Muchena

      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

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      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

      Author's profile photo Ralf Wenzel
      Ralf Wenzel

      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 )....?

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      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.

      Author's profile photo Ralf Wenzel
      Ralf Wenzel

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

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      and this will not be changed in the future?

       

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

      Author's profile photo Former Member
      Former Member

          meth1( CONV #( jtab ) ).

       

       

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

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      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 .

      Author's profile photo Ralf Wenzel
      Ralf Wenzel

      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 ). ?

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      Maybe second example under CONV?

      Author's profile photo Ralf Wenzel
      Ralf Wenzel

      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.

      Author's profile photo Christian Guenter
      Christian Guenter

      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 ).

      Author's profile photo Christian Guenter
      Christian Guenter

      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.

       

      2015-09-08 08_43_22-DV5(1)_010 Class Builder_ Class CL_SALV_TABLE Display.png

       

      2015-09-08 08_43_00-ABAP Keyword Documentation.png

      Author's profile photo Ralf Wenzel
      Ralf Wenzel

      Works as suspected. Thanks for this information.

      Author's profile photo Amadeus Grabmayer
      Amadeus Grabmayer

      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.

       

      MARA-reference_error.png

       

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


      DATA-reference_error.png

       

      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.

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      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

      Author's profile photo Amadeus Grabmayer
      Amadeus Grabmayer

      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

      Author's profile photo Kai Busse
      Kai Busse

      Hi Horst,

      for some reason the second example from Amadeus doesn't work for me even though I am on SAP_BASIS 7.50 and it's documented on the F1-Help.

       

      I get this error if I try to activate my method:

      A generic reference cannot be dereferenced (->) in the current statement.

       

      ..when trying to...

      FIELD-SYMBOLS: <l_any> TYPE any.

      ASSIGN table[ key = value ]-r_data->* TO <l_any>.

       

      Do you know what could cause this error to occur or do you know what I am doing wrong?

       

      Kind regards,

      Kai

      Author's profile photo Former Member
      Former Member

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

       

       

       


      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

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

       

      But for some reasons, it was turned down

      Author's profile photo Former Member
      Former Member

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

      Author's profile photo Muthukumar Pasupathy
      Muthukumar Pasupathy

      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."

      Author's profile photo Ralf Wenzel
      Ralf Wenzel

      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.

      Author's profile photo Former Member
      Former Member

      thanks !

      Author's profile photo Anmol Bhat
      Anmol Bhat

      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

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      See discussion above  ...

      Author's profile photo Enno Wulff
      Enno Wulff

      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.

       

      Author's profile photo David Kunz
      David Kunz

      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

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

       

      ASSIGN itab[ ... ] TO FIELD-SYMBOL(<fs>).
      Author's profile photo David Kunz
      David Kunz

      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.

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

       

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

      Author's profile photo David Kunz
      David Kunz

      Yes I see.

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

      Author's profile photo Виктор Избитский
      Виктор Избитский

      Hello from 2020. The += operator is implemented :^)

      Author's profile photo Alexander K
      Alexander K

      Hi Horst.

      And why your dev buddies refuse to implement +=?

      This is very conveniently for development.

       

      Author's profile photo Former Member
      Former Member

      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

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      BINARY SEARCH is not supported for table expressions. As an educative measure, ABAP wants you to use sorted keys instead.

      Author's profile photo Uwe Fetzer
      Uwe Fetzer

      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.

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

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

      Author's profile photo Uwe Fetzer
      Uwe Fetzer

      (Mist), should have known this ...

      Thank you.

      Author's profile photo Dmitry Iudin
      Dmitry Iudin

      but they are not equivalent, right? the assign statement is not dumping whereas the ref statement will dump

      I would not actually mind, but the SAPs own style-guides on github are currently recommending to use fields symbolds only in case of  dynamic access and in general prefer references. It seems that this is another exception to this rule

        DATA lt_sflight TYPE STANDARD TABLE OF sflight WITH EMPTY KEY.
      
        "assigning  has full equivalent with table expressions
        READ TABLE lt_sflight ASSIGNING FIELD-SYMBOL(<ls_sflight>) INDEX 1.
        ASSIGN lt_sflight[ 1 ]-carrid TO FIELD-SYMBOL(<lv_carrid>).
      
        "reference into does not have full equivalent
        READ TABLE lt_sflight REFERENCE INTO DATA(ls_sflight) INDEX 1."this is safe to use
      *  get REFERENCE OF lt_sflight[ 1 ]-carrid into DATA(lv_carrid). <<-- this is not syntactically possible
        DATA(lv_carrid) = REF #( lt_sflight[ 1 ]-carrid ). "<<-- this dumps due to table begin empty

       

      Author's profile photo Vinodkumar Tarlana
      Vinodkumar Tarlana

      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

       

       

       

       

      Author's profile photo Ramin Shafai
      Ramin Shafai

      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?

       

      Author's profile photo Ramin Shafai
      Ramin Shafai

      Why couldn't

          lt_table[ seq ]

      simply return blank if not found?

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      It can

      https://help.sap.com/http.svc/rc/abapdocu_752_index_htm/7.52/en-US/index.htm?file=abentable_exp_optional_default.htm

      Author's profile photo Ramin Shafai
      Ramin Shafai

      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?

       

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      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.

      Author's profile photo Ramin Shafai
      Ramin Shafai

      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.

       

       

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      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.

      Author's profile photo Ramin Shafai
      Ramin Shafai

      Agreed. Thanks for the insight.

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      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.

      Author's profile photo Former Member
      Former Member

      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?

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      You really want to say GUI 7.5 ???

      Author's profile photo Robert Forster
      Robert Forster

      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

       

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

       

      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_positions_read.htm

      Author's profile photo Amy King
      Amy King

      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

       

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      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).

      Author's profile photo Amy King
      Amy King

      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.

       

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

       

      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

      Author's profile photo Amy King
      Amy King

      Thanks Horst. 🙂

       

      Author's profile photo Luiz Felipe Martin
      Luiz Felipe Martin

      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!

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      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?

      Author's profile photo Srikar Poshetti
      Srikar Poshetti

      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

       

       

      Author's profile photo Sandra Rossi
      Sandra Rossi

      You should better post the question in the forum.

      Author's profile photo J. Graus
      J. Graus
      CHECK line_exists( itab[ key = 123 ] ).

       

      Author's profile photo saravana vel
      saravana vel

      Hello Mr. Horst,

      I have a condition/situation where in i would want to clear the contents of a few columns in the table, from a particular row to the last row of the table,however, with the new syntax, i am able to achieve it only from the said line. Also, the rows prior to the said line disappear.

      For example, i would want to clear column3, 4 and 5 from the 6th row to the last row(lets say for example 48th row), in this case, the behavior of the new syntax is as below,

      Table contains only 42 entries (the first 6 entries are discarded in the newly constructed table).

      The traditional ABAP code is as below:

      LOOP AT lt_poc ASSIGNING FIELDSYMBOL(<fs1>FROM lv_tabindex TO lv_maxperiod -1.              CLEAR <fs1>-revenue_recognition,
      <fs1>-poc_percent.
      ENDLOOP.

      ABAP.4 code is as below:

                  DATA(lt_temppoc) = VALUE tt_poc( FOR lspoc IN lt_poc FROM lv_tabindex TO lv_maxperiod - 1
                                         INDEX INTO index
                                         LET base = VALUE ty_poc( revenue_recognition = ' '
                                        poc_percent = ' ' )
                                        IN ( CORRESPONDING #( BASE ( base ) lspoc EXCEPT 

                                     revenue_recognition

                                     poc_percent
      ) ) ).

       

      Request you to please let me know what am i missing/addition(syntax) that needs to be added for retaining my entries prior to the change.

      Author's profile photo Sebastian Koitka
      Sebastian Koitka

      Hi,

      not sure if it is a good idea to post this as a comment, but let's see if anybody reacts, otherwise I need to find another place 😀

      Is it planned to have a syntax warning for missing catch of CX_SY_ITAB_LINE_NOT_FOUND after a table expression?

      I think it is exactly the same as a missing Catch of exceptions when calling a method that has raising clauses.

      It would help developers a lot, IMHO.

       

      Gruß,

      Sebastian

      Author's profile photo J. Graus
      J. Graus

      Hello

      What is the table expression variant of below code ?

      DATA:
        lt_field TYPE SORTED TABLE OF dummy WITH UNIQUE DEFAULT KEY,
        lv_field TYPE dummy.
      
      lt_field = VALUE #( ( 'X' ) ).
      READ TABLE lt_field FROM 'X' INTO lv_field.

      Regards

      Author's profile photo Sandra Rossi
      Sandra Rossi
      lv_field = lt_field[ table_line = 'X' ].