View Full Version : dynamisches SQL mit Clob möglich?
Hallo zusammen,
offensichtlich kann man EXECUTE IMMEDIATE mit zusammengebauten String im embedded SQL nicht verwenden, wenn die Datei ein Clob Feld enthält und man beim INTO eine Variable die ein XML_CLOB_FILE ist verwendet
DCL-S XmlDoc SQLTYPE(XML_CLOB_FILE)
EXEC SQL
SELECT XMLDOCUMENT(XMLGROUP(
FELDA as "Erstes"
FELDB as "Zweites"
FELDC as "Drittes"
))
INTO :XmlDoc From MyFile;
Hat jemand eine Idee, wie ich die Feldauswahl im Select und die Auswahl des From Files (oder natürlich den kompletten SQL-String) variabel halten kann?
Execute Immediate geht da leider nicht.
Du musst den Umweg über einen Cursor mit Open/Fetch/Close nehmen.
Per Declare Cursor for Statement und Prepare machst du einen dynamischen Cursor.
Dein Fetch kann dann wieder statisch sein solange die Ergebnisspalten passen.
Wie in deinen anderen Threads schon beschrieben musst du aber hier den Umweg über CLOB_LOCATOR gehen und kannst dann den Inhalt in eine CLOB_FILE kopieren.
Ich muß leider nochmal nachfragen:
- Clob-Locator definieren ist klar
- DECLARE CURSOR für den auszuführenden SELECT. ok.
- OPEN vom Cursor. auch ok.
- Dann FETCH vom Cursor. Bei into den CLob-Locator verwenden, korrekt?
Fehlt noch was?
Nach dem Fetch mit einem "exec sql Set ...;" den Lob-Locator dann auslesen, a) Hostvariable, b) xLOB_FILE.
Danke! Nach etwas Kampf mit der Definition des Locators läuft's jetzt.
Nun wäre es noch nett, wenn du die funktionierende Lösung (zumindest den SQL und RPG-Teil) hier darstellen und erklären würdest. Dies könnte anderen dann ebenso hilfreich sein.
Ich steuere ledglich Denkanstöße bei, zum Programmieren solcher Aktionen fehlt mir einfach die Zeit.
Ja, gerne.
1.) Definieren der XML-CLOB-Datei (Streamfile im IFS), eines XML-CLOB Felds als Host-Variable und des Locators als Zeiger.
DCL-S IXMLDoc SQLTYPE(XML_CLOB_FILE);
DCL-S IXMLDta SQLTYPE(XML_CLOB:1024);
DCL-S IXMLLoc SQLTYPE(XML_LOCATOR);
2.) Setzen des Zielpfads und des Dateinamens im IFS, durch die CLOB-Datei Definitionsfelder
DCL-S Xmlpath char(30) inz('/mydir/sql/out/');
IXMLDoc_Name = %trim(Xmlpath) + %trim(FileGroup) + '_' +
%trim(FileId) + '.xml';
IXMLDoc_NL = %Len(%Trim(IXMLDoc_Name));
IXMLDoc_FO = SQFOVR;
3.) Bauen des Selektions-Strings in einer Variablen
sqlstring = 'SELECT XMLDOCUMENT(XMLGROUP(TRIM(Fielda) AS "Host", +
TRIM(Fieldb) AS "Environ", TRIM(Fieldc) AS "Country" +
OPTION ROW "Testrow" ROOT "Testroot")) FROM File';
4.) SQL optionen nach Bedarf setzen
EXEC SQL
Set Option Datfmt=*iso, TimFmt=*iso,Naming=*sys,
CloSQLCsr=*EndActGrp;
5.) SQL Cursor definieren unter Verwendung der obigen Variablen
EXEC SQL
PREPARE selectstm FROM :sqlstring;
6.) Statisch können dann der SQL DECLARE, OPEN des Cursors, FETCH und SET bleiben.
EXEC SQL
DECLARE INXML CURSOR FOR selectstm;
EXEC SQL
OPEN INXML;
EXEC SQL
FETCH NEXT FROM INXML
INTO :IXMLLoc;
EXEC SQL
SET :IXMLDta = :IXMLLoc;
EXEC SQL
SET :IXMLDoc = :IXMLLoc;
EXEC SQL
CLOSE INXML;
Da ein Locator einen SQL-internen Speicherbereich belegt so musst du, wenn du ihn nicht mehr benötigst, mittels "FREE LOCATOR : MyLoc;" auch wieder freigeben.
Ansonsten läuft dein temporärer Speicher ziemlich voll. Wenn das viele Jobs machen und jeder Job mal so eben 1000de Lobs á 1GB erstellt ist abzusehen, wann deine AS/400 runterfährt.
Ein Fetch in einen belegten Locator impliziert keine Freigabe.
Execute Immediate geht da leider nicht.
Du musst den Umweg über einen Cursor mit Open/Fetch/Close nehmen.
Per Declare Cursor for Statement und Prepare machst du einen dynamischen Cursor.
Dein Fetch kann dann wieder statisch sein solange die Ergebnisspalten passen.
Wie in deinen anderen Threads schon beschrieben musst du aber hier den Umweg über CLOB_LOCATOR gehen und kannst dann den Inhalt in eine CLOB_FILE kopieren.
... der execute immediate scheitert daran, dass keine Variablen verwendet werden können. Prepare mit nachfolgendem execute using sollte allerdings auch ohne cursor und fetch ebenfalls gehen.
D*B
"Execute ... Using" gilt leider nur für Parametermarker.
MyStmt = "Select ... where f1=?";
prepare ...
execute ... using MyVar;
Um Ergebnisse zu erhalten geht das nur per Descriptor (SQLDA mit SQLVAR-Array).
Wer sich das zutraut kann das verwenden. Dies ist dann vielleicht schneller als Open/Fetch/Close.