... FOR ALL ENTRIES IN @itab WHERE ... col operator @itab-comp ...
Wirkung
Wenn vor dem Sprachelement WHERE der Anweisung SELECT einer
Hauptquery der Zusatz
FOR ALL ENTRIES angegeben ist, können die Komponenten comp
der dort angegebenen internen Tabelle itab innerhalb von sql_cond auf der rechten Seite eines
Vergleichsoperators in Vergleichen mit einer
Spaltecol verwendet
werden. Die angegebene Komponente comp muss zur Spalte col
kompatibel sein. Die interne Tabelle itab kann einen strukturierten oder einen elementaren Zeilentyp haben. Bei elementarem Zeilentyp ist für comp die
Pseudokomponentetable_line anzugeben. Dem Namen der internen Tabelle soll wie allen
Hostvariablen das Fluchtsymbol @ vorangestellt werden.
Der gesamte logische Ausdruck sql_cond
wird für jede einzelne Zeile der internen Tabelle itab ausgewertet.
Die Ergebnismenge der SELECT-Anweisung ist die Vereinigungsmenge der Ergebnismengen,
die sich aus den einzelnen Auswertungen ergeben. Mehrfach vorkommende Zeilen werden automatisch aus der Ergebnismenge entfernt, wofür der gesamte Zeileninhalt betrachtet wird.
Wenn die interne Tabelle itab leer ist, wird die gesamte WHERE-Bedingung
ignoriert. D.h. es werden alle Zeilen der Datenbanktabelle berücksichtigt und nach Entfernung der mehrfach vorkommenden Zeilen in die Ergebnismenge gestellt.
Der logische Ausdruck sql_cond
der WHERE-Bedingung kann über AND und
OR aus verschiedenen logischen Ausdrücken zusammengesetzt sein. Wenn FOR ALL ENTRIES angegeben ist, muss es aber mindestens einen
Vergleich mit einer Spalte der internen Tabelle itab geben, der statisch oder dynamisch angegeben werden kann.
Bei Verwendung des Zusatzes FOR ALL ENTRIES gelten folgende Einschränkungen im Zusammenspiel mit anderen Zusätzen:
Der Zusatz FOR ALL ENTRIES ist nur vor WHERE-Bedingungen
einer eigenständigen SELECT-Anweisung oder in der
Hauptquery hinter OPEN CURSOR möglich, wenn dort keine allgemeinen Tabellenausdrücke mit WITH definiert werden.
Der Zusatz FOR ALL ENTRIES kann nicht zusammen mit dem Zusatz SINGLE verwendet werden.
Der Zusatz FOR ALL ENTRIES kann nicht zusammen mit SQL-Ausdrücken verwendet werden.
Der Zusatz FOR ALL ENTRIES kann nicht zusammen mit UNION verwendet werden.
Der Zusatz FOR ALL ENTRIES soll nicht zusammen mit dem Zusatz GROUP BY verwendet werden. Der Zusatz GROUP BY hat bei Verwendung von FOR ALL ENTRIES keine Wirkung.
In einer SELECT-Anweisung mit FOR ALL ENTRIES
kann der Zusatz ORDER BY
nur mit dem Zusatz PRIMARY KEY verwendet und dadurch nur auf eine einzige
Tabelle oder View zugegriffen werden. In der SELECT-Liste
müssen in diesem Fall alle Spalten des Primärschlüssels außer der Mandantenspalte mandantenabhängiger Tabellen enthalten sein.
In einer SELECT-Anweisung mit FOR ALL ENTRIES können keine Pfadausdrücke verwendet werden.
Wenn der Zusatz FOR ALL ENTRIES verwendet wird, sollten in der SELECT-Liste keine Datenbankfelder der eingebauten Typen STRING und RAWSTRING
sowie LCHR und LRAW vorkommen. Diese Datentypen verhindern das Entfernen mehrfach vorkommender Zeilen
auf dem Datenbanksystem. Die Zeilen werden erst auf dem Applikationsserver aus der Ergebnismenge entfernt
. Die Angabe solcher Felder in der SELECT-Liste führt zu einer durch ein Pragma ausblendbaren Warnung von der Syntaxprüfung.
Die interne Tabelle itab wird einmal pro Query ausgewertet. Eine Änderung
des Inhalts der internen Tabelle in einer SELECT- oder WITH-Schleife hat keinen Einfluss auf den logischen Ausdruck.
Hinweise
Hinter FOR ALL ENTRIES und hinter INTO kann die gleiche interne Tabelle angegeben werden. Der Inhalt der Tabelle wird von
FOR ALL ENTRIES ausgewertet und dann von der INTO-Klausel überschrieben.
Der Vergleich mit einer Spalte der internen Tabelle kann auch in der WHERE-Bedingung einer
Subquery für die gleiche Datenquelle durchgeführt werden.
Bezüglich mehrfach vorkommender Zeilen in der Ergebnismenge wirkt der Zusatz FOR
ALL ENTRIES so, als sei der Zusatz DISTINCT
in der Definition der Selektionsmenge angegeben. Im Unterschied zu DISTINCT
werden die Zeilen aber nicht immer vom Datenbanksystem sondern unter Umständen erst auf dem Applikationsserver
aus der Ergebnismenge entfernt. Die mehrfachen Zeilen werden dann vom Datenbanksystem entfernt, wenn
die SELECT-Anweisung als eine einzige SQL-Anweisung an das Datenbanksystem
übergeben werden kann und dabei der Zusatz DISTINCT unterstützt
wird. Falls die SELECT-Anweisung auf mehrere SQL-Anweisungen verteilt übergeben
werden muss oder wenn Spalten der Typen STRING und RAWSTRING sowie LCHR und LRAW in der SELECT-Liste angegeben sind, findet die Verdichtung auf dem Applikationsserver statt.
Wenn mehrfache Zeilen erst auf dem Applikationsserver entfernt werden, werden in manchen Konstellationen
alle durch die WHERE-Bedingung spezifizierten Zeilen an eine interne Systemtabelle übergeben und in dieser verdichtet. Die
maximale Größe dieser Systemtabelle
ist wie die normaler interner Tabellen beschränkt. Insbesondere wird die Systemtabelle immer
benötigt, wenn gleichzeitig einer der Zusätze
PACKAGE SIZE oder UP
TO, OFFSET verwendet wird. Diese wirken dann nicht auf die Menge
der vom Datenbankserver an den Applikationsserver übergebenen Zeilen, sondern werden erst für
die Übergabe der Zeilen von der Systemtabelle an den eigentlichen Zielbereich verwendet. Wenn
die maximale Größe der internen Systemtabelle überschritten wird, kommt es zu einem Laufzeitfehler.
Der Zusatz FOR ALL ENTRIES umgeht die
Tabellenpufferung für
Tabellen mit generischer Pufferung, wenn die Bedingung hinter FOR ALL ENTRIES verhindert, dass genau ein generischer Bereich exakt spezifiziert wird.
In allen anderen Fällen wird die Tabellenpufferung verwendet und der Zusatz FOR ALL ENTRIES kann eine performantere Alternative für
Join-Ausdrücke darstellen.
Es wird dringend empfohlen, vor einer Verwendung einer internen Tabelle itab
hinter FOR ALL ENTRIES sicherzustellen, dass die interne Tabelle nicht initial
ist. Bei einer initialen internen Tabelle werden unabhängig von eventuellen weiteren Bedingungen
hinter WHERE alle Zeilen von der Datenbank gelesen, was in aller Regel nicht gewünscht ist.
Dass bei leerer interner Tabelle itab die gesamte WHERE-Bedingung ignoriert wird, betrifft bei automatischer
Mandantenbehandlung nicht die implizite
WHERE-Bedingung für den aktuellen oder mit USING CLIENT angegebenen Mandanten. Es werden also nur alle Daten des
aktuellen Mandanten gelesen. Wenn die automatische Mandantenbehandlung mit CLIENT SPECIFIED abgeschaltet wird, gibt es keine implizite WHERE-Bedingung
für den Mandanten. Eine dann explizit für die Mandantenspalte angegebene WHERE-Bedingung
wird bei leerer interner Tabelle itab mit der gesamten Bedingung ignoriert und es werden die Daten aller Mandanten gelesen.
Auslesen von Flugdaten für eine vorgegebene Abflugstadt. Die entsprechenden Fluggesellschaften
und Flugnummern werden zuerst in eine interne Tabelle entry_tab gestellt,
die in der WHERE-Bedingung der folgenden SELECT-Anweisung
ausgewertet wird. Diese Selektion könnte mit einem Join in der FROM-Klausel auch in einer einzigen SELECT-Anweisung
erfolgen. Beachten sie, dass vor der Ausführung der SELECT-Anweisung
mit FOR ALL ENTRIES sichergestellt wird, dass die Tabelle entry_tab nicht initial ist.
DATA city TYPE spfli-cityfrom VALUE 'FRANKFURT'. cl_demo_input=>request( CHANGING field = city ).
SELECT carrid, connid FROM spfli WHERE cityfrom = @( to_upper( city ) )
INTO TABLE @DATA(entry_tab).
IF entry_tab IS NOT INITIAL.
SELECT carrid, connid, fldate FROM sflight
FOR ALL ENTRIES IN @entry_tab WHERE carrid = @entry_tab-carrid AND
connid = @entry_tab-connid
ORDER BY PRIMARY KEY INTO TABLE @DATA(result_tab). cl_demo_output=>display( result_tab ). ENDIF.
Beispiel
Verwendung von FOR ALL ENTRIES mit leerer interner Tabelle. Es werden alle
Zeilen der Datenbanktabelle berücksichtigt. Die Anzahl gelesener Zeilen ist in der ersten
SELECT-Anweisung in aller Regel aber kleiner als in der zweiten, da nur eine Spalte gelesen wird
und dadurch mehr mehrfach vorkommende Zeilen entfernt werden können. Die zweite SELECT-Anweisung
stellt dagegen alle Zeilen der Datenbanktabelle in die Ergebnismenge, da deren Struktur den gesamten Tabellenschlüssel abdeckt.
DATA carriers TYPE TABLE OF scarr.
SELECT carrid, connid FROM spfli
FOR ALL ENTRIES IN @carriers WHERE carrid = @carriers-carrid
INTO TABLE @DATA(result1). cl_demo_output=>write( result1 ).
SELECT carrid FROM spfli FOR ALL ENTRIES IN @carriers
WHERE carrid = @carriers-carrid INTO TABLE @DATA(result2). cl_demo_output=>display( result2 ).