Die dynamische SQL soll zunächst mit einem einfachen Beispiel eingeführt werden. In diesem Beispiel wird noch kein SQL-Deskriptorbereich verwendet. Im Beispiel werden die SQL-Anweisungen wie in ESQL-COBOL mit EXEC SQL und END-EXEC gekennzeichnet. Die Aktionen in der Wirtssprache des ESQL-Programms sind in Kursiv dargestellt.
Beispiel
In der Tabelle AUFTRAG soll für den Satz mit der Auftragsnummer 251 und der Kundennummer 105 der Auftragsstatus auf 3 geändert werden. In statischer SQL kann dies durch folgende Anweisung erreicht werden:
UPDATE auftrag SET astnr=3 WHERE anr=251 AND knr=105
Dieser Anweisung entspricht in dynamischer SQL folgende Anweisungsfolge:
Deklaration der Benutzervariablen Sourcestmt und Bedingung
Sourcestmt='UPDATE auftrag SET astnr=3 WHERE anr=251'Einlesen des Texts 'AND knr=105' in Bedingung
Sourcestmt=Sourcestmt||BedingungEXEC SQL EXECUTE IMMEDIATE :Sourcestmt END_EXEC
Erklärung
Sourcestmt ist eine Benutzervariable, die im ESQL-Programm deklariert ist und der eine alphanumerische Zeichenkette mit der UPDATE-Anweisung zugewiesen wird.
Die UPDATE-Anweisung wird durch eine Bedingung erweitert, indem der Text in Sourcestmt mit dem zur Laufzeit eingelesenen Text in Bedingung verkettet wird. Während in statischer SQL der Anweisungstext der UPDATE-Anweisung zum Übersetzungszeitpunkt des Programms festliegt, braucht hier die Anweisung erst zur Laufzeit des Programms festgelegt zu werden.
Die EXECUTE IMMEDIATE-Anweisung prüft und übersetzt die Anweisung und führt sie aus.
Beispiel
Eine allgemeinere Form der obigen UPDATE-Anweisung kann mit statischer SQL durch die folgende Anweisung erreicht werden:
UPDATE auftrag SET astnr=:ASTNR WHERE anr=:ANR AND knr=105
Hier werden die Werte für ASTNR und ANR durch zwei Benutzervariablen ersetzt, deren Werte erst zur Laufzeit des Programms festgelegt werden. Dieser Anweisung entspricht in dynamischer SQL folgende Anweisungsfolge:
Deklaration der Benutzervariablen SOURCESTMT, BEDINGUNG, HOSTVAR1 und HOST-VAR2
sourcestmt='UPDATE auftrag SET astnr= ? WHERE anr= ?'Einlesen des Texts 'AND knr=105' in BEDINGUNG
sourcestmt=sourcestmt||bedingungEXEC SQL PREPARE dynstmt FROM :SOURCESTMT END-EXEC
Einlesen der Werte 3 für HOSTVAR1 und 251 für HOSTVAR2
EXEC SQL EXECUTE dynstmt USING :HOSTVAR1,:HOSTVAR2 END-EXEC
Erklärung
Die UPDATE-Anweisung enthält in der WHERE-Bedingung statt der Werte für ASTNR und ANR zwei Platzhalter, die durch Fragezeichen symbolisiert werden.
Die UPDATE-Anweisung wird durch eine Bedingung erweitert, indem der Text in SOURCESTMT mit dem zur Laufzeit eingelesenen Text in BEDINGUNG verkettet wird.
Diese dynamisch übersetzbare UPDATE-Anweisung wird mit der folgenden PREPARE-Anweisung übersetzt. DYNSTMT bezeichnet die dynamisch übersetzte SQL-Anweisung. Unter diesem Namen kann die Anweisung in einer EXECUTE-Anweisung angesprochen werden.
Vor der Ausführung der EXECUTE-Anweisung werden Werte für die im ESQL-Programm deklarierten Benutzervariablen HOSTVAR1 und HOSTVAR2 eingelesen. Diese Werte sollen die Platzhalter „?“ in der UPDATE-Anweisung ersetzen. Die EXECUTE-Anweisung führt nun die mit PREPARE übersetzte Anweisung DYNSTMT aus.
Beispiel
Es wird der Cursor CUR_LEISTUNG für die Tabelle LEISTUNG definiert.
|
Die in den Beispielen verwendeten Anweisungen EXECUTE IMMEDIATE, PREPARE und EXECUTE werden im Folgenden näher dargestellt. Zunächst wird beschrieben, welche Anweisungen dynamisch übersetzbar sind.
Dynamisch übersetzbare Anweisungen
Dynamisch übersetzbar sind folgende Anweisungen (zur Klassifikation der Anweisungen siehe "SQL-Anweisungen zur Schemadefinition und -verwaltung"):
SQL-Anweisungen zur Schemadefinition und -verwaltung
SQL-Anweisungen zur Gestaltung und Verwaltung von Routinen
SQL-Anweisungen zum Abfragen und Ändern von Daten:
SELECT (ohne INTO-Klausel)
UPDATE
DELETE
INSERT (ohne RETURN INTO-Klausel)
MERGE
CALL
SQL-Anweisungen zur Transaktionsverwaltung
SQL-Anweisungen zur Sessionsteuerung
SQL-Anweisungen zur Verwaltung der Speicherstruktur
SQL-Anweisungen zur Verwaltung von Benutzereinträgen
Utility-Anweisungen
Außerdem sind Cursorbeschreibungen dynamisch übersetzbar.
Nicht dynamisch übersetzbar sind
die SQL-Anweisungen der dynamischen SQL
die SQL-Anweisungen für das Arbeiten mit einem Cursor:
DECLARE CURSOR
OPEN
FETCH
CLOSE
STORE
RESTORE
die SQL-Anweisungen INCLUDE und WHENEVER.
EXECUTE IMMEDIATE-Anweisung
Mit der Anweisung EXECUTE IMMEDIATE wird eine dynamisch formulierte Anweisung in einem Schritt vorbereitet und ausgeführt. EXECUTE IMMEDIATE entspricht also einer PREPARE-Anweisung mit unmittelbar darauffolgender EXECUTE-Anweisung. Allerdings bleibt die Anweisung nicht vorbereitet und kann nicht mit EXECUTE nochmals ausgeführt werden.
Innerhalb des Anweisungstexts dürfen keine Benutzervariablen und keine Fragezeichen als Platzhalter für unbekannte Werte verwendet werden.
PREPARE-Anweisung
PREPARE bereitet eine dynamisch formulierte Anweisung oder die Cursorbeschreibung eines dynamischen Cursors für die spätere Ausführung vor.
Eine mit PREPARE vorbereitete Anweisung wird mit EXECUTE ausgeführt.
Innerhalb des Anweisungstexts dürfen keine Benutzervariablen verwendet werden. Platzhalter für noch unbekannte Eingabewerte werden durch ein Fragezeichen angegeben.
Platzhalter
Die in der Anweisungsvariablen enthaltene dynamisch übersetzbare Anweisung bzw. dynamisch übersetzbare Cursorbeschreibung darf keine Benutzervariablen enthalten. Stattdessen dürfen darin Platzhalter für Eingabewerte stehen, die durch Fragezeichen dargestellt werden. Diese Platzhalter werden in der USING-Klausel einer späteren EXECUTE- oder OPEN-Anweisung mit Werten versorgt.
Für jeden Platzhalter wird ein SQL-Datentyp bestimmt. Es gibt einige Regeln, die die Verwendung von Platzhaltern in anweisungsvariable einschränken. Ein Platzhalter ist nur in einem Kontext erlaubt, in dem der Datentyp des Platzhalters eindeutig bestimmbar ist.
Platzhalter sind deshalb nicht erlaubt
als Element einer SELECT-Liste in der Form „?“ (dagegen ist z.B. „SELECT ?+1“ erlaubt)
als Operand eines einstelligen Operators
als Argument einer Mengenfunktion
in einer Abfrage auf den NULL-Wert
wenn beide Operanden eines zweistelligen Operators oder eines Vergleichsoperators Platzhalter sind
wenn bei einer Bereichsabfrage mit BETWEEN, in der der erste Operand ein Platzhalter ist, einer der beiden anderen Operanden ein Platzhalter ist
als erster Operand bei einem Mustervergleich mit LIKE
wenn bei einem Vergleich eines Ausdrucks mit einer Menge von Werten sowohl der zu vergleichende Ausdruck als auch alle Werte in der Liste nach IN Platzhalter sind
wenn in einem CASE-Ausdruck alle Operanden Platzhalter sind. Enthält der CASE-Ausdruck eine oder mehrere THEN- bzw. ELSE-Klauseln, dürfen zusätzlich nicht alle Operanden dieser Klauseln Platzhalter sein.
als Operanden der Zeichenkettenfunktionen LOWER und UPPER
als erster Operand (zeichen) und/oder als zweiter Operand (ausdruck) der Zeichenkettenfunktion TRIM (z.B. TRIM (TRAILING FROM ?))
als erster Operand der Zeichenkettenfunktion SUBSTRING (z.B. SUBSTRING ? FROM 1 FOR 5))
wenn beide Operanden der numerischen Funktion POSITION Platzhalter sind.
EXECUTE-Anweisung
EXECUTE führt eine mit PREPARE vorbereitete Anweisung aus. Platzhalter für Eingabewerte in der dynamisch formulierten Anweisung werden durch aktuelle Werte ersetzt.
Ist die Anweisung eine SELECT-Anweisung, werden die Spaltenwerte des Ergebnissatzes in Benutzervariablen oder einem SQL-Deskriptorbereich abgelegt.
Eine EXECUTE-Anweisung kann beliebig oft für eine mit PREPARE vorbereitete Anweisung ausgeführt werden.
Eine Anweisung kann mit EXECUTE nur in der Übersetzungseinheit ausgeführt werden, in der sie vorher mit PREPARE vorbereitet wurde.
In der EXECUTE-Anweisung können Benutzervariablen oder SQL-Deskriptorbereiche für die Ein- und Ausgabewerte verwendet werden. Die Verwendung von SQL-Deskriptorbereichen wird im nächsten Abschnitt beschrieben.