I have a Problem with ABAP. I have the following code from a book:
METHOD make_reservation.
DATA: license_plate TYPE zcars-license_plate,
reservation_wa LIKE LINE OF reservation_tab,
reservation_num TYPE i,
mess TYPE string.
reservation_num = lines( reservation_tab ).
SELECT license_plate FROM zcars INTO (license_plate) WHERE category = category.
LOOP AT reservation_tab
TRANSPORTING NO FIELDS
WHERE license_plate = license_plate
AND NOT ( date_from > date_to OR date_to < date_from ).
ENDLOOP.
IF sy-subrc <> 0.
reservation_wa-reservation_id = reservation_num + 1.
reservation_wa-customer_id = customer.
reservation_wa-license_plate = license_plate.
reservation_wa-date_from = date_from.
reservation_wa-date_to = date_to.
INSERT reservation_wa INTO TABLE reservation_tab.
IF sy-subrc <> 0.
CONCATENATE license_plate ' reserved!' INTO mess.
MESSAGE mess TYPE 'I'.
ELSE.
MESSAGE 'internal error!' TYPE 'I' DISPLAY LIKE 'E'.
LEAVE PROGRAM.
ENDIF.
RETURN.
ENDIF.
ENDSELECT.
RAISE EXCEPTION TYPE zcx_no_car_available.
ENDMETHOD.
the problem is the line INSERT reservation_wa INTO TABLE reservation_tab. which does not run correctly and I always get sy-subrc <> 0. This results to the message "internal error!"
now my question: I tired to debug it, but I cant find the reason why this statement does not insert the data. How can I find out a detailed error message what went wrong with this SQL statement?
This snipplet tests for not equal 0:
INSERT reservation_wa INTO TABLE reservation_tab.
IF sy-subrc <> 0.
CONCATENATE license_plate ' reserved!' INTO mess.
MESSAGE mess TYPE 'I'.
ELSE.
MESSAGE 'internal error!' TYPE 'I' DISPLAY LIKE 'E'.
LEAVE PROGRAM.
ENDIF.
I always prefer to test for equality (that's easier to read). The similar coding for your code:
INSERT reservation_wa INTO TABLE reservation_tab.
IF sy-subrc = 0.
MESSAGE 'internal error!' TYPE 'I' DISPLAY LIKE 'E'.
LEAVE PROGRAM.
ELSE.
CONCATENATE license_plate ' reserved!' INTO mess.
MESSAGE mess TYPE 'I'.
ENDIF
In plain text: If the insert is successful (return code == 0), then report an error. If the insert is not successful, then inform about the correct reservation.
I don't know your exact requirement, but it seems you mix up the if/else branch in your code.
In ABAP, sy-subrc == 0 always means success. Your code seems to have a problem since the success is associated with any other value.
If you put a breakpoint in your code just before the insert, you'll be able to check that the insertion was a success.
You can check the possible return values of an instruction by putting the cursor on it and using the F1 key. this will launch the help/documentation.
Regards
Related
I am using the MESSAGE function and I want to know how I can find out if the message id exists or not.
For example:
I defined a message with the id "001" in my message class "test_message".
Then I call it like this: MESSAGE e001(test_messages) WITH 'Test'.
I retrieve it in another function from sy
When I do MESSAGE e000(test_messages) WITH 'Test'.
the values in sy are the same (except for the id of course). But in that case I want to change my process because I never created a message with the id 000.
I don't know where else to check if the id actually exists or not.
You can do a SELECT versus the table T100. If you can find your message, it exists :P
Something like
SELECT "just anything that fits your needs, with or without SINGLE
"UP TO 1 ROWS if you will not use the table's PK
FROM T100
INTO "field or fieldlist that fits your needs
WHERE ARBGB = "your ID
AND MSGNR = "your number.
"ENDSELECT. if you use UP TO 1 ROWS
IF sy-subrc = 0. "it exists
VXLozano's answer is appropriate but could be improved in performance by providing also the language field and retrieving only the TEXT field. Doing so allows you to add the "SINGLE" option and speed-up your message look-up.
SELECT SINGLE TEXT
FROM T100
INTO dummyfield
WHERE SPRSL = SY-LANGU
AND ARBGB = "Your ID"
AND MSGNR = "your Number".
IF sy-subrc = 0.
"the requested message in the message class exists for your current language
ENDIF.
I've had a dump recently,
DATA: gt_data TYPE SORTED TABLE OF ty_data WITH NON-UNIQUE KEY bukrs gaapnm,
...
lt_tabdel TYPE standard TABLE OF ty_data.
LOOP AT gt_data ASSIGNING <gf_data>.
IF <gf_data>-KANSW + <gf_data>-KAUFW = 0.
APPEND <gf_data> TO lt_tabdel.
ENDIF.
ENDLOOP.
IF lt_tabdel IS NOT INITIAL.
DELETE gt_data FROM lt_tabdel.
ENDIF.
And on the line with deleting table from internal table - i've had a dump: In statement
Convert object to integer
only numerical type data objects are supported at argument position
"object".
In the present case, operand "object" has the non-numerical data type "TABLE
OF TY_DATA". I just can't understand - why? Both of it had the same type... So, it will be great if you could provide some advice and a bit of explanation of error origins.
You have (inadvertently) used this variant of the DELETE statement that uses FROM and TO to specify indexes, i. e. numbers of table lines. In a sense, you are coding delete all lines in gt_data below the one identified by the line number in lt_tabdel, and the system goes belly-up when trying to convert the contents of lt_tabdel to an integer.
As far as I can see - i. E. if you've provided a complete code sample - this should be sufficient:
LOOP AT gt_data ASSIGNING <gf_data>.
IF <gf_data>-KANSW + <gf_data>-KAUFW = 0.
DELETE gt_data.
CONTINUE. " safety measure
ENDIF.
ENDLOOP.
For an explanation of the CONTINUE statement, check this answer.
IF lt_tabdel IS NOT INITIAL.
DELETE gt_data FROM lt_tabdel.
ENDIF.
* IF lt_tabdel IS NOT INITIAL.
DELETE TABLE gt_data FROM lt_tabdel.
ENDIF. *
Adding TABLE will help you.
Ok, i found solution. Delete - was the wrong command. So i used this one instead:
LOOP AT gt_data ASSIGNING <gf_data>.
IF <gf_data>-KANSW + <gf_data>-KAUFW <> 0.
append <gf_data> to lt_data.
ENDIF.
ENDLOOP.
gt_data[] = lt_data[].
Just filled another table and assigned it contents to the main table.
I get the following error: DBIF_RSQL_INVALID_RSQL CX_SY_OPEN_SQL_DB (Open SQL command is too big. Condition WHERE of the Open SQL command contains too many conditions). The error points to the following line:
select * from Z3T_MAILS into table t_full_mail UP TO 250 ROWS where ID in r_mid and (p_dat_clause).
Other parts of code:
DATA: p_dat_clause type STRING,
t_full_mail type Z3TT_MAILS,
r_mid type range of Z3E_MAIL_ID.
<...>
if not NOT_READED is initial.
p_clause = 'ISREAD = '''''.
endif.
if DATETO is initial.
p_dateto = DATEFROM.
else.
p_dateto = DATETO.
endif.
if not DATEFROM is initial or not DATETO is initial.
concatenate 'SEND_DATE >= ''' DATEFROM ''' and SEND_DATE <= ''' p_dateto '''' into p_dat_clause.
endif.
<...>
if MAILS is supplied or BODY is supplied or p_dat_clause ne ''.
if not r_mid[] is initial.
select * from Z3T_MAILS into table t_full_mail UP TO 250 ROWS where ID in r_mid and (p_dat_clause).
endif.
endif.
I am new to ABAP and would appreciate any help!
That error happens when you use a range/select-option that has too many entries for the database to handle. The solution to this is always dependent on the use, but in any case you have to limit the number of entries in the range.
In your case you only want up to 250 rows from the database anyway. So, if R_MID is filled with all rows containing a single ID you can check the number of lines in it (LINES( R_MID ) ) and limit it to 250 if there are more than that. In most systems this would get rid of the error.
I'm just guessing here but your range r_mid probably has hundreds of lines that look like this:
r_mid-sign = 'I'.
r_mid-option = 'EQ'.
r_mid-low = '123123123'.
r_mid-high = ''.
So instead you could store those IDs in an internal table. You even might be able to use the internal table you're looping over to fill r_mid in the first place.
Your date variables on the other hand are actually well suited to be declared as a single range:
r_date-sign = 'I'.
r_date-option = 'BT'.
r_date-low = datefrom.
r_date-high = dateto.
Also note the documentation about ranges.
Finally you can write your query as follows:
SELECT *
FROM z3t_mails
INTO TABLE t_full_mail
FOR ALL ENTRIES IN lt_mid
WHERE id EQ lt_mid-id
AND send_date IN r_date.
I have a database table named zrswheel .I entered 3 datas and want to show them on screen.Here s my code
REPORT ZRS_WHEEL.
TYPES:
BEGIN OF ty_zrswheel,
lv_brand TYPE c,
lv_dimension TYPE i,
lv_pressure TYPE i,
END OF ty_zrswheel.
DATA:
wa_zrswheel TYPE ty_zrswheel,
it_zrswheel TYPE TABLE of ty_zrswheel.
SELECT dimension pressure brand
FROM zrswheel
INTO TABLE it_zrswheel.
*WHERE ID=''.
IF sy-subrc NE 0.
write: 'There is an Error in retrieving data.'.
ELSE.
LOOP AT it_zrswheel INTO wa_zrswheel.
WRITE: wa_zrswheel-lv_dimension,wa_zrswheel-lv_brand,wa_zrswheel-lv_pressure.
NEW-LINE.
ENDLOOP.
ENDIF.
When I execute I get this error:
Runtime Errors : DBIF_RSQL_INVALID_RSQL
Except. CX_SY_OPEN_SQL_DB
What is the structure of your zrswheel?
Does it fit to your internal structure ty_zrswheel?
Without knowing the structure of zrswheel, nobody can help you.
The following is just a guess from my side.
It is very unusual to call fields in a structure like lv_.
So I think your zrswheel is defined as:
dimension type c,
brand type i
pressure type i
I think your report should look like:
REPORT ZRS_WHEEL.
DATA:
wa_zrswheel TYPE zrswheel,
it_zrswheel TYPE TABLE of zrswheel.
SELECT * FROM zrswheel INTO TABLE it_zrswheel.
LOOP AT it_zrswheel INTO wa_zrswheel.
WRITE: / wa_zrswheel-dimension,wa_zrswheel-brand,wa_zrswheel-pressure.
ENDLOOP.
IF sy-subrc NE 0.
write: 'Nothing found'.
ENDIF.
If you want only select an extract of zrswheel, then try:
REPORT ZRS_WHEEL.
TYPES:
BEGIN OF ty_zrswheel,
brand LIKE zrswheel-brand, "or lv_brand?
dimension LIKE zrswheel-dimension, "or lv_dimension?,
pressure LIKE zrswheel-pressure, "or lv_pressure?,
END OF ty_zrswheel.
DATA:
wa_zrswheel TYPE ty_zrswheel,
it_zrswheel TYPE TABLE of ty_zrswheel.
SELECT *FROM zrswheel
INTO corresponding fields of TABLE it_zrswheel.
LOOP AT it_zrswheel INTO wa_zrswheel.
WRITE: / wa_zrswheel-dimension,wa_zrswheel-brand,wa_zrswheel-pressure.
ENDLOOP.
IF sy-subrc NE 0.
write: 'There is an Error in retrieving data.'.
ENDIF.
Remark:
I'm not sure about the correct syntax of INTO CORRESPONDING FIELDS - please check the online help or wait for my update when I have a SAP-system to check the syntax)
Check your order of fields in the structure and in the select statement. Ensure the data types and length match for the fields .
I have an ABAP program to add records into the database. I would like to check if there is the same identification number in the database and if so raise an error message. The second thing, if user passes the id field as empty I would like to raise an error message.
MY METHOD TO ADD RECORDS INTO DATABASE
METHOD add.
DATA: IT_E TYPE TABLE OF ZE.
DATA:WA_E TYPE ZE.
IF sy-subrc EQ 0.
WA_E-ID = C_ID.
WA_E-NAME = C_NAME.
APPEND wa_e TO it_e.
INSERT ZE FROM TABLE it_e.
CALL FUNCTION 'POPUP_TO_DISPLAY_TEXT'
EXPORTING
TITEL = 'Message2'
TEXTLINE1 = 'Record Added Successfully.'.
IF sy-subrc <> 0.
CALL FUNCTION 'POPUP_TO_DISPLAY_TEXT'
EXPORTING
TITEL = 'Message2'
TEXTLINE1 = 'YOu cant use this id no'.
ENDIF.
DATA : ref_obj TYPE REF TO LCL_E.
MAIN PART
START-OF-SELECTION.
IF ra_add EQ 'X'.
IF pa_id eq space.
CALL FUNCTION 'POPUP_TO_DISPLAY_TEXT'
EXPORTING
TITEL = 'Message2'
TEXTLINE1 = 'You cant pass id field empty'.
else.
CREATE OBJECT ref_obj
EXPORTING
im_id = pa_id
im_name = pa_name
CALL METHOD ref_obj->add.
endif.
For the first issue I would recommend to make a SELECT with the key before the INSERT to ensure that record exists in table, if it does display the message else make the INSERT. For the second issue you should use "IF lv_data IS INITIAL".
1)You can make the field mandatory using the keyword OBLIGATORY.
PARAMETERS : pa_id type c OBLIGATORY.
2) Try to retrieve the record from database using the id.if the sy-subrc <> 0 then insert the record ,else raise the error message.