[NEWSboard IBMi Forum]
Seite 1 von 2 1 2 Letzte
  1. #1
    Registriert seit
    Aug 2002
    Beiträge
    77

    Question Brauche Hilfe zu FETCH xxx USING DESCRIPTOR

    Hallo zusammen.
    Ich bin am verzweifeln beim Zusammenbauen eines dynamischen SQL Statements.
    Ich habe eine SQLDA entsprechend SQL Reference aufgebaut.
    Hier, was im Beispiel des Handbuches steht (leider ist das Beispiel für PL1, aber der Unterschied scheint nur im "fehlenden" END-EXEC zu bestehen...

    EXEC SQL PREPARE STMT1_NAME FROM :STMT1_STR;

    ... /* code to set SQLN to zero and to allocate the SQLDA */
    EXEC SQL DESCRIBE STMT1_NAME INTO :SQLDA;

    ... /* code to check that SQLD is greater than zero, to set */
    /* SQLN to SQLD, then to re-allocate the SQLDA */
    EXEC SQL DESCRIBE STMT1_NAME INTO :SQLDA;

    ... /* code to prepare for the use of the SQLDA */
    EXEC SQL OPEN DYN_CURSOR;

    ... /* loop to fetch rows from result table */
    EXEC SQL FETCH DYN_CURSOR USING DESCRIPTOR :SQLDA;

    Hier nun mein Sorgenkind
    D SQL_NUM C CONST(2)
    D SQLDA DS
    D SQLDAID 1 8A
    D SQLDABC 9 12B 0
    D SQLN 13 14B 0
    D SQLD 15 16B 0
    D SQL_VAR 80A DIM(SQL_NUM)
    D SQLVAR DS
    D SQLTYPE 1 2B 0
    D SQLLEN 3 4B 0
    D SQLRES 5 16A
    D SQLDATA 17 32*
    D SQLIND 33 48*
    D SQLNAMELEN 49 50B 0
    D SQLNAME 51 80A
    C*SQL_NUM ist die hier benutze Anzahl Felder
    STMT='SELECT FELD1, FELD2 FROM DATEI'

    C/EXEC SQL
    C+ PREPARE S1 FROM :SQLSTMT
    C/END-EXEC

    SQLN = *ZEROS

    C/EXEC SQL
    C+ DESCRIBE S1 INTO :SQLDA
    C/END-EXEC


    IF SQLD<= 0
    return
    endif
    sqln = sqld

    C/EXEC SQL
    C+ DESCRIBE S1 INTO :SQLDA
    C/END-EXEC
    C* Jetzt steht nach debug tatsächlich sauber in der SQLDA die "Feldinfo" in der SQL_VAR Tabelle. Die Pointer SQLDATA und SQLIND sind nicht *NULL!

    C* Open Cursor
    C/EXEC SQL
    C+ OPEN C1
    C/END-EXEC

    C dow sqlcod = 0
    * Fetch a row
    C/EXEC SQL
    C+ FETCH NEXT FROM C1 USING DESCRIPTOR :SQLDA
    C/END-EXEC
    C SQLCOD IFNE 0
    C LEAVE
    C ENDIF
    C ENDDO
    C/EXEC SQL
    C+ close c1
    C/END-EXEC
    C MOVE *ON *INLR


    Nach dem Fetch ist der SQL Code auf -822.
    Im Joblog steht:
    PREPARE für Anweisung S1 beendet
    DESCRIBE für vorbereitete Anweisung S1 beendet
    DESCRIBE für vorbereitete Anweisung S1 beendet
    Blockung für Abfrage
    Cursor C1 eröffnet
    SQLDA enthält ungültige Adresse
    -- Art 1 gibt an, daß die SQLDATA-Adresse ungültig ist

    Ich hab nun schon versucht, einfach pointer einzustellen, die auf eine leer DS weisen, aber das bringts auch nicht. Hat jemand von euch/Ihnen ein Beispielprogramm oder einen Tip, was da mit "allocate SQLDA" und reallocate SQLDA gemeint ist und wie das funktioniert??

    Verwendetes Release in V4R5

    Danke
    Andreas
    ***Wer einen Schreibfehler findet darf ihn behalten***

  2. #2
    Registriert seit
    Jan 2001
    Beiträge
    833

    Wink

    Hallo,

    ich arbeite bei dynamischen SQl immer
    mit einem Array welches zur Laufzeit
    zusammengebastelt wird. Das funktuioniert eigentlich prima.

    Hoffentlich kannst Du damit etwas anfangen
    gruss Michael
    Hier ein Auszug aus einem RPG Programm:
    * ------------------------------------------------------------
    * SQL SELECTION
    * ------------------------------------------------------------
    D SL S 1 DIM(1600)
    D SELCT1 S 80 DIM(20) CTDATA PERRCD(1)

    D SELECT DS 1600

    C LodSqlData BEGSR
    C/EXEC SQL
    C+ PREPARE SELECTION FROM :SELECT
    C/END-EXEC
    *
    C/EXEC SQL
    C+ DECLARE SqlFile SCROLL CURSOR FOR SELECTION
    C/END-EXEC
    *
    C/EXEC SQL
    C+ OPEN SqlFile
    C/END-EXEC


    C ENDSR




    001 c Dou Sqlcod <> *Zeros
    001 C/EXEC SQL
    001 C+ FETCH NEXT FROM SqlFile INTO S_Cusumrp
    001 C/END-EXEC
    001 *
    002 c If Sqlcod = *Zeros
    c Endif

    c Enddo

    C ENDSR
    o


    ** ** SELECTION für Sql Anweisung **
    Select *


    from Lib/Datei

    Where
    Feld1 = 'xxx'
    and Feld2 = 1998

    Order by Feld1, Feld2

  3. #3
    Registriert seit
    Aug 2002
    Beiträge
    77

    Post

    -> Michael
    Danke für die schnelle Anwort.
    Wie hast du DS_cusumrp definiert?
    Andreas
    ***Wer einen Schreibfehler findet darf ihn behalten***

  4. #4
    Registriert seit
    Jan 2001
    Beiträge
    833

    Cool

    Hallo,

    Die DS_Cusumrp ist die externe Datenstruktur
    einer PF. da in diesem SQl alle Felder der
    PF mit SQL gelesen wurden. Damit erspart man
    sich das lästige coden bei dem Fetch.

    gruss michael

    PS: Klappt es denn ?

    Danke für die schnelle Anwort.
    Wie hast du DS_cusumrp definiert?[/B][/QUOTE]


  5. #5
    Registriert seit
    Aug 2002
    Beiträge
    77

    Post

    -> Michael
    Ich muss mit variabler Abfrage arbeiten, weil ich nicht weiss, welche Felder der Anwender auswählt. Wenn ich also eine starre Datenstruktur benutze bekomme ich einen Abbruch wegen falscher Feldformate.
    Daher ja das describe (schreibt mir zur Laufzeit die angeforderten Felder und typen in die SQLDA zurück. Klappt also nicht :-(
    Andreas
    ***Wer einen Schreibfehler findet darf ihn behalten***

  6. #6
    Registriert seit
    Jan 2001
    Beiträge
    833

    Post

    Hallo Andreas,

    Habe ich das richtig verstanden, dass dein
    Fetch je nach Auswahl verschiedene Felder bringen soll ?

    Mit einem ARRAY im RPG könntest Du das Select Statement ja variabel aufbauen.

    Du könntest dann vielleicht je nach Auswahl
    verschieden Fetch Routinen machen.(Hm müsste klappen)

    gruss michael

  7. #7
    Registriert seit
    Feb 2001
    Beiträge
    20.241

    Post

    Variable SQL's gestalten sich nun mal schwierig.

    Mit dem "Describe" erhält man eine SQLDA-Struktur, die die Feldtypen und Größen enthält.
    Das Feld "SQLN" muss mit der Anzahl der Strukturfelder "SQLVAR" initialisiert werden.
    Das Feld "SQLD" enthält NACH dem Describe die Anzahl Felder in dem Array.

    Das Strukturfeld SQLVAR definiert man ambesten so:
    D SQLVAR 80A DIM(200)
    D SQLTYPE _ 2 B 0 OVERLAY(SQLVAR:1)
    D SQLLEN _ 4 B 0 OVERLAY(SQLVAR:3)
    D SQLDATA ___ * _ OVERLAY(SQLVAR:17)
    :
    :

    Dadurch lassen sich die Felder auch mit ihrem Index ansprechen, z.B. "SQLTYPE(Ind)".

    Kommen wir nun zum "Fetch ... USING Descriptor :SQLDA"

    Der Describe setzt keine Adressen in den Pointern !!!

    Das muss das Programm selbst erledigen.
    D.H., mit der Anweisung ALLOC können Sie dynamischen Speicher zuordnen und der SQLDATA(n) zuweisen.
    Dies muss für jedes Feld erfolgen.
    Zu berücksichtigen sind da vor allem auch die Feldtypen (eine Liste ist im Handbuch der CD Library enthalten).
    Man kann die Feldtypen auch vorgeben, SQL wandelt diese dann entsprechend um.

    Erst dann ist ein Fetch möglich !

    Da das ganze Thema ziemlich aufwändig ist, und hier der Ort für eine Schulung nicht der richtige ist, verweise ich auf das Handbuch "DB2 for AS/400 SQL Programming".
    Dienstleistungen? Die gibt es hier: http://www.fuerchau.de
    Das Excel-AddIn: https://www.ftsolutions.de/index.php/downloads
    BI? Da war doch noch was: http://www.ftsolutions.de

  8. #8
    Registriert seit
    Aug 2001
    Beiträge
    2.873

    Post

    Hallo Andreas,

    was hälst Du davon, alle möglichen Ausgabe-Felder in einer Datenstruktur zu definieren?
    Diese Datenstruktur wird dann beim Fetch komplett gefüllt.
    Im RPG-Programm kannst Du ja dann nur die ausgewählten Felder mit dem entsprechenden Inhalt verarbeiten.

    Beispiel: Der Anwender wählt aus einer Datei mit 200 Feldern 10 aus, die angezeigt werden sollen.
    Beim Fetch wird dann der komplette Datensatz ausgegeben.
    Das gleiche geschieht ja auch beim Lesen in RPG. Der komplette Satz ist im Zugriff, obwohl nur einige Felder benötigt werden.

    Bei dieser Verarbeitungsmöglichkeit benötigst Du wahrscheinlich nicht einmal ein dynamisches SQL.
    Select * From File Where ....
    Fetch into DSFILE

    Birgitta
    Birgitta Hauser

    Anwendungsmodernisierung, Beratung, Schulungen, Programmierung im Bereich RPG, SQL und Datenbank
    IBM Champion seit 2020 - 4. Jahr in Folge
    Birgitta Hauser - Modernization - Education - Consulting on IBM i

  9. #9
    Registriert seit
    Aug 2002
    Beiträge
    77

    Post

    Die Lösung von herrn Fuerchau ist es :-)
    Es klappt prima mit einem Loop und ALLOC in der Länge SQLLEN bzw ausgewerteter precision
    Vielen Dank auch an alle anderen für die Hinweise und Tipps!
    Andreas
    ***Wer einen Schreibfehler findet darf ihn behalten***

  10. #10
    Registriert seit
    Mar 2006
    Beiträge
    98
    Zitat Zitat von AndreasH Beitrag anzeigen
    Hallo zusammen.
    Ich bin am verzweifeln beim Zusammenbauen eines dynamischen SQL Statements.
    Ich habe eine SQLDA entsprechend SQL Reference aufgebaut.
    Hier, was im Beispiel des Handbuches steht (leider ist das Beispiel für PL1, aber der Unterschied scheint nur im "fehlenden" END-EXEC zu bestehen...

    EXEC SQL PREPARE STMT1_NAME FROM :STMT1_STR;

    ... /* code to set SQLN to zero and to allocate the SQLDA */
    EXEC SQL DESCRIBE STMT1_NAME INTO :SQLDA;

    ... /* code to check that SQLD is greater than zero, to set */
    /* SQLN to SQLD, then to re-allocate the SQLDA */
    EXEC SQL DESCRIBE STMT1_NAME INTO :SQLDA;

    ... /* code to prepare for the use of the SQLDA */
    EXEC SQL OPEN DYN_CURSOR;

    ... /* loop to fetch rows from result table */
    EXEC SQL FETCH DYN_CURSOR USING DESCRIPTOR :SQLDA;

    Hier nun mein Sorgenkind
    D SQL_NUM C CONST(2)
    D SQLDA DS
    D SQLDAID 1 8A
    D SQLDABC 9 12B 0
    D SQLN 13 14B 0
    D SQLD 15 16B 0
    D SQL_VAR 80A DIM(SQL_NUM)
    D SQLVAR DS
    D SQLTYPE 1 2B 0
    D SQLLEN 3 4B 0
    D SQLRES 5 16A
    D SQLDATA 17 32*
    D SQLIND 33 48*
    D SQLNAMELEN 49 50B 0
    D SQLNAME 51 80A
    C*SQL_NUM ist die hier benutze Anzahl Felder
    STMT='SELECT FELD1, FELD2 FROM DATEI'

    C/EXEC SQL
    C+ PREPARE S1 FROM :SQLSTMT
    C/END-EXEC

    SQLN = *ZEROS

    C/EXEC SQL
    C+ DESCRIBE S1 INTO :SQLDA
    C/END-EXEC


    IF SQLD<= 0
    return
    endif
    sqln = sqld

    C/EXEC SQL
    C+ DESCRIBE S1 INTO :SQLDA
    C/END-EXEC
    C* Jetzt steht nach debug tatsächlich sauber in der SQLDA die "Feldinfo" in der SQL_VAR Tabelle. Die Pointer SQLDATA und SQLIND sind nicht *NULL!

    C* Open Cursor
    C/EXEC SQL
    C+ OPEN C1
    C/END-EXEC

    C dow sqlcod = 0
    * Fetch a row
    C/EXEC SQL
    C+ FETCH NEXT FROM C1 USING DESCRIPTOR :SQLDA
    C/END-EXEC
    C SQLCOD IFNE 0
    C LEAVE
    C ENDIF
    C ENDDO
    C/EXEC SQL
    C+ close c1
    C/END-EXEC
    C MOVE *ON *INLR


    Nach dem Fetch ist der SQL Code auf -822.
    Im Joblog steht:
    PREPARE für Anweisung S1 beendet
    DESCRIBE für vorbereitete Anweisung S1 beendet
    DESCRIBE für vorbereitete Anweisung S1 beendet
    Blockung für Abfrage
    Cursor C1 eröffnet
    SQLDA enthält ungültige Adresse
    -- Art 1 gibt an, daß die SQLDATA-Adresse ungültig ist

    Ich hab nun schon versucht, einfach pointer einzustellen, die auf eine leer DS weisen, aber das bringts auch nicht. Hat jemand von euch/Ihnen ein Beispielprogramm oder einen Tip, was da mit "allocate SQLDA" und reallocate SQLDA gemeint ist und wie das funktioniert??

    Verwendetes Release in V4R5

    Danke
    Hallo,

    ich habe auch so ein ähnliches Problem, ich will die sqlda nutzen.

    was ist da falsch definiert????
    Folgender Fehler bekomme ich bei RDI wen ich es kompilieren will.



    RNF7433 Zeigerunterfeld SQLDATA ist nicht korrekt ausgerichtet; die Bestimmung wird ignoriert.
    RNF7433 Zeigerunterfeld SQLIND ist nicht korrekt ausgerichtet; die Bestimmung wird ignoriert.
    RNF0533 Die Länge von Feld SQLLEN mit ganzer Zahl oder ohne Vorzeichen ist ungültig.

    D* SQL DESCRIPTOR AREA
    D SQLDA DS
    D SQLDAID 8A
    D SQLDABC 10I 0
    D SQLN 5I 0
    d SQLD 5I 0
    D SQL_VAR 80A DIM(SQL_NUM)
    D 33 48*
    D 49 64*
    D***
    D SQLVAR DS
    D SQLTYPE 5I 0
    D SQLLEN 6I 0
    D SQLRES 12A
    D SQLINFO1 16A
    D SQLDATA * OVERLAY(SQLINFO1:1)
    D SQL_RESULT_SET_LOCATOR...
    D 20I 0 OVERLAY(SQLINFO1:1)
    D SQLINFO2 16A
    D SQLIND * OVERLAY(SQLINFO2:1)
    D SQL_ROW_CHANGE...
    D 10I 0 OVERLAY(SQLINFO2:1)
    D SQL_RESULT_SET_ROWS...
    D 10I 0 OVERLAY(SQLINFO2:1)
    D SQLNAMELEN 5I 0
    D SQLNAME 30A
    D** END OF SQLDA
    D** EXTENDED SQLDA
    D SQLVAR2 DS
    D SQLLONGL 1 4I 0
    D SQLRSVDL 5 32A
    D SQLDATAL 33 48*
    D SQLTNAMELN 49 50I 0
    D SQLTNAME 51 80A
    D** END OF EXTENDED SQLDA
    D sql_num c const(80)
    D** End of SQLDA
    D***

    EXEC SQL
    INCLUDE SQLDA;
    EXEC SQL
    set option datfmt=*iso;
    EXEC SQL
    PREPARE SELECTION FROM :stm ;
    EXEC SQL
    declare C1 cursor for selection ;
    EXEC SQL
    OPEN C1 ;

    dou sqlcod = 100 ;
    EXEC SQL
    FETCH C1 USING DESCRIPTOR :SQLDA ;
    if sqlcod = 100; // €Dateiende
    leave ;
    endif ;

    if sqlcod < *Zeros ;
    and sqlcod <> -801 ;
    leave ;
    endif ;


    enddo ;
    EXEC SQL
    CLOSE C1 ;

  11. #11
    Registriert seit
    Feb 2001
    Beiträge
    20.241
    Schau dir die Definition der SQLDA und SQLVAR in der QSYSINC (oder im Handbuch) mal an.
    Irgendwo fehlen noch Reserve-Definitionen.
    Das Problem:
    Pointer müssen an einer 16-Byte-Grenze ausgerichtet sein!
    Dienstleistungen? Die gibt es hier: http://www.fuerchau.de
    Das Excel-AddIn: https://www.ftsolutions.de/index.php/downloads
    BI? Da war doch noch was: http://www.ftsolutions.de

  12. #12
    Registriert seit
    Mar 2002
    Beiträge
    5.287
    ...das macht der Compiler, falls man ihn nicht dran hindert und die Pointer in DS definiert. Im letzteren Fall heisßt das Zauberwort align

    D*B
    AS400 Freeware
    http://www.bender-dv.de
    Mit embedded SQL in RPG auf Datenbanken von ADABAS bis XBASE zugreifen
    http://sourceforge.net/projects/appserver4rpg/

Similar Threads

  1. Frei Porn Site!
    By Fucasdreh in forum NEWSboard Server Job
    Antworten: 0
    Letzter Beitrag: 10-01-07, 13:12
  2. Brauche Hilfe
    By kuempi von stein in forum NEWSboard Java
    Antworten: 3
    Letzter Beitrag: 07-07-06, 16:03
  3. Brauche hapi_c.h und Hilfe bei Prog.
    By chullain in forum IBM i Hauptforum
    Antworten: 2
    Letzter Beitrag: 29-03-06, 09:18
  4. Brauche Hilfe zu FETCH USING DESCRIPTOR
    By AndreasH in forum NEWSboard Programmierung
    Antworten: 0
    Letzter Beitrag: 27-08-02, 09:41
  5. Brauche Hilfe im DDS
    By hs in forum IBM i Hauptforum
    Antworten: 6
    Letzter Beitrag: 26-09-01, 09:02

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • You may not post attachments
  • You may not edit your posts
  •