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
EXEC SQL DECLARE dyn_cursor SCROLL CURSOR FOR dynstmt END-EXEC
EXEC SQL ALLOCATE DESCRIPTOR GLOBAL 'Placehold' END-EXEC
EXEC SQL ALLOCATE DESCRIPTOR GLOBAL 'Results' END-EXEC
Einlesen von SOURCESTMT
EXEC SQL PREPARE dynstmt FROM :SOURCESTMT END-EXEC
EXEC SQL DESCRIBE INPUT dynstmt
USING SQL DESCRIPTOR GLOBAL 'Placehold' END-EXEC
Fehlerbehandlung, falls nicht SQLSTATE(1:2) = "00"
EXEC SQL DESCRIBE OUTPUT dynstmt USING SQL DESCRIPTOR GLOBAL 'Results' END-EXEC
Fehlerbehandlung, falls nicht SQLSTATE(1:2) = "00"
EXEC SQL GET DESCRIPTOR GLOBAL 'Placehold' :H_COUNT = COUNT END-EXEC
Schleife von I=1 bis I=H_COUNT
EXEC SQL GET DESCRIPTOR GLOBAL 'Placehold' VALUE :I
:H_TYPE =TYPE,
:H_LENGTH = LENGTH, ..., END-EXEC
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_CHARACTEREXEC 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_NUMERIC1EXEC 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_NUMERIC2EXEC 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_NUMERIC3EXEC SQL SET DESCRIPTOR GLOBAL 'Placehold' VALUE :I TYPE=2,
PRECISION=18, SCALE=18, INDICATOR=0, DATA=:H_NUMERIC3 END-EXEC
usw.
Schleifenende
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)
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
EXEC SQL OPEN dyn_Cursor USING SQL DESCRIPTOR GLOBAL 'Placehold' END-EXEC
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 12EXEC 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
EXEC SQL CLOSE dyn_cursor END-EXEC
EXEC SQL DEALLOCATE DESCRIPTOR GLOBAL 'Placehold' END-EXEC
EXEC SQL DEALLOCATE DESCRIPTOR GLOBAL 'Results' END-EXEC
Erläuterung
Der dynamische Cursor DYN_CURSOR wird deklariert. DYN_CURSOR besitzt eine dynamisch übersetzbare Cursorbeschreibung DYNSTMT.
Die Deskriptorbereiche „Placehold“ für die Platzhalter und „Results“ für die Spaltenwerte eines Ergebnissatzes werden angelegt.
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.
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.
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.
Mit GET DESCRIPTOR wird die Anzahl der Platzhalter H_COUNT bestimmt.
Für jeden Platzhalter werden mit GET DESCRIPTOR Datentyp, Länge, usw. gelesen und in die entsprechenden Benutzervariablen H_TYPE, H_LENGTH, usw. übertragen.
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.
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.
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.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.
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.
Der Cursor DYN_CURSOR wird geschlossen.
Schließlich werden die Deskriptorbereiche mit DEALLOCATE wieder freigegeben.