SQL-Daten

SQL ist eine Sprache, die mit einem Verwaltungssystem für relationale Datenbanken kommuniziert. Dieses System steuert wiederum eine Datenbank, die Geschäftsinformationen in vernetzten Tabellen verwaltet.

EGL bietet zwei Möglichkeiten zum Arbeiten mit SQL-Daten:

Bei EGL besteht sogar die Möglichkeit, die beiden Verfahren zu kombinieren. Sie können über den EGL-Code auf die von EGL generierten SQL-Anweisungen zugreifen und diese ändern (siehe Implizite SQL-Anweisungen anzeigen).

Die Themen in diesem Abschnitt enthalten die folgenden Informationen:

EGL-Ansatz

In der folgenden Tabelle wird beschrieben, wie EGL für die Interaktion mit einer relationalen Datenbank verwendet werden kann.

Tabelle 1. Bewährte Verfahren für EGL-SQL
SQL-Ziel EGL-Ansatz
Einfache SQL-Datenbearbeitung (SELECT, UPDATE, INSERT, DELETE). Primärschlüssel steuert WHERE und ORDER BY. EGL-Schlüsselwörter (get, replace, add, delete) verwenden und EGL zur Generierung von implizitem SQL veranlassen.
Einfache SQL-Datenbearbeitung mit wiederverwendbarer angepasster WHERE-Klausel Angepasste WHERE-Klausel in die Eigenschaft defaultSelectCondition einfügen.
SQL-SELECT-Anweisungen mit angepasster WHERE-Klausel Explizites SQL über die #sql-Direktive verwenden.
SQL-Anweisung JOIN für Tabellen Die Funktion 'SQL abrufen' in der Workbench verwenden und dann die Tabellen in Primär- und Fremdschlüsseln mit der Eigenschaft defaultSelectCondition korrekt verknüpfen:
defaultSelectCondition = #sqlCondition{
  customer.customer_ID = 
  orders.customer_ID }
Abgeleitete Daten in SELECT-Befehl (z. B. MAX() ider AVG()) Explizites SQL über die #sql-Direktive verwenden und die abgeleiteten Felder in die geschweiften Klammern einfügen.
Einen angepassten SQLRecord erstellen, wobei die Eigenschaft column für die einzelnen Felder den abgeleiteten oder berechneten Ausdruck angibt.
Komplexe oder angepasste SQL-Anweisung UPDATE, INSERT oder DELETE EGL-Anweisung replace, add oder delete mit explizitem SQL verwenden (#sql-Direktive).
Explizites SQL über die Anweisung execute #sql verwenden.
Andere SQL-Anweisungen als die für einfache Datenbearbeitung (z. B. CREATE TABLE) Explizites SQL über die Anweisung execute #sql verwenden.
Dynamisches SQL (vorbereitete SQL-Anweisung) Explizites SQL über die Anweisung execute #sql verwenden.
Gespeicherte Prozedur

Explizites SQL verwenden. Beispiel:
open result_set with #sql{
  CALL stored_proc ( :host_var) }

Verarbeitung einzelner Zeilen der Ergebnisliste über eine SQL-Anweisung SELECT EGL-Befehl open zum Öffnen der Ergebnisliste verwenden und anschließend eine Schleife mit einer der folgenden Anweisungen auslösen:
  • forEach (from result_set)
  • while (sqlLib.sqlData.sqlcode == 0)
Programmatic Paging für Onlinesuchvorgänge Assistenten für die Datenzugriffsanwendung verwenden.
Hinzufügen von Daten zur SQL-Tabelle Tabelleneditor in der Datenperspektive der Workbench verwenden.
Gültigkeitsprüfung von SQL-Anweisungen Im EGL-Editor 'Validate SQL' aus dem Kontextmenü auswählen.
Interactive SQL mit dem SQL-Editor in der Datenperspektive der Workbench ausführen.

Ergebnismengenverarbeitung

Führen Sie die folgenden Schritte aus, um eine Folge von Zeilen auf eine gängige Weise zu aktualisieren:
  1. Deklarieren und öffnen Sie einen Cursor, indem Sie eine EGL-Anweisung open mit der Option forUpdate ausführen. Mit dieser Option werden die ausgewählten Zeilen für nachfolgende Aktualisierungen oder Löschvorgänge gesperrt.
  2. Rufen Sie eine Zeile durch Ausführung der EGL-Anweisung get next ab.
  3. Führen Sie in einer forEach-Schleife die folgenden Aktionen aus:
    1. Rufen Sie Daten aus der Ergebnisliste für die Hostvariablen ab. Eine Hostvariable ist eine Variable in einer SQL-Anweisung, deren Name mit einer Variablen in der Hostprogrammiersprache (in diesem Fall enthält EGL die SQL-Anweisungen) übereinstimmt, plus einem zusätzlichen Doppelpunkt (:) als Anfangszeichen.
    2. Aktualisieren oder löschen Sie die Zeile durch Ausführung einer EGL-Anweisung replace oder delete.
    3. Rufen Sie eine weitere Zeile durch Ausführung der EGL-Anweisung get next ab.
  4. Führen Sie die Funktion commit() aus, um die Änderungen festzuschreiben.

Die Anweisungen, die den Cursor öffnen und die Zeilen dieses Cursors bearbeiten, stehen über eine Ergebnismengen+++-ID miteinander in Beziehung, die für alle Ergebnismengen-IDs und Programmvariablen innerhalb des Programms eindeutig sein muss. Diese ID wird in der Anweisung open angegeben, die den Cursor öffnet, und sie wird in der Anweisung forEach referenziert, die die Schleife erstellt. Ferner kann die ID in den Anweisungen get next, delete und replace referenziert werden, die eine einzelne Zeile betreffen, sowie in der Anweisung close, die den Cursor schließt.

Zum Speichern der Daten, die aus einer relationalen Datenbank gelesen oder in diese geschrieben werden, kann ein spezieller Typ von EGL-Datensatz (SQLRecord) verwendet werden. Im folgenden Beispiel wird gezeigt, wie Sie eine Folge von Zeilen aktualisieren können, wenn Sie SQL selbst codieren:
  try
    open selectEmp forUpdate for emp;
  onException(sqlx SqlException)
    myErrorHandler(sqlx);    // exits program
  end

  foreach(emp)
    emp.empname = emp.empname :: " " :: "III";
    try 
      replace emp;
    onException(sqlx SqlException)
      myErrorHandler(sqlx);   // exits program
    end
  end  // end while; cursor is closed automatically
       // when the last row in the result set is read

  sysLib.commit();

Verwenden Sie zum regelmäßigen Festschreiben von Änderungen bei der Verarbeitung einer EGL-Anweisung open (unabhängig davon, ob Sie mit SQL-Datensätzen arbeiten) die Anweisungsoption hold, mit der die Cursorposition nach einer Festschreibung gehalten wird. Wenn ein für CICS bestimmtes Programm jedoch segmentiert ist, hat die Option hold keine Auswirkungen, da eine Umkehrung in einem segmentierten Programm die CICS-Transaktion beendet und das Programm an der Aufbewahrung von Dateien oder Datenbankpositionen hindert.

SQL-Datensätze und ihre Verwendung

Nach dem Definieren eines SQLRecord-Abschnitts wird eine Variable basierend auf diesem Abschnitt deklariert. Mit dieser Datensatzvariablen können Sie auf eine relationale Datenbank auf dieselbe Weise wie auf eine Datei zugreifen. Beispiel: Wenn die Variable myEmpRecord auf einem SQLRecord-Abschnitt basiert, der die Datenbanktabelle EMPLOYEE referenziert, können Sie myEmpRecord in der EGL-Anweisung add verwenden:
  add myEmpRecord;
In diesem Fall fügt EGL die Daten aus myEmpRecord in EMPLOYEE ein. Nach der Ausführung der EGL-Anweisung enthält die Datensatzvariable Informationen zu Fehlerbedingungen:
  try
    add myEmpRecord;
  onException(sqlx SqlException)
    if (myEmpRecord is unique) // if a table row had the same key
      myErrorHandler(sqlx);
    end
  end
Zur Interaktion mit einer relationalen Datenbank wird eine Datensatzvariable wie myEmpRecord verwendet:
  • Definieren Sie einen SQLRecord-Abschnitt und deklarieren Sie die zugehörige Datensatzvariable.
  • Schreiben Sie SQL-Anweisungen, die mit dem SQL-Datensatz E/A-Aktivitäten ausführen.
  • Übernehmen Sie das Standardverhalten der EGL-Anweisungen (das in den meisten Fällen zu dem gewünschten Ergebnis führt) oder nehmen Sie der Geschäftslogik entsprechende SQL-Änderungen vor.

SQLRecord-Abschnitt und zugehörigen Datensatz definieren

Das Definieren eines SQLRecord-Abschnitts und die Zuordnung der einzelnen Felder zu einer Spalte erfolgt in einer relationalen Tabelle oder Ansicht. EGL kann diese Aktionen automatisch ausführen (siehe SQL-Tabellendaten abrufen).

Wenn der SQLRecord-Abschnitt kein fester Datensatzabschnitt ist, können Sie Basisfelder und andere Variablen einfügen. Normalerweise werden die folgenden Variablen eingefügt:
  • Andere SQL-Datensätze. Jeder dieser Datensätze repräsentiert eine Eins-zu-eins-Beziehung zwischen der übergeordneten und der untergeordneten Tabelle.
  • Arrays mit SQL-Datensätzen. Jeder dieser Datensätze repräsentiert eine Eins-zu-viele-Beziehung zwischen der übergeordneten und der untergeordneten Tabelle.

Eine Datenbankspalte kann nur durch Felder eines Basiselementtyps+++ repräsentiert werden.

Stehen vor den Feldern Ebenennummern, ist der SQLRecord-Abschnitt ein fester Datensatzabschnitt. Es gelten die folgenden Regeln:
  • Die Struktur in den einzelnen SQLRecord-Abschnitten muss flach (ohne Hierarchie) sein.
  • Alle Felder müssen Basisfelder sein, jedoch nicht vom Typ BLOB, CLOB oder STRING.
  • Keines der Datensatzfelder darf eine Strukturfeld-Feldgruppe (structure-field) sein.

Nach dem Definieren eines SQLRecord-Abschnitts wird eine Datensatzvariable basierend auf diesem Abschnitt deklariert.

SQL-bezogene EGL-Anweisungen

Sie können eine Gruppe von EGL-Anweisungen erstellen, die alle die Datensatzvariable als E/A-Objekt in der Anweisung verwenden. EGL stellt für jede Anweisung eine implizite SQL-Anweisung bereit, die nicht in der Quelle enthalten ist, sondern durch die Kombination von Datensatzvariable und EGL-Anweisung impliziert ist. Beispielsweise fügt eine implizite SQL-Anweisung INSERT im Falle einer EGL-Anweisung add die Werte der Felder in einem Datensatz in die zugeordnete Tabellenspalte ein. Wenn die Datensatzvariable ein Feld enthält, für das keine Tabellenspalte zugeordnet wurde, erstellt EGL die implizite SQL-Anweisung unter der Annahme, dass der Name des Felds dem Namen der Spalte entspricht.

Die folgenden EGL-Anweisungen entsprechen den aufgeführten SQL-Anweisungen:

Tabelle 2. Implizite SQL-Anweisungen
EGL-Anweisung SQL-Anweisung
add INSERT
delete DELETE
get, open SELECT
replace UPDATE

Implizite SELECT-Anweisungen

Beim Definieren einer EGL-Anweisung, die eine Datensatzvariable verwendet und entweder eine SQL-Anweisung SELECT oder eine Cursordeklaration generiert, stellt EGL eine implizite SQL-Anweisung SELECT bereit. Diese Anweisung ist in die Cursordeklaration eingebettet (sofern vorhanden). Sie könnten beispielsweise eine Variable deklarieren, die auf dem folgenden SQLRecord-Abschnitt basiert:
  Record Employee type sqlRecord
    { tableNames = [["EMPLOYEE"]],
      keyItems = ["empnum"] }
    empnum decimal(6,0);
    empname char(40);
  end
Als nächstes deklarieren Sie eine Variable, die auf diesem Datensatz basiert:
myEmpRecord Employee;
Anschließend können Sie den Code für eine Anweisung get schreiben:
  get myEmpRecord;
Die implizite SQL-Anweisung SELECT sieht wie folgt aus:
  SELECT empnum, empname
  FROM   EMPLOYEE
  WHERE  empnum = :empnum
Ferner fügt EGL eine INTO-Klausel in die eigenständige Anweisung SELECT (wenn keine Cursordeklaration beteiligt ist) oder in die Anweisung FETCH ein, die dem Cursor zugeordnet ist. Die INTO-Klausel listet die Hostvariablen auf, die Werte aus den in der ersten Klausel der Anweisung SELECT aufgelisteten Spalten empfangen:
  INTO :empnum, :empname
Die implizite Anweisung SELECT liest jeden Spaltenwert in die entsprechende Hostvariable, referenziert die in der Datensatzvariablen angegebenen Tabellen und verfügt über eine Suchbedingung (eine WHERE-Klausel), die von der Kombination zweier Faktoren abhängt:
  • Dem Wert, den Sie für die Datensatzeigenschaft defaultSelectCondition angegeben haben.
  • Einer Beziehung (z. B. eine Gleichheit) von zwei Wertegruppen:
    • Namen von Spalten, die die Tabellenschlüssel bilden.
    • Werte der Hostvariablen, die die Satzschlüssel darstellen.
    EGL leitet die Beziehung aus der Datensatzeigenschaft tableNames oder der usingKeys-Klausel der EGL-Anweisung ab.

Einzelheiten zu impliziten SELECT-Anweisungen finden Sie in den verschiedenen Themen zu Schlüsselwörtern im Handbuch EGL Language Reference+++.

SQL-Datensätze mit Cursorn

Bei Verwendung von SQL-Datensätzen können Anweisungen zur Cursorverarbeitung unter Verwendung derselben Datensatzvariablen in mehreren EGL-Anweisungen zueinander in Beziehung gesetzt werden. Die Vorgehensweise entspricht dabei weitgehend der Verwendung einer Ergebnismengen-ID. Eine über eine Ergebnismengen-ID angegebene anweisungsübergreifende Beziehung hat jedoch Vorrang vor einer über die Datensatzvariable angegebene Beziehung; in einigen Fällen muss eine Ergebnismengen-ID (resultSetID) angegeben werden.

Darüber hinaus kann für eine bestimmte Datensatzvariable nur ein Cursor geöffnet sein. Wenn eine EGL-Anweisung einen Cursor öffnet, solange ein anderer Cursor für dieselbe Datensatzvariable geöffnet ist, wird der erste Cursor automatisch vom generierten Code geschlossen.

Anpassung von SQL-Anweisungen

Im Falle einer EGL-Anweisung, die als E/A-Objekt eine SQL-Datensatzvariable verwendet, gibt es zwei mögliche Vorgehensweisen:
  • Übernehmen Sie die implizite SQL-Anweisung. In diesem Fall haben Änderungen des SQLRecord-Abschnitts Auswirkungen auf die SQL-Anweisungen, die zur Laufzeit verwendet werden. Wenn Sie beispielsweise später angeben, dass ein anderes Feld als Schlüssel für den SQL-Datensatz verwendet werden soll, ändert EGL die implizite Anweisung SELECT in jeder Cursordeklaration, die auf diesem SQLRecord-Abschnitt basiert.
  • Geben Sie an, dass die SQL-Anweisung explizit sein soll. EGL kann die implizite SQL-Anweisung in Ihren Code einfügen, sodass Sie diese ändern können. In diesem Fall sind die Details dieser SQL-Anweisung vom SQLRecord-Abschnitt getrennt; nachfolgende Änderungen des SQLRecord-Abschnitts haben keine Auswirkungen auf die SQL-Anweisung, die zur Laufzeit verwendet wird.

    Wenn Sie eine explizite SQL-Anweisung aus der Quelle entfernen, ist die implizite SQL-Anweisung (sofern vorhanden) bei der Generierung erneut verfügbar.

Beispiel für die Verwendung eines Datensatzes in einem Datensatz

Um einem Programm das Abrufen von Daten für eine Reihe von Mitarbeitern in einer Abteilung zu ermöglichen, können Sie zwei SQLRecord-Abschnitte und eine Funktion erstellen:
DataItem DeptNo { column = "deptNo" } end

Record Dept type SQLRecord
   deptNo DeptNo;
   managerID CHAR(6);
   employees Employee[];
end

Record Employee type SQLRecord
   employeeID CHAR(6);
   empDeptNo DeptNo;
end

Function getDeptEmployees(myDeptRecord Dept)
   get myDeptRecord.employees usingKeys myDeptRecord.deptNo;
end

Test und Einstellung für Nullwerte

Wenn eine Variable nullfähig sein soll (d. h. Nullwerte werden akzeptiert), müssen Sie die Variable mit dem Erweiterungszeichen ? deklarieren:
Record Employee type SQLRecord
   employeeID CHAR(6);
   empDeptNo INT?;
end
Verwenden Sie zum Testen auf Nullwerte eine EGL-Standardanweisung if:
if (myEmpRecord.empDeptNo == null)
   ...
end
Ein Nullwert kann einer Variablen direkt zugeordnet werden:
myEmpRecord.empDeptNo = null;
Die Syntax funktioniert, auch wenn das Ziel nicht nullfähig ist. In diesem Fall hat die Anweisung dieselben Auswirkungen wie die folgende Anweisung:
set myEmpRecord.empDeptNo empty;

Kompatibilität

Tabelle 3. Hinweise zur Kompatibilität für SQL
Plattform Problem
CICS für z/OS, z/OS-Stapelbetrieb, iSeriesC Der generierte Code kann direkt auf DB2 UDB zugreifen.
AIX, HP-UX, iSeriesJ, Linux, Solaris, z/OS UNIX System Services, Windows 2000/NT/XP JDBC bietet Zugriff auf DB2 UDB, Oracle, Informix und Microsoft SQL Server.

Feedback