Your Browser is not longer supported

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

{{viewport.spaceProperty.prod}}

Dynamische SQL mit Deskriptorbereichen

Beispiel

Eine beliebige SQL-Anweisung wird zur Laufzeit des Programms eingelesen. Es wird angenommen, dass Anzahl und Datentyp der Eingabewerte beim Schreiben des Programms noch nicht bekannt sind. Sowohl Anzahl und Datentypen der Eingabewerte als auch die Spaltenwerte der Ergebnissätze werden mit Hilfe von DESCRIBE ermittelt.

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.

Die Fehlerbehandlung wird im vorliegenden Beispiel nur an einigen Stellen dargestellt. Ein vollständiges Beispiel erfordert natürlich nach jeder ausführbaren SQL-Anweisung eine Abfrage des SQLSTATE und eine entsprechende Fehlerbehandlung. Es wird vorausgesetzt, dass keine multiplen Spalten vorliegen.

Deklaration von Benutzervariablen H_COUNT, H_TYPE, H_LENGTH, H_NAME, usw., die die Werte für COUNT, TYPE, LENGTH, NAME, usw. in den Feldern des Deskriptorbereichs enthalten bzw. aufnehmen sollen.

Deklaration von Benutzervariablen, die jeweils einem SQL-Datentyp entsprechen: H_CHARACTER, H_NUMERIC1, H_NUMERIC2, usw. für verschiedene Wertebereiche, usw.

Deklaration der Benutzervariablen SOURCESTMT zur Aufnahme der dynamisch übersetzbaren Anweisung

  1. EXEC SQL DECLARE dyn_cursor SCROLL CURSOR FOR dynstmt END-EXEC

  2. EXEC SQL ALLOCATE DESCRIPTOR GLOBAL 'Placehold' END-EXEC
    EXEC SQL ALLOCATE DESCRIPTOR GLOBAL 'Results' END-EXEC

  3. Einlesen von SOURCESTMT

    EXEC SQL PREPARE dynstmt FROM :SOURCESTMT END-EXEC


    1. EXEC SQL DESCRIBE INPUT dynstmt
      USING SQL DESCRIPTOR GLOBAL 'Placehold' END-EXEC

      Fehlerbehandlung, falls nicht SQLSTATE(1:2) = "00"

    2. EXEC SQL DESCRIBE OUTPUT dynstmt USING SQL DESCRIPTOR GLOBAL 'Results' END-EXEC

      Fehlerbehandlung, falls nicht SQLSTATE(1:2) = "00"

  4. EXEC SQL GET DESCRIPTOR GLOBAL 'Placehold' :H_COUNT = COUNT END-EXEC

  5. Schleife von I=1 bis I=H_COUNT

    EXEC SQL GET DESCRIPTOR GLOBAL 'Placehold' VALUE :I
    :H_TYPE =TYPE,
    :H_LENGTH = LENGTH, ..., END-EXEC
  6. Auswahl einer geeigneten Benutzervariablen entsprechend dem Datentyp des Platzhalters. Anpassen des Datentyps und Einlesen des Werts für den Platzhalter in den Deskriptorbereich, z.B.:

    wenn :H_TYPE = 1 oder 12
    Einlesen des Werts für den Platzhalter in H_CHARACTER

    EXEC SQL SET DESCRIPTOR GLOBAL 'Placehold' VALUE :I TYPE = 1,

    LENGTH=256, INDICATOR=0, DATA=:H_CHARACTER END-EXEC

    wenn :H_TYPE =2 oder 3 und 10 bis 18 Vorkommastellen
    Einlesen des Werts für den Platzhalter in H_NUMERIC1

    EXEC SQL SET DESCRIPTOR GLOBAL 'Placehold' VALUE :I TYPE=2,

    PRECISION=18, SCALE=0, INDICATOR=0, DATA=:H_NUMERIC1 END-EXEC

    wenn :H_TYPE =2 oder 3 und 1 bis 9 Vorkommastellen
    Einlesen des Werts für den Platzhalter in H_NUMERIC2

    EXEC SQL SET DESCRIPTOR GLOBAL 'Placehold' VALUE :I TYPE=2,

    PRECISION=18, SCALE=9, INDICATOR=0, DATA=:H_NUMERIC2 END-EXEC

    wenn :H_TYPE =2 oder 3 und 0 Vorkommastellen
    Einlesen des Werts für den Platzhalter in H_NUMERIC3

    EXEC SQL SET DESCRIPTOR GLOBAL 'Placehold' VALUE :I TYPE=2,

    PRECISION=18, SCALE=18, INDICATOR=0, DATA=:H_NUMERIC3 END-EXEC

    usw.

    Schleifenende

  7. EXEC SQL GET DESCRIPTOR GLOBAL 'Results' :H_COUNT=COUNT END-EXEC

    Wenn :H_COUNT=0

    EXEC SQL EXECUTE dynstmt USING SQL DESCRIPTOR GLOBAL 'Placehold'

    END-EXEC

    Sprung nach (12)

  8. sonst

    Schleife von I=1 bis I=H_COUNT

    EXEC SQL GET DESCRIPTOR GLOBAL 'Results' VALUE :I
    :H_TYPE=TYPE
    :H_LENGTH=LENGTH ... END-EXEC

    Auswahl einer geeigneten Benutzervariablen entsprechend dem Datentyp der Spaltenwerte der Ergebnistabelle. Anpassen des Datentyps im Deskriptorbereich, analog dem Vorgehen (6) bei den Platzhaltern, z.B.:

    wenn :H_TYPE = 1 oder 12

    EXEC SQL SET DESCRIPTOR GLOBAL 'Results' VALUE :I TYPE = 1, LENGTH=256

    END-EXEC

    usw.

    Schleifenende

  9. EXEC SQL OPEN dyn_Cursor USING SQL DESCRIPTOR GLOBAL 'Placehold' END-EXEC

  10. Ausführen der folgenden FETCH-Anweisung in einer Schleife, bis die Bedingung „Tabellenende“ auftritt

    EXEC SQL FETCH NEXT FROM dyn_cursor INTO SQL DESCRIPTOR GLOBAL

    'Results' END-EXEC

    Fehlerbehandlung, falls nicht SQLSTATE(1:2) = ''00''

    Schleife über alle Spalten des Ergebnissatzes:
    Wenn :H_TYPE =1 oder 12

    EXEC SQL GET DESCRIPTOR GLOBAL 'Results' VALUE :I

    :H_NAME=NAME, :H_CHARACTER=DATA END-EXEC

    wenn :H_TYPE =2 oder 3 und 10 bis 18 Vorkommastellen

    EXEC SQL GET DESCRIPTOR GLOBAL 'Results' VALUE :I

    :H_NAME=NAME, :H_NUMERIC1=DATA END-EXEC

    usw.

    Ausgabe von H_NAME und der entsprechenden Benutzervariable

    Schleifenende

    Schleifenende

  11. EXEC SQL CLOSE dyn_cursor END-EXEC

  12. EXEC SQL DEALLOCATE DESCRIPTOR GLOBAL 'Placehold' END-EXEC

    EXEC SQL DEALLOCATE DESCRIPTOR GLOBAL 'Results' END-EXEC

Erläuterung

  1. Der dynamische Cursor DYN_CURSOR wird deklariert. DYN_CURSOR besitzt eine dynamisch übersetzbare Cursorbeschreibung DYNSTMT.

  2. Die Deskriptorbereiche „Placehold“ für die Platzhalter und „Results“ für die Spaltenwerte eines Ergebnissatzes werden angelegt.

  3. Der Anweisungstext wird in SOURCESTMT eingelesen und für die spätere Ausführung vorbereitet. Der Anweisungstext kann eine dynamisch übersetzbare Anweisung oder eine Cursorbeschreibung sein.


    1. Nach erfolgreicher Ausführung der PREPARE-Anweisung werden mit DESCRIBE INPUT Anzahl und Datentypen der Platzhalter in der dynamisch übersetzten SQL-Anweisung DYNSTMT abgefragt. Wenn das DESCRIBE INPUT erfolgreich war, dann ist DYNSTMT dynamisch übersetzt und der SQL-Deskriptorbereich „Placehold“ mit den Typbeschreibungen der dynamischen Parameter gesetzt.

    2. Ebenso werden mit DESCRIBE OUTPUT Anzahl und Datentypen der Spalten eines Ergebnissatzes in den Deskriptorbereich „Results“ geschrieben. Wenn das DESCRIBE OUTPUT erfolgreich war, dann ist DYNSTMT dynamisch übersetzt und der SQL-Deskriptorbereich „Results“ mit den Typbeschreibungen der Spalten eines Ergebnissatzes gesetzt.

  4. Mit GET DESCRIPTOR wird die Anzahl der Platzhalter H_COUNT bestimmt.

  5. Für jeden Platzhalter werden mit GET DESCRIPTOR Datentyp, Länge, usw. gelesen und in die entsprechenden Benutzervariablen H_TYPE, H_LENGTH, usw. übertragen.

  6. Entsprechend dem Datentyp des Platzhalters wird eine geeignete Benutzervariable ausgewählt. In diese wird der Wert des Platzhalters eingelesen. Um den Wert eines Platzhalters in den Deskriptorbereich zu übertragen, müssen mit SET DESCRIPTOR im Deskriptorbereich Datentyp, Länge, Anzahl der Dezimal- und Nachkommastellen, usw. den Datentypen der Benutzervariablen angepasst werden. Im Programm wurden z.B. drei Datentypen vorgesehen, die den SQL-Datentypen NUMERIC(18,0), NUMERIC(18,9) und NUMERIC(18,18) entsprechen. Je nach Datentyp des Platzhalters wird im Deskriptorbereich einer dieser Datentypen gesetzt.Nach der Ausführung der SET DESCRIPTOR-Anweisungen enthält der Deskriptorbereich „Placehold“ die Werte für die Platzhalter.

  7. Mit GET DESCRIPTOR wird die Anzahl der Spalten der Ergebnistabelle abgefragt.Ist diese Anzahl 0, dann wird die dynamisch übersetzte Anweisung mit EXECUTE ausgeführt. In der USING-Klausel wird der Deskriptorbereich „Placehold“ angegeben. Er enthält die Werte für die Platzhalter in der dynamisch übersetzten Anweisung. Anschließend wird das Programm bei (13) fortgesetzt.

  8. Ansonsten werden die Sätze der Ergebnistabelle mit Hilfe des bei (1) deklarierten Cursors gelesen.
    Analog (6) und (7) werden zunächst für den Deskriptorbereich „Results“ mit GET DESCRIPTOR Datentypen, Längen, usw. der Ergebnisspalten gelesen. Mit SET DESCRIPTOR werden dann Datentypen, Längen usw. im Deskriptorbereich angepasst.

  9. Der Cursor DYN_CURSOR wird geöffnet. In der USING-Klausel wird der Deskriptorbereich „Placehold“ angegeben. Er enthält die Werte für die Platzhalter in der Cursorbeschreibung.

  10. Die Ergebnistabelle wird satzweise mit FETCH in den Deskriptorbereich „Results“ geschrieben. Mit GET DESCRIPTOR werden die Spaltenwerte aus dem Deskriptorbereich in geeignete Benutzervariablen übertragen und ausgegeben.

  11. Der Cursor DYN_CURSOR wird geschlossen.

  12. Schließlich werden die Deskriptorbereiche mit DEALLOCATE wieder freigegeben.