10-25-2016 2:05 PM
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
10-25-2016 7:23 PM
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.
10-25-2016 2:59 PM
10-25-2016 3:06 PM
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
10-25-2016 3:14 PM
It's dumping without BASE addition as well 🙂 I'm on 7.40 SP5 here, so no BASE possibility
10-25-2016 3:34 PM
10-25-2016 5:36 PM
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...
10-25-2016 8:24 PM
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.
10-25-2016 3:07 PM
10-25-2016 3:32 PM
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.
10-25-2016 7:19 PM
10-25-2016 7:23 PM
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.
10-25-2016 8:21 PM
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? 😐
10-25-2016 8:38 PM
It should be feasible with FOR ... GROUP BY ... I guess that next releases will bring new cool features 🙂
10-26-2016 6:12 AM
I converted Jānis B's comment at this point into an answer (below).
10-25-2016 9:51 PM
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
).
10-25-2016 10:02 PM
10-25-2016 10:10 PM
This is IMO easier to grasp
carriers = VALUE #( BASE carriers
FOR GROUPS OF <fs> IN flights
GROUP BY <fs>-carrid
( <fs>-carrid )
).
10-26-2016 6:58 AM
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.
10-26-2016 7:04 AM
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?