[NEWSboard IBMi Forum]
  1. #1
    Registriert seit
    Apr 2004
    Beiträge
    105

    Embedded SQL Kommando

    Hallo,
    Ich führe in einem PGM ein Embedded SQL Statement (ich arbeite mit eienm Cursor) aus,
    das mir leider kein Ergebnis zurückliefert.

    Code:
     
    SqlStm =  'SELECT PROGPW, AUSFPW, IDNRPL, ANGBPL, 
    PNAMPW, HOLZPW, KZ05PW, KZ06PW, AUSNPW, AUSDPW, DTNEPW 
    From RBPFILE/PRGSTP 
    Inner Join PRGLEP On PROGPW = PROGPL
         And AUSFPW = AUSFPL
    Where STATPW = ''A'' 
    Order by PROGPW, AUSFPW, IDNRPL, ANGBPL 
    For read only'
    Hier möchte ich gerne dynamische Selektierungen einbauen:

    Code:
    DPROG             S            100    Inz(' and PROGPW  = :PROGD0')
    DAUSF             S            100    Inz(' and AUSFPW  = :AUSFD0')
    DIDNR             S            100    Inz(' and IDNRPL  = :IDNRD0')
    DANGB             S            100    Inz(' and ANGBPL  = :ANGBD0')
    
    
    if        PROGD0 <>  '   '       
    eval      cmd = %trim(cmd) + PROG
    endif                            
    if        AUSFD0 <> '    '       
    eval      cmd = %trim(cmd) + AUSF
    endif                            
    if        IDNRD0 <> 0            
    eval      cmd = %trim(cmd) + IDNR
    endif                            
    if        ANGBD0 <>  '   '       
    eval      cmd = %trim(cmd) + ANGB
    endif
    Das SqlStm habe ich entsprechend geändert:

    Code:
     
    ...
    Where STATPW = ''A'' '
    + ':cmd' +
    'Order by
    ...
    Es klappt ohne den cmd-Teil, aber warum nicht mit?
    Kann mir jemand helfen?

  2. #2
    Registriert seit
    Feb 2001
    Beiträge
    20.243
    Bei embedded SQL können Parameter (:FELD) nicht als Variablen eingesetzt werden, da Parameter bereits durch den Precompiler in Felder aufgelöst werden (Umwandlungsliste).
    Wenn du dynamische SQL's zusammenbauen willst, musst du den gesamten Select in einer Variablen zusammenbauen und per "Prepare Statement" vorbereiten.
    Anschließend kannst du per Execute das Statement ausführen und den Cursor öffnen.

    Versuche doch alternativ die Where-Bedingung besser vorzubereiten:

    where ... and (:PROGD0 = ' ' or PROGPW = :PROGD0) ...
    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

  3. #3
    Registriert seit
    Apr 2004
    Beiträge
    105
    Ich habe den Fehler gefunden, so klappts:

    Code:
    if        PROGD0 <>  '   '                              
    eval      cmd = %trim(cmd) + PROG + '''' + PROGD0 +'''' 
    endif                                                   
    if        AUSFD0 <> '    '                              
    eval      cmd = %trim(cmd) + AUSF + '''' + AUSFD0 +'''' 
    endif                                                   
    if        IDNRD0 <> 0                                   
    eval      cmd = %trim(cmd) + IDNR + %char(IDNRD0)       
    endif                                                   
    if        ANGBD0 <>  '   '                              
    eval      cmd = %trim(cmd) + ANGB + '''' + ANGBD0 +'''' 
    endif                                                   
    
    eval      SqlStm =  
    ....
    'Where STATPW = ''A'' ' + 
    cmd +                     
    ' Order by PROGPW, AUSFPW,.....

  4. #4
    Registriert seit
    Aug 2001
    Beiträge
    2.875

    Parameter-Marker

    Hi,

    du kannst in deinem Select-Statement Parameter-Marker (?) an Stelle der Variablen verwenden.

    In deinem Open-Statement gibts Du die entsprechenden Host-Variablen in der Reihenfolge an, wie sie im Select-Statement verwendet werden.

    Beispiel:
    PHP-Code:
     Stmt 'Select   Feld1 +
               from  MyFile +
               where     MyFeld1 = ''?'' +
                     and MyFeld2 = ?'
    ;
      
    C/EXEC SQL Open MyCsr Using :MyVar1, :MyVar2
    C
    /END-EXEC 
    Dies ist vorallem dann sinnvoll, wenn das gleiche Select-Statement mehrfach mit unterschiedlichen Variablen ausgeführt werden muss.

    Die Konvertierung des Strings in ein ausführbares SQL-Statement und das DECLARE-Statement müssen dann nicht erneut ausgeführt zu werden.

    Es muss nur der Cursor geschlossen und wieder neu eröffnet werden.

    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

  5. #5
    Registriert seit
    Apr 2004
    Beiträge
    105
    Mein Problem ist es, eine Art Filter zu Programmieren.
    Das passiert in einem SQLRPGLE-Programm. Die Daten werden an ein VARPG-Programm weitergegeben und dort in einer Subfile abgefragt.
    Im VARPG-Programm gibt es 4 Eingabefelder, nach denen man die große Datenmenge selektieren kann: PROGD9, AUSFD9, ANGBD9 und IDNRD9.
    Deswegen können die obigen Felder gefüllt sein oder auch nicht. Um das Abzufragen baue ich mir die cmd-Variable so zusammen:

    PHP-Code:
    DPROG             S            100    Inz(' and PROGPW  = ')           
    DAUSF             S            100    Inz(' and AUSFPW  = ')           
    DIDNR             S            100    Inz(' and IDNRPL  = ')           
    DANGB             S            100    Inz(' and ANGBPL  = ')           
                                                                           
    C                   if        PROGD0 <>  '   '                         
    C                   eval      cmd = %trim(cmd) + PROG '''' PROGD0 ''''
    C                   endif                                              
    C                   if        AUSFD0 <> '    '                         
    C                   eval      cmd = %trim(cmd) + AUSF '''' AUSFD0 ''''
    C                   endif                                              
    C                   if        IDNRD0 <> 0                              
    C                   
    eval      cmd = %trim(cmd) + IDNR + %char(IDNRD0)  
    C                   endif                                              
    C                   if        ANGBD0 <>  '   '                         
    C                   eval      cmd = %trim(cmd) + ANGB '''' ANGBD0 ''''
    C                   endif 
    Oder weiß einer eine andere Lösung hierfür?

  6. #6
    Registriert seit
    Feb 2001
    Beiträge
    20.243
    Naja, ganz so dynamisch ist es nicht nötig:

    /exec sql
    c+ declare mycursor for cursor as
    c+ SELECT PROGPW, AUSFPW, IDNRPL, ANGBPL,
    c+ PNAMPW, HOLZPW, KZ05PW, KZ06PW, AUSNPW, AUSDPW, DTNEPW
    c+ From RBPFILE/PRGSTP
    c+ Inner Join PRGLEP On PROGPW = PROGPL
    c+ And AUSFPW = AUSFPL
    c+ Where STATPW = 'A'
    c+ and (:PROGD0 = ' ' or PROGPW = :PROGD0)
    c+ and (:AUSFD0 = ' ' or AUSFPW = :AUSFD0 )
    c+ and (:IDNRD0= ' ' or IDNRPL = :IDNRD0)
    c+ and (:ANGBD0 = ' ' or ANGBPL = :ANGBD0 )
    c+ Order by PROGPW, AUSFPW, IDNRPL, ANGBPL
    c+ For read only'
    c/end-exec

    c/exec sql
    c+ open mycursor
    c/end-exec

    Da ja nur deine Where-Klausel variabel ist, geht das so viel einfacher.
    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

  7. #7
    Registriert seit
    Aug 2001
    Beiträge
    2.875

    Statisches SQL

    Hallo,

    verwende doch einfach statisches SQL!

    Beispiel:
    PHP-Code:
    C/EXEC SQL                                           
    C
    + DECLARE MyCursor CURSOR FOR                         
    CSELECT Feld1Feld2Feld3FeldN       
    C
    FROM   MyFile                                   
    C
    WHERE      FIRNR        = :HstFINR                 
    C
    +        AND MyLAND BETWEEN :VonLAND AND :BisLAND     
    C
    +        AND MyPLZ  BETWEEN :VonPLZ AND :BisPLZ     
    C
    +        AND MyORT  BETWEEN :VonORT AND :BisOrt  
    C
    +        AND MyKND  BETWEEN :VonKND and BisKND    
    C
    * ... und so weiter     
    C
    ORDER BY   MyLANDMyPLZMYBNR
    C
    + For Read Only
    C
    /END-Exec 
    Je nach dem, ob ein Wert eingegeben wurde oder nicht, werden die VON/BIS-Angaben entweder mit dem eingegebenen Wert oder mit *LoVal/HiVal gefüllt.

    Der Query-Optimizer kann solche Abfragen korrekt auflösen.

    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

  8. #8
    Registriert seit
    Apr 2004
    Beiträge
    105
    Super, vielen Dank, ich habe diesen Teil eingebaut:
    PHP-Code:
    c+ and (:PROGD0 ' ' or PROGPW = :PROGD0)
    c+ and (:AUSFD0 ' ' or AUSFPW = :AUSFD0)
    c+ and (:IDNRD0' ' or IDNRPL = :IDNRD0)
    c+ and (:ANGBD0 ' ' or ANGBPL = :ANGBD0

    Allerdings habe ich noch ein Problem:
    Ich arbeite mit einem SQLRPGLE- und einem VARPG-Programm.
    Das Varpg steuert und zeigt die Daten in einer Subfile an, das SQLRPGLE-Programm ermittelt die Daten.
    Hier arbeite ich mit einem 20.000stelligen Datenpuffer, der die relevanten Daten von einem in das andere Programm übergibt. Da große Datenmengen nicht in den Puffer passen, muß ich die Subfile von VARPG-Seite nachladen. Das obige Programm ermittelt die Daten beim ersten Aufruf. Für alle weiteren muß ich eine andere SQL-Abfrage erstellen mit verschachtelten where-Klauseln.

    Beispiel 1:
    ANGBD9, IDNRD9 und AUSFD9 sind gefüllt
    PHP-Code:
    CWhere STATPW 'A'     
    C+ and   ANGBPL  = :ANGBD9
    C
    + and   IDNRPL  = :IDNRD9
    C
    + and   AUSFPW  = :AUSFD9
    C
    + and   PROGPW  > :PROGD9 
    Beispiel 2:
    nachladen - PROGD9 & AUSFD9 ist gefüllt.
    D9-Felder sind die Felder des letzten Datensatzes, die nächsten müssen ermittelt werden.
    PHP-Code:
    CWhere STATPW 'A'      
    C+ and   ANGBPL >  :ANGBD9 
    C
    + and   IDNRPL >= :IDNRD9 
    C
    + and   AUSFPW  = :AUSFD9 
    C
    + and   PROGPW  = :PROGD9 
    C
    + or   (STATPW =  'A'     
    C+ and   IDNRPL >  :IDNRD9 
    C
    + and   AUSFPW  = :AUSFD9 
    C
    + and   PROGPW  = :PROGD9
    Beipiel 3:
    nachladen - PROGD9 ist gefüllt.
    PHP-Code:
    CWhere STATPW 'A'
    C+ and   ANGBPL > :ANGBD9
    C
    + and   IDNRPL >= :IDNRD9
    C
    + and   AUSFPW >= :AUSFD9
    C
    + and   PROGPW >= :PROGD9
    C
    + or   (STATPW 'A' 
    C+ and   IDNRPL > :IDNRD9
    C
    + and   AUSFPW >= :AUSFD9
    C
    + and   PROGPW >= :PROGD9)
    C+ or   (STATPW 'A'            
    C+ and   AUSFPW > :AUSFD9
    C
    + and   PROGPW >= :PROGD9)
    C+ or   (STATPW 'A'
    C+ and   PROGPW > :PROGD9
    Da ich 4 Felder zur Selektion habe müßte ich dann 16 (!!!) einzelne Where-Bedingungen schreiben.
    Hat dafür vielleicht jemand eine Lösung?

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

    Thumbs up

    Hallo Woki,

    warum machst Du Dir das mit dem Datenpuffer so schwierig ?

    Erstelle beim Aufruf deines Programms eine DTAQ.
    ( Achtung Namensvergabe muss eindeutig sein wenn mehrere
    VRPG Clients die Anwendung starten).

    Dein AS 400 Programm füllt die Werte in die DTAQ.
    Wenn dein AS 400 Programm fertig ist
    liest dein VARPG die DTAQ und schreibt die Subfile.

    Hört sich schwierig an ist aber ganz einfach.

    Ausserdem kann man sich das lästige Nachladen sparen.

    Gruss Michael

  10. #10
    Registriert seit
    Feb 2001
    Beiträge
    20.243
    Kann VARPG kein embedded SQL ?
    Ganz schön kompliziert für eine einfache Anzeige !
    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

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

    Thumbs up

    Hallo Baldur,

    auch VARPG kann Embedded SQL. Dazu ist es allerdings notwendig
    auf dem Client die DB2 zu installieren.

    Aber warum sollen wir auf dem PC eine DB2 installieren
    wenn wir doch eine AS400 haben.


    Gruss Michael

  12. #12
    Registriert seit
    Feb 2001
    Beiträge
    20.243
    Ich denke eher, dass die Verbindung dann über DB2/Connect laufen muss so dass die AS400 weiterhin als Server fungieren kann.
    Aber was für ein Aufwand !
    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

Similar Threads

  1. Embedded SQL in VARPG
    By Squall in forum NEWSboard Programmierung
    Antworten: 23
    Letzter Beitrag: 18-10-06, 12:01
  2. embedded SQL in RPG
    By muadeep in forum IBM i Hauptforum
    Antworten: 5
    Letzter Beitrag: 03-08-06, 13:25
  3. SQL .. for update of (RPG embedded SQL)
    By loeweadolf in forum NEWSboard Programmierung
    Antworten: 2
    Letzter Beitrag: 01-06-06, 09:43
  4. Character verbinden in Embedded SQL
    By e_sichert in forum NEWSboard Programmierung
    Antworten: 3
    Letzter Beitrag: 03-05-06, 10:47
  5. Embedded SQL Kommando
    By haertl in forum NEWSboard Programmierung
    Antworten: 8
    Letzter Beitrag: 05-07-04, 07:30

Berechtigungen

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