Your Browser is not longer supported

Please use Google Chrome, Mozilla Firefox or Microsoft Edge to view the page correctly
Loading...

{{viewport.spaceProperty.prod}}

Dynamisches Vorbereiten und Ausführen von SQL-Anweisungen

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:

  1. Deklaration der Benutzervariablen Sourcestmt und Bedingung
    Sourcestmt='UPDATE auftrag SET astnr=3 WHERE anr=251'

  2. Einlesen des Texts 'AND knr=105' in Bedingung
    Sourcestmt=Sourcestmt||Bedingung

  3. EXEC SQL EXECUTE IMMEDIATE :Sourcestmt END_EXEC


Erklärung

    1. Sourcestmt ist eine Benutzervariable, die im ESQL-Programm deklariert ist und der eine alphanumerische Zeichenkette mit der UPDATE-Anweisung zugewiesen wird.

    2. 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.

    3. 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:

  1. Deklaration der Benutzervariablen SOURCESTMT, BEDINGUNG, HOSTVAR1 und HOST-VAR2
    sourcestmt='UPDATE auftrag SET astnr= ? WHERE anr= ?'

  2. Einlesen des Texts 'AND knr=105' in BEDINGUNG
    sourcestmt=sourcestmt||bedingung

  3. EXEC SQL PREPARE dynstmt FROM :SOURCESTMT END-EXEC

  4. Einlesen der Werte 3 für HOSTVAR1 und 251 für HOSTVAR2

    EXEC SQL EXECUTE dynstmt USING :HOSTVAR1,:HOSTVAR2 END-EXEC


Erklärung

    1. Die UPDATE-Anweisung enthält in der WHERE-Bedingung statt der Werte für ASTNR und ANR zwei Platzhalter, die durch Fragezeichen symbolisiert werden.

    2. Die UPDATE-Anweisung wird durch eine Bedingung erweitert, indem der Text in SOURCESTMT mit dem zur Laufzeit eingelesenen Text in BEDINGUNG verkettet wird.

    3. 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.

    4. 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 Cursorbeschreibung soll zur Laufzeit des Programms erzeugt werden. Der Anwender kann die Auftragsnummer und die Bedingung eingeben, die für die auszugebenden Leistungen gelten sollen.

  1. Deklaration der Benutzervariablen ANREINGABE, BEDINGUNG und BESCHREIBUNG. Außerdem wird die SQL-Variable AUFTRAGSNR definiert, die
    den Wert der Auftragsnummer aus ANREINGABE aufnimmt.

  2. Cursor CUR_LEISTUNG definieren:

    EXEC SQL
         DECLARE cur_leistung CURSOR FOR CURBESCHREIBUNG
    END-EXEC
    
  3. Eingabe der Werte für ANREINGABE und BEDINGUNG durch den Anwender zur Laufzeit des Programms.

  4. Erzeugen der Beschreibung BESCHREIBUNG:

    STRING "SELECT * FROM leistung WHERE anr = ? AND " bedingung

  5. Cursorbeschreibung erzeugen:

    EXEC SQL
         PREPARE CURBESCHREIBUNG FROM :BESCHREIBUNG
    END-EXEC
    
  6. Cursor CUR_LEISTUNG öffnen. Der Platzhalter „?“ in der Cursorbeschreibung wird dabei mit der vom Anwender gewählten Auftragsnummer besetzt:

    EXEC SQL
         OPEN cur_leistung USING :AUFTRAGSNR
    END-EXEC
    

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.