Der Schlüsselbefehl Read table im neuen ABAP mit Tabellenausdrücken
Siehe Neues ABAP (ab Release 7.40).
Siehe Kategorie: Neues ABAP.
Siehe Prädikatfunktion LINE EXISTS.
Warum Tabellenausdrücke statt READ TABLE
Ab der ABAP-Version 7.40 gibt es auch weiter entwickelte Alternativen zu "Read table", indem in eckigen Klammern "[[ <tabellenzeile> ]]" die Tabellenzeile angesprochen wird mit einem sogenannten "Tabellenausdruck".
DATA (lv_ziel) = itab[ 5 ]-tiefestruktur[ 1 ]-spalte1.
Dieser Tabellenausdruck kann als Operantenteil von anderen Anweisungen genutzt werden und führt insofern zu kompakteren und performanteren Coding. Tabellenausdrücke können auch ineinander geschachtelt sein und insofern können tiefe Strukturen damit gelesen werden.
Es kann eine Zeile oder auch genau ein Feld einer Zeile gelesen werden.
Lesen Tabellenzeile mit Index
Alte Syntax mit "Read table index"
Um eine interne Tabelle zu lesen, wird klassisch der Schlüsselbefehl "Read table index .." genutzt.
READ TABLE itab INDEX lv_index INTO wa.
Um dann ein Feld einer anzusprechen: Die Zeile der Tabelle wird gelesen und dann aus der Struktur das Feld angesprochen und der Zielvariablen zugewiesen.
READ TABLE itab INDEX lv_index INTO wa. lv_feld = wa-feld.
Neue Syntax mit "itab[ index ]"
Erste Zeile wird gelesen mit "[ index ]". Zwischen dem eckigen Klammern und dem Zeilenindex steht jeweils ein Leerzeichen.
Data: ls_sflight type sflight.
ls_sflight = lt_sflight[ 1 ].
Bei einer Zuweisung zu einem Field-Symbol
Assign lt_sflight[ 1 ] to <fs_sflight>.
Man kann auch gleich lediglich ein Feld der Struktur zuweisen, was sehr elegant ist
Data: lv_carrid type sflight-carrd.
lv_carrid = lt_sflight[ 1 ]-carrid.
Wenn die Zeile nicht gefunden wird, wird die Exception CX_SY_ITAB_LINE_NOT_FOUND ausgelöst.
Folglich wird auch kein SY-SUBRC gesetzt. Entweder es wird eine Zeile gefunden (SY-SUBRC bleibt bei 0) oder es wird die Exception CX_SY_ITAB_LINE_NOT_FOUND ausgelöst.
Ab ABAP 7.40 SP08 die Möglichkeit mit dem Zusatz OPTIONAL abzufangen, dass keine Zeile gefunden werden kann, ohne das die Exception ausgelöst wird. Mit dem DEFAULT kann ein Wert an die Zielvariable übertragen werden für den Fall, dass keine Tabellenzeile gefunden wurde.
Neue Syntax mit "itab[ index ]" OPTIONAL
Es ist auch möglich ohne das mögliche Auslösen der Exception CX_SY_ITAB_LINE_NOT_FOUND zu arbeiten. Dann muss man allerdings mit dem Schlüsselwort VALUE arbeiten.
ls_sflight = VALUE #( lt_sflight[ 1 ] OPTIONAL ).
Wenn hier kein Datensatz in LT_SFLIGHT ist, dann wird kein Datensatz in die Struktur LS_SFLIGHT geschrieben und die Exception CX_SY_ITAB_LINE_NOT_FOUND wird nicht ausgelöst.
Vorsicht: kein Setzen von SY-SUBRC
Beim Tabellenausdruck wird SY-SUBRC nicht ungleich 0 gesetzt, sofern kein Datensatz gefunden wurde. Syntaxfehlerfrei, aber funktional nicht korrekt wäre
ls_sflight = VALUE #( lt_sflight[ 1 ] OPTIONAL ). if sy-subrc <> 0. ... endif.
Dann würde man eher folgendes Coding schreiben
ls_sflight = VALUE #( lt_sflight[ 1 ] OPTIONAL ). if ls_sflight is initial. ... endif.
Dann müsste man allerdings kritisch hinterfragen, ob bei einem Finden eines Datensatzes einer internen Tabelle auch wirklich immer die Zielstruktur ungleich initial sein muss. Sonst könnte es zu einer falschen Schlussfolgerung kommen. Dann sollte man ohne den Zusatz OPTIONAL arbeiten (mit der Ausnahme CX_SY_ITAB_LINE_NOT_FOUND) oder z. B. den klassischen READ TABLE verwenden
read table lt_sflight index 1 into ls_sflight. if sy-subrc <> 0. .. endif.
Lesen Tabellenzeile mit Bedingung
Struktur einer Tabelle lesen
Es können mehrere Felder innerhalb der Klammern abgefragt werden.
wa = itab[ feld1 = .. feld2 = .. ].
oder auch auf mehrere Zeilen verteilt
wa = itab[ feld1 = .. feld2 = .. ].
Bei einer Zuweisung zu einem Field-Symbol
Assign itab[ feld1 = .. feld2 = .. ] to <fs>.
Bei einer Zuweisung zu einem Field-Symbol mit inline-Deklaration
Assign itab[ feld1 = .. feld2 = .. ] to field-symbol(<fs>).
Feld einer Struktur einer Tabelle lesen
Sehr elegant ist in der neuen Syntax, dass man den Rückgabewert einer Abfrage einer internen Tabelle als Bedingung nutzen kann.
Die Bedingung steht in "[ <Bedingung> ]".
Hier wird von der internen Tabelle LT_SVAL mit dessen Feld TABNAME abgefragt ob hier "EKPO" steht und ob der Wert des Feldes VALUE initial ist.
IF lt_sval[ tabname = 'EKPO' ]-value IS INITIAL.
RETURN.
ENDIF.
oder hier wird der Warenempfänger aus der internen Tabelle LT_PARTN gelesen.
Data(lv_kunwe) = lt_partn[ PARTN_ROLE = 'WE' ]-PARTN_NUMB.
Keine Zeile gefunden - Ausnahme CX_SY_ITAB_LINE_NOT_FOUND
Man muss beim Tabellenausdruck mit der neuen ABAP-Syntax vorsichtig sein, wenn ein gesuchter Datensatz nicht vorhanden ist. Wenn der Datensatz nicht vorhanden ist, wird eine Ausnahme "CX_SY_ITAB_LINE_NOT_FOUND" ausgelöst und wenn man diese Ausnahme nicht abfängt, kommt es zu einem Laufzeitfehler.
cs_adressen-kunnr_mf = lt_vbpa[ parvw = 'MF' ]-kunnr.
Ausnahme
Hier war ein Partner "MF" nicht in der internen Tabelle LT_VBPA vorhanden.
Behandlung mit TRY-ENDTRY-Fehlerbehandlung
Man könnte die Ausnahme abfangen mit einer TRY-ENDTRY-Fehlerbehandlung.
try. cs_adressen-kunnr_mf = lt_vbpa[ parvw = 'MF' ]-kunnr. catch CX_SY_ITAB_LINE_NOT_FOUND. ... (Fehlerbehandlung)
endtry.
Tabellenausdruck mit Zusatz OPTIONAL
Eleganter ist ab ABAP 7.40 SP8 der Zusatz "optional". Der Befehl funktioniert allerdings nur in Kombination mit "VALUE".
cs_adressen-kunnr_mf = value #( lt_vbpa[ parvw = 'MF' ]-kunnr OPTIONAL )
Web-Links
Literatur
- ABAP Objects: Das neue umfassende Handbuch zu Konzepten, Sprachelementen und Werkzeugen in ABAP OO, 2016, von Felix Roth, S. 253 ff.