Mit dem ABAP-spezifischen Zusatz SINGLE ist die Ergebnismenge einer
Query einzeilig. Der Zusatz ist
möglich bei einer eigenständigen SELECT-Anweisung oder der
Hauptquery einer eigenständigen
WITH-Anweisung. Wenn SINGLE angegeben ist, öffnen diese Anweisungen beim Einlesen in einen nicht-tabellenartigen
Zielbereich keine mit
ENDSELECT bzw. ENDWITH abzuschließende Schleife und es kann keine interne Tabelle als
Zielbereich angegeben werden.
Falls die Selektion der SELECT-Anweisung genau eine Zeile umfasst, wird diese in die Ergebnismenge gestellt.
Falls die Selektion der SELECT-Anweisung mehr als eine Zeile umfasst, wird davon eine beliebige Zeile in die Ergebnismenge gestellt.
Der Zusatz SINGLE ist dafür vorgesehen, genau eine Zeile in eine
flache Struktur als
Arbeitsbereich auszulesen, ohne dass eine mit ENDSELECT
bzw. ENDWITH zu schließende Schleife geöffnet wird.
In der Regel soll die Zeile genau bestimmt sein und sie muss sie eindeutig in der WHERE-Bedingung spezifiziert sein, was in der Regel durch die Angabe von Vergleichswerten für den
Primärschlüssel der
Datenquelle geschieht. Es kommt zu einer Warnung von der
erweiterten Programmprüfung, wenn die Zeile nicht genau bestimmt ist.
Wenn die Zeile nicht eindeutig bestimmt wird, kann der Zusatz SINGLE
auch dafür verwendet werden, um festzustellen, ob eine entsprechende Zeile vorhanden ist. In diesem Fall muss die Warnung der erweiterten Programmprüfung durch ein
Pragma ausgeblendet werden.
Um einen unnötigen Transport von Daten ganz zu vermeiden, kann für diesen Zweck aber auch eine SELECT-Liste verwendet werden, die nichts als eine Konstante enthält (siehe
ausführbares Beispiel).
Eine SELECT-Anweisung mit dem Zusatz SINGLE ist
bei vollständig spezifizierter Zeile in aller Regel schneller als bei unvollständiger Spezifizierung der Zeile.
Die Ergebnismenge von SELECT-Anweisungen mit dem Zusatz SINGLE
ist die Gleiche wie mit dem Zusatz UP
TO 1 ROWS ohne Verwendung des Zusatzes ORDER BY.
Bei Verwendung des Zusatzes SINGLE entfällt die Notwendigkeit
der Anweisungen ENDSELECT, ENDWITH bzw. des Einlesens in eine interne Tabelle. Es können aber nicht alle Zusätze der SELECT-Anweisung verwendet werden.
Bei Verwendung des Zusatzes UP
TO 1 ROWS muss die Anweisung ENDSELECT
bzw. ENDWITH angegeben bzw. in
eine interne Tabelle eingelesen werden. Es kann aber der Zusatz ORDER BY angegeben werden.
Da eine SELECT-Anweisung mit dem Zusatz SINGLE
auf das Auslesen genau einer Zeile optimiert ist, ist sie in der Regel etwas schneller als mit dem Zusatz
UP TO 1 ROWS. Der Unterschied dürfte in der Praxis aber keine Rolle spielen. Es wird deshalb empfohlen,
den Zusatz SINGLE zu verwenden, um genau eine vollständig spezifizierte Zeile zu lesen,
den Zusatz UP TO 1 ROWS zu verwenden, um maximal eine Zeile einer Menge von selektierten Zeilen zu lesen.
Da der Zusatz ORDER BY
nicht zusammen mit SINGLE angegeben werden kann, ist es undefiniert, welche
Zeile einer nicht eindeutigen Selektion gelesen wird. Um die ausgelesene Zeile einer nicht eindeutigen
Selektion zu definieren, kann statt dessen der Zusatz
UP TO 1 ROWS mit dem Zusatz ORDER BY angegeben werden.
Wenn bei der Angabe von SINGLE in der INTO-KlauselLOB-Handles erzeugt werden, müssen
in der WHERE-Bedingung alle Primärschlüsselfelder
in mit AND verknüpften logischen Ausdrücken auf Gleichheit
überprüft werden. Falls dies nicht möglich ist, kann statt SINGLE
der Zusatz UP TO 1 ROWS verwendet werden.
Bei Verwendung des Zusatzes SINGLE bleiben nach einer
Erzeugung von LOB-Handles neben den
Lokatoren auch alle
Leseströme die bei Ausführung
der SELECT-Anweisung erzeugt werden, solange bestehen, bis sie explizit mit
einer ihrer Methoden oder implizit am Ende der aktuellen Datenbank-LUW geschlossen werden. In dieser
Zeit ist die zugehörige Datenbankoperation nicht abgeschlossen. Es wird empfohlen, alle LOB-Handles so früh wie möglich explizit zu schließen.
Beispiel
Auslesen der Zeile mit den Angaben zum Lufthansa-Flug 0400 aus der Datenbanktabelle SPFLI.
SELECT SINGLE * FROM spfli WHERE carrid = 'LH' AND
connid = '0400' INTO @DATA(wa).
Beispiel
Das Programm DEMO_SELECT_SINGLE_VS_UP_TO vergleicht die Performance von
SELECT-Anweisungen mit dem Zusatz SINGLE mit gleichwertigen
Anweisungen mit dem Zusatz UP TO 1 ROWS.
Zusatz
... FOR UPDATE
Wirkung
Der Zusatz FOR UPDATE setzt beim Lesen einer einzelnen Zeile mit SINGLE eine
Datenbanksperre in Form einer
Schreibsperre für
diese Zeile auf der Datenbank. Die SELECT-Anweisung wird in diesem Fall nur
dann ausgeführt, wenn in der WHERE-Bedingung
alle Primärschlüsselfelder in mit AND verknüpften logischen
Ausdrücken auf Gleichheit überprüft werden. Andernfalls ist die Ergebnismenge leer und sy-subrc wird auf 8 gesetzt.
Hinweise
Bei falscher Verwendung kann das Setzen der Sperre zu einem Deadlock führen.
Bei Verwendung des Zusatzes FOR UPDATE umgeht eine eigenständige SELECT-Anweisung die
Tabellenpufferung.
Beispiel
Im folgenden Beispiel wird die von der Anweisung DELETE gesetzte
Schreibsperre über einen
Datenbank-Commit gelöst. Dann wird eine Schreibsperre
bereits von der Anweisung SELECT und nicht erst von der Anweisung UPDATE verhängt.
DELETE FROM demo_expressions. INSERT demo_expressions FROM @( VALUE #( id = 'X' ) ). COMMIT CONNECTION default.
...
SELECT SINGLE FOR UPDATE id, num1 FROM demo_expressions
WHERE id = 'X' INTO @DATA(wa).
...
UPDATE demo_expressions SET num1 = 111 WHERE id = 'X'.