System fields — sy-subrc, sy-tabix, sy-index and friends¶
Level: 101 · newcomer
One line: sy is a structure the kernel keeps up to date — the current user, client, date, the last return code, the current loop row — and the three fields that cause bugs are sy-subrc (overwritten by the next statement that sets one), sy-tabix (the LOOP AT row) and sy-index (the DO pass), the last two of which are regularly confused.
The ones you will read¶
| Field | Holds | Set by |
|---|---|---|
sy-subrc |
return code of the last statement that sets one; 0 is success |
most statements |
sy-tabix |
current row index | LOOP AT, READ TABLE |
sy-index |
current pass number | DO, WHILE |
sy-dbcnt |
rows affected | Open SQL |
sy-datum, sy-uzeit |
date and time, user's zone, at program start | GET TIME refreshes |
sy-uname, sy-mandt, sy-langu |
user, client, logon language | logon |
sy-repid, sy-cprog |
this program; the calling program | runtime |
sy-batch |
X in a background job |
runtime |
sy-msgid, sy-msgno, sy-msgty, sy-msgv1…4 |
the last message, in pieces | MESSAGE, function modules |
sy-sysid, sy-host |
system ID, application server | runtime |
sy-fdpos |
offset of a CS/CA match |
comparison operators |
sy-uzeit is worth a second look: it is set when the program starts and does not tick. A job that logs sy-uzeit after two hours of work logs the start time. See GET TIME.
The rules¶
- Read
sy-subrcimmediately. AWRITE, a method call, aSELECT— nearly anything can reset it. Copy it into a variable when there is anything between the statement and the test. - Never assign to a
syfield. It compiles. It also lies to every statement that reads the field afterwards. sy-subrc = 0after a statement that does not set it means nothing. ALOOP ATsets it (4if the table was empty); an assignment does not.sy-tabixinside a nestedLOOPbelongs to the inner loop, and aREAD TABLEinside the loop overwrites it too.
z_kw_sy_fields.prog.abap — pasted here by tools/check_examples.py. Syntax-checked, never run: abaplint parses and type-checks it against the release in abaplint.json, but no system has produced output for it, so this page shows none.
REPORT z_kw_sy_fields.
" The fields nearly every program reads. The kernel sets them; assign to one
" yourself and you are lying to the next statement that reads it.
WRITE: / 'user ', sy-uname.
WRITE: / 'client ', sy-mandt.
WRITE: / 'language ', sy-langu.
WRITE: / 'program ', sy-repid.
WRITE: / 'system ', sy-sysid.
WRITE: / 'date/time', sy-datum, sy-uzeit.
WRITE: / 'batch? ', sy-batch.
TYPES ty_ints TYPE STANDARD TABLE OF i WITH EMPTY KEY.
DATA(lt_n) = VALUE ty_ints( ( 10 ) ( 20 ) ( 30 ) ).
" sy-tabix: the row index inside LOOP AT, and after a READ TABLE.
LOOP AT lt_n INTO DATA(lv_n).
WRITE: / 'tabix', sy-tabix, lv_n.
ENDLOOP.
" sy-index: the pass counter of DO and WHILE. A different field, and the
" one people read in a LOOP by mistake.
DO 2 TIMES.
WRITE: / 'index', sy-index.
ENDDO.
" sy-subrc: the return code of the LAST statement that sets one. Copy it
" straight away -- almost any statement in between can overwrite it.
READ TABLE lt_n INTO lv_n INDEX 99.
DATA(lv_rc) = sy-subrc.
WRITE: / 'read past the end ->', lv_rc.
" sy-dbcnt: rows affected by the last Open SQL statement.
SELECT carrid FROM scarr INTO TABLE @DATA(lt_carriers).
WRITE: / 'rows selected', sy-dbcnt, lines( lt_carriers ).
" sy-msg*: the last message, in pieces. See the MESSAGE page.
WRITE: / 'last message type [', sy-msgty, ']'.
If you are coming from another language¶
- C.
errno, with the same "read it now" rule and the same silent overwriting — except that ABAP sets it on success as well. - Shell.
$?issy-subrc;$USER,$HOSTNAMEanddateare the rest of the structure.
See also¶
READ TABLEand table expressions — the statement most often followed by a forgottensy-subrccheckLOOP ATandDOandWHILE—sy-tabixandsy-index, one eachMESSAGE— thesy-msg…fieldsGET TIME— refreshingsy-datumandsy-uzeit- Background jobs —
sy-batch