Überlegungen zu 'prepare' mit SQL

Die EGL-Anweisung 'prepare' generiert eine SQL-Anweisung PREPARE und ermöglicht es Ihnen, bei Bedarf Details einzuschließen, die nur zur Ausführungszeit bekannt sind. Führen Sie den vorbereiteten SQL-Code mit einer EGL-Anweisung 'execute' oder (wenn der SQL-Code eine Ergebnismenge zurückgibt) mit einer EGL-Anweisung 'open' oder 'get' aus.

Syntax

Syntaxdiagramm für die Anweisung 'prepare'
ID_der_vorbereiteten_Anweisung
Eine von Ihnen ausgewählte Zeichenfolge zwecks Angabe des SQL-Codes, der von der Anweisung 'prepare' zur Ausführungszeit erstellt wird. Sie können diese ID dann mit der EGL-Anweisung execute, open oder get verwenden.
Zeichenfolgenausdruck
Eine gültige SQL-Anweisung im Format eines Zeichenfolgenausdrucks. Kennzeichnen Sie Literalzeichenfolgen durch Fragezeichen und verwenden Sie den Operator '::', um diese Literalzeichenfolgen mit Zeichenfolgevariablen zu kombinieren (siehe 'Beispiele' in diesem Thema).
SQL-Datensatzvariable
Der Name einer SQL-Datensatzvariablen. Der EGL-Editor kann Hinweise zum Erstellen von Zeichenfolgeausdrücken liefern (siehe Content-Assist im Handbuch für EGL-Programmierer). Sie können diesen Namen auf Fehlerbedingungen überprüfen (siehe 'Beispiele' in diesem Thema).

Dynamisches SQL und die Anweisung 'prepare'

Die Anweisung 'prepare' ist die Standardmethode zur Verarbeitung von dynamischem SQL. Der von Ihnen angegebene Zeichenfolgeausdruck kann Variablen enthalten, deren Werte nur zur Ausführungszeit bekannt werden und leistungsfähige Optionen für Ihr Programm bereitstellen.

Eine allgemeine Art der Verwendung von dynamischem SQL sind vom Benutzer gesteuerte Abfragen. So könnten Benutzer beispielsweise Kontrollkästchen auswählen, um Informationen in einen Bericht einzuschließen. Außerdem könnten Sie mithilfe einer WHERE-Klausel festlegen, welche Kundendatensätze vom Programm angezeigt werden. In beiden Fällen wissen Sie nicht im Voraus, welche Daten der Benutzer auswählt.

Sie können auch Fragezeichen als Platzhalter für Hostvariablen in dem Zeichenfolgeausdruck verwenden (siehe Hostvariablen). Wenn Sie die vorbereitete Anweisung ausführen, listen Sie diese Variablen als Teil einer using-Klausel in der Anweisung 'prepare', 'get' oder 'open' auf. Dieser Prozess wird im zweiten Beispiel gezeigt. Sie müssen Hostvariablen für alle als Platzhalter verwendeten Fragezeichen angeben und darüber hinaus wissen, wofür diese Variablen verwendet werden.

Beispiele

Im folgenden Beispiel wird eine Zeichenfolge dynamisch auf Basis der vom Benutzer aus einem Menü ausgewählten Elemente erstellt:
query STRING;
fieldName STRING; 
isFirstField BOOLEAN;  

query = "SELECT "; 
isFirstField = true; 

// die Funktion stellt die vom Benutzer ausgewählten Feldnamen bereit 
// der Rückgabewert ist '-1', wenn alle verwendet werden 
while ((nextFieldName(fieldName)) == 0)  // setzt 'fieldName'
   if (!isFirstField)  // bei mehr als einem Feld in SELECT
      query ::= ", ";
   end
   query ::= fieldName;
   isFirstField = false; 
end // Ende von 'while' 

// Fertigstellung der Abfrage 
query ::= "FROM Customer WHERE customer_number = ?"; 
prepare myPreparedStatement from query;
Testen Sie nach Ausführung der Anweisung 'prepare' den Datensatznamen auf einen E/A-Fehlerwert, um zu ermitteln, ob die Anweisung erfolgreich war, wie im nachstehenden Beispiel. In diesem Beispiel werden Fragezeichen als Platzhalter für Hostvariablen verwendet (siehe Hostvariablen):
  try
    prepare prep01 from  
     "INSERT INTO " :: aTableName :: 
     "(customer_number, customer_name) " ::
     "VALUE ?, ?"
     for myCustomer;

  onException(sqlEx SQLException)
    if (myCustomer is unique)
      myErrorHandler(8);
    else
      myErrorHandler(sqlEx);
    end
  end
  
  try
    execute myStatement 
    using myRecord.empnum,
          myRecord.empname;
  onException(sqlEx SQLException)
    myErrorHandler(sqlEx);
  end

Wie in den vorherigen Beispielen gezeigt, können Sie ein Fragezeichen (?) anstelle einer Hostvariablen verwenden. Der Name der Hostvariablen, die zur Ausführungszeit verwendet wird, wird in die using-Klausel der Anweisung 'execute', 'open' oder 'get' gestellt, die die vorbereitete Anweisung ausführt.

Eine Anweisung 'prepare', die für eine Zeile einer Ergebnismenge ausgeführt wird, kann eine Phrase im Format 'WHERE CURRENT OF Ergebnismengen-ID' einschließen. Dieses Verfahren ist nur dann gültig, wenn die folgenden Bedingungen zutreffen:
  • Die Phrase ist in einem Literal codiert.
  • Die Ergebnismenge ist bei Ausführung der Anweisung 'prepare' geöffnet.
Unter der Annahme, dass X1 die Ergebnismengen-ID aus der Anweisung 'open' ist, erstellt das folgende Beispiel eine dynamische vorbereitete Anweisung und führt diese aus:
	 prepare prep02 from
    "update myTable " ::
    "set empname = ?,  empphone = ?  where current of x1" ;
 
  execute prep02 using empname, empphone;
  freeSQL prep02;

Kompatibilität

Tabelle 1. Hinweise zur Kompatibilität für 'prepare'
Plattform Problem
COBOL-Generierung und -Debugging In einer dynamischen vorbereiteten SQL-Anweisung müssen Sie alle Kennungen und SQLRecord-Variablen in derselben Funktion deklarieren, in der diese Kennungen und Variablen referenziert und verwendet werden. Diese Einschränkung gilt nicht für Java™-Generierung, bei der die Kennungen überall im Namensbereich stehen können.
Java-Generierung Wenn der Zeichenfolgeausdruck, auf dessen Basis die Anweisung vorbereitet wird, aus irgendeinem Grund nicht gültig ist, kann es sein, dass die Anweisung 'prepare' dennoch nicht fehlschlägt. Stattdessen ist es möglich, dass EGL beim ersten Versuch, die vorbereitete Anweisung zu verwenden, eine SQL-Ausnahmebedingung (SQLException) auslöst.
Es könnte ein Problem auftreten, wenn Sie einen JDBC-Treiber von Oracle verwenden, um Code zu bearbeiten, der wie folgt strukturiert ist:
   prepare q from "select a, b from c where myColumn > ?";
   get into x, y with q using myVar;

Das Problem ist folgendes: Um sicherzustellen, dass Zeilen abgerufen werden, müssen Sie unter Umständen die Länge der Variablen auf dieselbe Länge setzen, die für die Datenbankspalte verwendet wird.

Im folgenden Fall werden keine Zeilen abgerufen:
  • Eine Anweisung 'prepare' schließt eine SQL-Anweisung SELECT mit einer WHERE-Klausel ein.
  • Die WHERE-Klausel vergleicht eine Spalte des SQL-Typs CHAR mit einer Hostvariablen.
  • In der Anweisung, von der die vorbereitete Anweisung ausgeführt wird, hat die Hostvariable den EGL-Typ CHAR.
  • Die Länge der Datenbankspalte weicht von der Länge der Variablen ab.
  • Sie verwenden einen JDBC-Treiber von Oracle.

Als diese Informationen geschrieben wurden, war das Problem in Abschnitt 11.3.7.4 auf der folgenden Website dokumentiert: http://download.oracle.com/docs/cd/B14117_01/java.101/b10979/datacc.htm.


Feedback