Application Development Discussions
Join the discussions or start your own on all things application development, including tools and APIs, programming models, and keeping your skills sharp.
cancel
Showing results for 
Search instead for 
Did you mean: 

CX_SY_ITAB_DUPLICATE_KEY with VALUE( )

SuhaSaha
Advisor
Advisor

Hello,

The exception is raised when i am trying to execute the following code snippet:

TYPES: ty_carrier TYPE HASHED TABLE OF sflight-carrid
       WITH UNIQUE KEY table_line.
DATA: carriers TYPE ty_carrier.
SELECT *
  FROM sflight
  INTO TABLE @DATA(flights).
IF sy-subrc = 0.
  carriers = VALUE #( BASE carriers
    FOR <wa> IN flights ( <wa>-carrid )
  ).
ENDIF.
cl_demo_output=>display_data(
    value = carriers
    name  = |Carriers|    " Name
).

As per the SAP documentation:

"Each inner parenthesis constructs one or more rows in accordance with the information in line_spec and inserts them into the new internal table in accordance with the rules for the statement INSERT ... INTO TABLE."

"lines constructed in line_spec for every iteration of the last FOR expression are inserted into the target table".

My understanding was that with each iteration of the FOR, the lines are inserted. So why is the behaviour differenent when i use the classical approach?

  LOOP AT flights ASSIGNING FIELD-SYMBOL(<flight>).
    INSERT <flight>-carrid INTO TABLE carriers.
  ENDLOOP.

What am i missing here?

BR,

Suhas

1 ACCEPTED SOLUTION

Sandra_Rossi
Active Contributor

I guess the behavior is correct but it's not documented (not yet, maybe tomorrow in 7.51 SP 1 😉 ) : in old programming, the insertion of one line in a unique index table can be checked with sy-subrc, while a mass insertion leads to exception because it's impossible to handle programmatically this situation. In iteration expressions, it's not possible to handle programmatically (if sy-subrc) a one-line insertion failure, so it's logic that it generates an exception too.

18 REPLIES 18

ŁukaszPęgiel
Contributor
0 Kudos

For me "loop at" is here bugged 😉 It should dump as well.

ceedee666
Active Contributor

Hi Suhas,

I think the following is relevant:

"Addition 1

... BASE itab

Effect

... If BASE is specified, the content of itab is assigned to the return value before the individual rows are inserted. If the character # is specified for the type of the return value and the type cannot be determined from the operand position of the constructor expression, the type of itab is used for this expression (if identifiable)."

Sound to my as if lines constructed by FOR are first inserted in a table specified by BASE. This most probably is no hash table and therefore the insert fails. Would be interested to get horst.keller view on this.

Christian


It's dumping without BASE addition as well 🙂 I'm on 7.40 SP5 here, so no BASE possibility

0 Kudos

I had given it a shot as well 😉

I understand that docu line to mean: before inserting new lines, take over the BASE lines, and the carriers BASE is empty at the beginning anyhow... The debugger after shortdump shows the the first line is inserted, so I assume that the thing is indeed inserting row by row...

The debugger after shortdump shows the the first line is inserted, so I assume that the thing is indeed inserting row by row...

You can also set the "Step size" option in the UI-debugger and check that! For the first iteration of the FOR expression the internal table carriers is filled with the first record.

ceedee666
Active Contributor
0 Kudos

That was exactly my first reaction 😉

SuhaSaha
Advisor
Advisor

Per SAP documentation:

When single rows are inserted, sy-subrc is set to 4 if a duplicate entry with respect to the primary key were to be produced; also, a handleable exception of the class CX_SY_ITAB_DUPLICATE_KEY is raised if a duplicate entry with respect to a secondary key would were to be produced.

Hence, no dump rather SY-SUBRC is set to 4.

ceedee666
Active Contributor

When you think of it in detail it's quite a mess, isn't it.

Sandra_Rossi
Active Contributor

I guess the behavior is correct but it's not documented (not yet, maybe tomorrow in 7.51 SP 1 😉 ) : in old programming, the insertion of one line in a unique index table can be checked with sy-subrc, while a mass insertion leads to exception because it's impossible to handle programmatically this situation. In iteration expressions, it's not possible to handle programmatically (if sy-subrc) a one-line insertion failure, so it's logic that it generates an exception too.

0 Kudos
In iteration expressions, it's not possible to handle programmatically (if sy-subrc) a one-line insertion failure, so it's logic that it generates an exception too.

Agreed.

But how can i resume the processing after the exception has been raised? That means if i want to get the list of unique carriers from the (internal)table of flights, i cannot use the FOR expression? 😐

It should be feasible with FOR ... GROUP BY ... I guess that next releases will bring new cool features 🙂

matt
Active Contributor

I converted Jānis B's comment at this point into an answer (below).

Private_Member_7726
Active Contributor

Something like this? 🙂

TYPES: ty_carrier TYPE HASHED TABLE OF sflight-carrid
       WITH UNIQUE KEY table_line.
DATA: carriers TYPE ty_carrier.
SELECT *
  FROM sflight
  INTO TABLE @DATA(flights).
IF sy-subrc = 0.
  carriers = VALUE #( 
    BASE carriers
    FOR GROUPS <gr> of <fs> in flights GROUP BY <fs>-carrid without members
    ( <gr> )
  ).
ENDIF.

cl_demo_output=>display_data(
    value = carriers
    name  = |Carriers|    " Name
).

0 Kudos

And it works, at least for building group key tables 🙂

This is IMO easier to grasp

  carriers = VALUE #( BASE carriers
    FOR GROUPS OF <fs> IN flights
      GROUP BY <fs>-carrid
    ( <fs>-carrid )
  ).

Hi Janis, Hi Sandra,

thanks for the solution! Tbh, i did not think about "grouping" the flights by carriers to get the unique carriers.

I use LOOP...GROUP BY regularly, but have not been able to wrap my head around the syntax of the FOR...GROUP BY expression.

Going back to the original question, this means that the behaviour of VALUE...FOR to construct internal tables is not properly documented.

SuhaSaha
Advisor
Advisor

I had thought about it, IMO this is because of the legacy ABAP code.

If the behaviour of INSERT...INTO TABLE would have been changed with the introduction of the FOR expression, then suddenly the old code would have started throwing exceptions. Isn't it?