Überlegungen zu 'open' mit SQL

Im Kontext von SQL erstellt die EGL-Anweisung 'open' eine Ergebnismenge auf Basis einer relationalen Datenbank sowie einen Cursor, mit dessen Hilfe Sie die Liste durchsuchen können.

EGL ermöglicht Ihnen keinen direkten Zugriff auf diesen Cursor. Stattdessen werden positionsgebundene Optionen mit der Anweisung 'get' bereitgestellt (siehe Überlegungen zu 'get' mit SQL). Nach Ausführung der Anweisung 'open' zeigt der Cursor auf die erste Zeile (den ersten Datensatz) in der Ergebnismenge.

Syntax

Syntaxdiagramm für die Anweisung 'open'
Ergebnismengen-ID
Eine von Ihnen ausgewählte Zeichenfolge zwecks Angabe der Ergebnismenge, die von der Anweisung 'open' erstellt wird. Sie können die ID mit einer positionsgebundenen Anweisung 'get' oder mit den Anweisungen 'replace', 'delete' oder 'close' verwenden.
rowsetsize
'RowsetSize' ist eine Anmerkung, mit der gesteuert wird, wie viele Zeilen in einer Multiple-Row-Abrufoperation oder in einer Multiple-Row-Einfügeoperation auf einmal abgerufen bzw. eingefügt werden.
scroll
Option, die es einer Anweisung 'get' ermöglicht, durch die Ergebnismenge zu navigieren. Weitere Informationen zu positionsgebunden get-Anweisungen finden Sie unter Überlegungen zu 'get' mit SQL. Diese Option ist nur dann verfügbar, wenn Sie Ausgabe in Java™ generieren.
hold
Option, die das Programm veranlasst, die Position in einer Ergebnismenge beizubehalten, wenn ein Commit ausgeführt wird. Die Option 'hold' ist geeignet, wenn alle folgenden Bedingungen zutreffen:
  • Sie verwenden die EGL-Anweisung 'open' zum Öffnen eines Cursor und nicht zum Aufrufen einer gespeicherten Prozedur.
  • Sie wollen Änderungen in regelmäßigen Abständen festschreiben, ohne Ihre Position in der Ergebnismenge zu verlieren.
  • Ihr Datenbankverwaltungssystem unterstützt die Verwendung der Option WITH HOLD in der SQL-Cursordeklaration.

Cursor, für die Sie die Option 'hold' angeben, werden bei einem Commit nicht geschlossen. Bei einem Rollback oder einer Datenbankverbindung werden hingegen alle Cursor geschlossen. Geben Sie die Option 'hold' nicht an, wenn Sie die Cursorposition bei einem Commit nicht beizubehalten brauchen.

Weitere Informationen finden Sie unter 'Kompatibilität' in diesem Thema.

forUpdate
Option, über die Sie eine spätere EGL-Anweisung verwenden können, um die Daten, die aus der Datenbank abgerufen wurden, zu ersetzen oder zu löschen. Verwenden Sie diese Option nicht, wenn Sie eine gespeicherte Prozedur aufrufen.
usingKeys ... Feld
Sie können hier Feldnamen aus Ihrem SQL-Datensatz angeben, um die Schlüsselfelder zu überschreiben, die Sie in dieser Datensatzdefinition angegeben haben. Das Feld (oder die Felder), das Sie mit der Klausel 'usingKeys' angeben, erstellt die Schlüssel/Wert-Komponente der WHERE-Klausel in einer impliziten SQL-Anweisung. Die implizite SQL-Anweisung wird während der Ausführung verwendet, wenn Sie keine explizite SQL-Anweisung angeben. Wenn Sie eineusingKeys-Klausel verwenden, müssen Sie auch eine SQL-Satzvariable angeben.

Wenn Sie keine Klausel 'usingKeys' angeben, basiert die Schlüssel/Wert-Komponente der impliziten Anweisung auf dem SQL-Datensatzabschnitt, der in der Anweisung 'open' referenziert wird.

Wenn Sie das Schlüsselwort 'forUpdate' angeben, werden die den Schlüsselelementen zugeordneten Spalten aus den in der SQL-Klausel FOR UPDATE OF aufgelisteten Spalten ausgeschlossen. Wenn Sie das Schlüsselwort 'forUpdate' nicht angeben, werden nur die den Schlüsselelementen zugeordneten Spalten in die Liste der Spalten in der SQL-Klausel ORDER BY eingeschlossen.

Wenn Sie eine eingebettete SQL-Anweisung angeben, wird jeder implizite Code ignoriert, den EGL ansonsten möglicherweise generiert.

with #sql{ SQL-Anweisung }
Gibt eine eingebettete SQL-Anweisung SELECT an, die optional ist, wenn Sie auch eine SQL-Datensatzvariable angeben. Eingebetteter Code hat Vorrang vor jedem impliziten Code, den EGL ansonsten möglicherweise generiert. Zwischen der Direktive '#sql' und der linken geschweiften Klammer darf kein Leerzeichen stehen.
Betrachen Sie folgenden Fall: Ihr Code enthält eine Anweisung 'get' oder 'open', die einen SQL-Datensatz verwendet, eine explizite SQL-Anweisung einschließt und keine INTO-Klausel aufweist. Es folgt ein Beispiel eines EGL-Codes, der eine solche Anweisung 'get' einschließt:
customer CustomerRecordPart{};
get customer with #sql{
   select MySCHEMA.CUSTOMER.Column01
   from MYSCHEMA.CUSTOMER
   where MYSCHEMA.Column02 = "AZ"}; 
Der folgende Datensatzabschnitt (Record) wurde in diesem Code referenziert:
Record CustomerRecordPart type SQLRecord {tableNames = [["MYSCHEMA.CUSTOMER"]]}
   customerNumber INT    {column = "MYSCHEMA.CUSTOMER.Column01"};
   ...
end

In der zuvor beschriebenen Anweisung 'get' oder 'open' muss die für einen Spaltennamen in der SQL-Klausel SELECT verwendete Qualifizierung mit der Qualifizierung übereinstimmen, die für das entsprechende Feld im Datensatzabschnitt verwendet wird.

into Ziel
Entspricht einer SQL-Klausel INTO, die die EGL-Hostvariablen angibt (siehe Hostvariablen), die Werte aus der Ergebnismenge empfangen. Sie können als Alternative auch einen Datensatznamen angeben. In diesem Fall verwendet EGL sämtliche Felder aus dem Datensatz. Fügen Sie in einer Klausel diesen Typs (die sich außerhalb einer #sql-Anweisung befindet) keinen Doppelpunkt vor dem Namen einer Hostvariablen ein.
ID_der_vorbereiteten_Anweisung
Gibt Code an, der mit einer EGL-Anweisung 'prepare' erstellt wurde, und ermöglicht eine dynamische Verarbeitung. Details hierzu finden Sie in Überlegungen zu 'prepare' mit SQL.
using Feld
Entspricht einer SQL-Klausel USING, die die EGL-Hostvariablen angibt, die zur Ausführungszeit für die vorbereitete Anweisung bereitgestellt werden. Fügen Sie in einer Klausel 'using Feld' (die sich außerhalb einer Direktive '#sql' befindet) keinen Doppelpunkt vor dem Namen einer Hostvariablen ein.
SQL-Datensatzvariable
Der Name einer SQL-Datensatzvariablen. Wenn Sie keine SQL-Datensatzvariable angeben, müssen Sie eingebetteten SQL-Code (mit der Direktive '#sql') bereitstellen. Wenn Sie eine SQL-Satzvariable bereitstellen und keinen eingebetteten SQL-Code angeben, verwendet EGL Informationen über die Satzeigenschaften, um eine implizite SQL-Anweisung SELECT zu erstellen. Sie können die Variable nach der Operation 'open' abfragen, um eventuelle Fehlerbedingungen zu ermitteln. Weitere Informationen hierzu finden Sie unter 'Fehlerbedingungen' in diesem Thema.
dynamische_SQL-Feldgruppe
Diese Variable benennt eine dynamische Feldgruppe, die sich aus SQL-Datensatzvariablen zusammensetzt. EGL unterstützt dynamische Feldgruppen aus SQL-Datensätzen als Ziel der Anweisung 'open'. Die Verwendung einer dynamischen Feldgruppe ist nur dann gültig, wenn für diese Anweisung die Funktion für Zeilengruppenverarbeitung verwendet wird.

Standardverarbeitung

Wenn Sie eine SQL-Datensatzvariable angeben, hat die Anweisung 'open' standardmäßig den folgenden Effekt:
  • Die Anweisung 'open' macht eine Gruppe von Zeilen verfügbar. EGL verwendet die Zuordnungsinformationen im SQL-Datensatzabschnitt, um jede Spalte in den ausgewählten Zeilen einem Datensatzvariablenfeld zuzuordnen. Mit Ausnahme der Spalten, die einem schreibgeschützten Datensatzfeld zugeordnet sind, sind alle Spalte für eine nachfolgende Aktualisierung durch eine EGL-Anweisung 'replace' verfügbar.
  • Wenn Sie nur ein Schlüsselfeld für den SQL-Datensatz deklarieren, wählt die Anweisung 'open' alle Zeilen aus, die die folgenden Bedingungen erfüllen:
    • Die Zeilen erfüllen die datensatzspezifische Eigenschaft 'defaultSelectCondition' des SQL-Datensatzabschnitts.
    • Der Wert in der Schlüsselspalte der SQL-Tabelle ist größer-gleich dem Wert im Schlüsselfeld der SQL-Datensatzvariablen.
  • Wenn Sie keine Schlüsselfelder oder mehrere Schlüsselfelder für den SQL-Datensatz deklarieren, stellt die datensatzspezifische Eigenschaft 'defaultSelectCondition' die einzigen Suchbedingungen bereit, und die Anweisung 'open' ruft alle Zeilen ab, die diese Bedingungen erfüllen.
  • Wenn Sie weder einen Datensatzschlüssel noch eine Standardauswahlbedingung angeben, wählt die Anweisung 'open' alle Zeilen in der Tabelle aus.
  • Die ausgewählten Zeilen werden nicht sortiert.
Die EGL-Anweisung 'open' wird im generierten Code durch eine Cursordeklaration dargestellt, die eine SQL-Anweisung SELECT oder SELECT FOR UPDATE einschließt. Die folgenden Bedingungen treffen standardmäßig zu:
  • Die Klausel FOR UPDATE OF schließt keine schreibgeschützten Datensatzfelder ein.
  • Die SQL-Anweisung SELECT für einen bestimmten Datensatz ist mit der folgenden Anweisung vergleichbar:
      SELECT Spalte01, 
             Spalte02, ... 
             SpalteNN
      INTO   :Datensatzfeld01,
             :Datensatzfeld02, ...
             :DatensatzfeldNN
      FROM   Tabellenname 
      WHERE  Schlüsselspalte01 = :Schlüsselfeld01
      FOR UPDATE OF
             Spalte01, 
             Spalte02, ... 
             SpalteNN

Sie können die Standardanweisung überschreiben, indem Sie eine eingebettete SQL-Anweisung in der EGL-Anweisung 'open' angeben (mithilfe der Direktive #sql).

Beispiele

Die folgenden Beispiele setzen eine SQL-Datensatzvariable namens 'myCustomer' voraus:

  open myCustomerResults forUpdate for myCustomer;

  open x1 with
    #sql{
      SELECT customer_number,
             customer_name, 
             customer_balance
      FROM   Customer 
      WHERE  customer_number >= :myCustomer.customerNumber
      FOR UPDATE OF 
             :myCustomer.customerNumber, 
             :myCustomer.customerName,
             :myCustomer.customerBalance
    }

  open x2 with 
    #sql{
      SELECT customer_name, customer_balance
      FROM Customer
      WHERE customer_number = :myCustomer.customerNumber
    }
  for myCustomer;

  open x3 with
    #sql{
      call aResultSetStoredProc(:parameter)
    }
Es folgt das Beispiel eines Verarbeitungsablaufs, für den das Schlüsselwort 'hold' erforderlich ist:
  1. Deklarieren und öffnen Sie einen Cursor mit einer EGL-Anweisung 'open'.
  2. Rufen Sie eine Zeile mit einer EGL-Anweisung 'get next' ab.
  3. Führen Sie die folgenden Aktionen in einer Schleife aus:
    1. Verarbeiten Sie die Daten auf die eine oder andere Weise.
    2. Aktualisieren Sie die Zeile mit einer EGL-Anweisung 'replace'.
    3. Schreiben Sie Änderungen mit der Systemfunktion 'sysLib.commit()' fest.
    4. Rufen Sie eine weitere Zeile mit einer EGL-Anweisung 'get next' ab.

Wenn Sie 'hold' nicht angeben, schlägt die erste Ausführung des vierten Teils von Schritt 3 fehl, da der Cursor nicht mehr offen ist.

Fehlerbedingungen

Die folgenden Situationen sind nicht gültig:
  • Sie schließen eine eingebettete SQL-Anweisung ein, in der eine für SELECT erforderliche Klausel fehlt. Die erforderlichen Klauseln sind SELECT, FROM und FOR UPDATE OF (bei Angabe der Option 'forUpdate').
  • Ihre SQL-Datensatzvariable ist einer Spalte zugeordnet, die entweder zur Ausführungszeit nicht vorhanden ist oder die mit dem zugehörigen Datensatzfeld nicht kompatibel ist.
  • Sie geben die Option 'forUpdate' an, und Ihr Code versucht, eine Anweisung 'open' für einen der folgenden SQL-Datensatztypen auszuführen:
    • Für einen SQL-Datensatz, dessen einzige Datensatzfelder schreibgeschützt sind.
    • Für einen SQL-Datensatz, der zu mehr als einer SQL-Tabelle gehört.
Ein Problem tritt auch dann auf, wenn die beiden folgenden Bedingungen zutreffen:
  1. Sie passen eine EGL-Anweisung 'open' für Aktualisierung an, ohne anzugeben, dass eine bestimmte SQL-Tabellenspalte für die Aktualisierung verfügbar ist.
  2. Die zur Anweisung 'open' gehörende Anweisung 'replace' versucht, die Spalte zu überarbeiten.
Zur Lösung dieses Problems gibt es folgende Möglichkeiten:
  • Wenn Sie die EGL-Anweisung 'open' anpassen, schließen Sie den Spaltennamen in die Klausel FOR UPTDATE OF der SQL-Anweisung SELECT ein.
  • Wenn Sie die EGL-Anweisung 'replace' anpassen, entfernen Sie alle Verweise auf die Spalte in der SET-Klausel der SQL-Anweisung UPDATE.
  • Übernehmen Sie den impliziten SQL-Code, den EGL sowohl für die Anweisung 'open' als auch für die Anweisung 'replace' generiert.

Kompatibilität

Jedes Managementsystem für relationale Datenbanken (RDBMS) verfügt über eine eigene SQL-Version. Nicht alle SQL-Befehle sind in jeder Implementierung verfügbar. Bevor Sie eine eingebettete SQL-Anweisung codieren, lesen Sie die Dokumentation für Ihr Managementsystem für relationale Datenbanken.

Tabelle 1. Hinweise zur Kompatibilität für 'open' und SQL
Plattform Problem
Java-Generierung Die Option 'hold' ist für Java-Programme nur dann verfügbar, wenn der JDBC-Treiber JDBC ab Version 3.0 unterstützt.
CICS Wenn das Programm im Segmentmodus ausgeführt wird, beendet eine Anweisung 'converse' die CICS-Transaktion und verhindert, dass das Programm eine Datei- oder Datenbankposition beibehält, und zwar auch dann, wenn Sie das Schlüsselwort 'hold' in der Anweisung 'open' verwenden.
IMS/VS Jede Anweisung 'converse' wird im Segmentmodus ausgeführt. Eine solche Anweisung beendet die IMS-Transaktion und verhindert, dass das Programm eine Datei- oder Datenbankposition beibehält, und zwar auch dann, wenn Sie das Schlüsselwort 'hold' in der Anweisung 'open' verwenden.
Cloudscape- oder Derby-Datenbanken EGL unterstützt keine Anweisung 'open', die sowohl das Flag 'scroll' als auch das Flag 'forUpdate' verwendet. Sie können in der Anweisung immer nur eines der Flags verwenden.

Feedback