Anmelden

View Full Version : dynamisches SQL mit Clob möglich?



Seiten : [1] 2

msost
05-04-17, 10:45
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?

Fuerchau
05-04-17, 12:41
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.

msost
05-04-17, 15:26
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?

Fuerchau
05-04-17, 16:00
Nach dem Fetch mit einem "exec sql Set ...;" den Lob-Locator dann auslesen, a) Hostvariable, b) xLOB_FILE.

msost
06-04-17, 13:36
Danke! Nach etwas Kampf mit der Definition des Locators läuft's jetzt.

Fuerchau
06-04-17, 14:29
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.

msost
06-04-17, 15:16
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;

Fuerchau
07-04-17, 08:14
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.

BenderD
07-04-17, 09:14
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

Fuerchau
07-04-17, 09:26
"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.