[NEWSboard IBMi Forum]
Seite 1 von 3 1 2 ... Letzte
  1. #1
    Registriert seit
    Nov 2009
    Beiträge
    227

    SQL set oder select into mit dynamischer Selektion

    Guten Morgen,

    wir brauchen ein in einem SQLRPGLE Pgm ein dynamisches select das 6 Werte beinhalten kann.

    von
    select count(*) from Datei where 'Normale-Bedingung, immer'

    über
    select count(*) from Datei where Normale-Bedingung and Feld1 = :wert1

    zu
    select count(*) from Datei where Normale-Bedingung and feld1=:wert1 and feld2=:wert2 and feld3=:wert3 and feld4=:wert4 and feld5=:wert5 and feld6=:wert6

    Alle 64 Kombinationen

    den Where kann ich dynamisch in einen String schreiben

    ein
    select count(*) from Datei where :String
    funktioniert nicht

    weder als
    set :CNTR = (select count(*) from Datei where :String ) noch als
    select count(*) into :CNTR from Datei where :String

    alle möglichen 64 kombinationen in einer select / When Gruppe abarbeiten ist keine Alternative.

    Wie löst Ihr das?

    Dietlinde Beck

  2. #2
    Registriert seit
    Jan 2012
    Beiträge
    1.215
    Hallo Dietlinde,
    du beschreibst da ein statisches SQL, an das du eine dynamische where Anweisung andocken willst. Das geht (meines Wissens nach) nicht.

    Entweder machst du das ganze SQL dynamisch: Du baust dir den kompletten SQL String mit RPG Mitteln zusammen und führst das dann aus

    ODER

    du machst alles statisch:
    Ich gehe mal davon aus, dass deine Selektionswerte wert1 bis wert6 leer sind, wenn sie nicht benötigt werden und gefüllt sind, wenn sie zur Selektion beitragen sollen. Dann könntest du das where so scheiben:

    Code:
    ... where (:wert1 = '' or feld1 = :wert1) 
           and (:wert2 = '' or feld2 = :wert2)
           and (:wert3 = '' or feld3 = :wert3)
           and (:wert4 = '' or feld4 = :wert4)
           and (:wert5 = '' or feld5 = :wert5)
           and (:wert6 = '' or feld6 = :wert6)
    Diese Variante ist allerdings eventuell nicht sehr performant, da wegen der OR-Bedingungen wahrscheinlich kein guter Index verwendet wird.

    LG, Dieter

  3. #3
    Registriert seit
    Nov 2009
    Beiträge
    227
    Danke Dieter,
    leider ist das so nicht machbar!
    Alle Werte können alle Inhalte haben, wenn sie nicht selektiert sind.

    Natürlich kann ich das ganze Statement dynamisch machen
    aber execute immediate geht ja nicht als SET oder insert into. ODER?
    Dann müsste ich den Zähler in eine Datei ausgeben und diese dann lesen.

    nicht sehr elegant, oder?

  4. #4
    Registriert seit
    Jan 2012
    Beiträge
    1.215
    Du müsstest das dynamische SQL in einem Cursor verarbeiten. In eine Datei ausgeben musst du es nicht.
    Wenn dein dynamisches SQL ein Count ist, wird dein cursor genau eine Zeile und eine Spalte haben. Du brauchst also keine Schleife:

    Beispiel: (Die Variable String enthält dein SQL-Statement)

    Code:
    
           // SQL-Anweisung validieren (unter dem Name "cmd"):
           exec sql prepare cmd from :string;
    
    
           // Cursor mit dem Namen "result" definieren:
           exec sql declare result cursor for cmd;
    
    
           // Cursor öffnen:
           exec sql open result;
    
    
           // Verarbeiten des Cursors (Es kann nur genau 1 Satz mit genau 1 Feld sein):
           exec sql fetch next from result into :ergebnis;
    
    
           // Cursor schließen:
           exec sql close result;

    Tipp:
    (Ich habe mir dafür ein Serviceprogramm geschrieben, das einen "count"-SQL-String bekommt und mir den Wert zurückliefert.)

  5. #5
    Registriert seit
    Aug 2001
    Beiträge
    2.932
    SELECT ... INTO kann nicht dynamisch ausgeführt werden, aber ein Cursor ist auch nicht unbedingt notwendig.
    VALUES ... INTO funktioniert wie SELECT ... INTO, kann jedoch dynamisch ausgeführt werden:

    Code:
    SelectStmt = 'Values( Select Count(*) from Datei ' + String + ') into ?';
    Exec SQL Prepare DynSQL from :SelectStmt;
    Exec SQL Execute DynSQL using :ReceiverVar;
    i.Ü. ist das Ganze auch tatsächlich statisch mit SELECT ... INTO möglich:

    Code:
    EXEC SQL Select Count(*) from Datei into :ReceiverVar 
              Where     Col1 = Case When :HostCol1 > '' Then :HostCol1 Else Col1 End
                    and Col2 = Case When :HostCol2 <> 0 Then :HostCol2 Else Col2 End
                    and Col3 = Case When :HostCol3 > '2000-01-01' then :HostCol3 Else Col3 End
                    and ....
                    and ColN = Case When :HostColN > '' Then :HostColN Else ColN End
    Birgitta Hauser

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

  6. #6
    Registriert seit
    Mar 2002
    Beiträge
    5.376
    ... between ist auch noch eine Option

    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/

  7. #7
    Registriert seit
    Jan 2012
    Beiträge
    1.215
    Dietlinde, dann ist wahrscheinlich Birgittas Vorschlag mit dem dynamischen "Values-Statement" die eleganteste Lösung. Ich wusste nicht, dass das geht und habe das bisher mit einem Cursor gelöst.

    Die Lösung mit statischem SQL scheidet ja aus, wie du selbst geschrieben hast:

    "leider ist das so nicht machbar!
    Alle Werte können alle Inhalte haben, wenn sie nicht selektiert sind."

  8. #8
    Registriert seit
    Feb 2001
    Beiträge
    20.716
    Statisch kannst du das ebenso machen, denn immerhin gibts ja noch NULL-Anzeiger:

    Code:
    where (   feld1 = :wert1 :Null1) 
           or feld2 = :wert2 :Null2)
           or feld3 = :wert3 :Null3)
           or feld4 = :wert4 :Null4)
           or feld5 = :wert5 :Null5)
           or feld6 = :wert6 :Null6)
    Null-Anzeiger sind vom Typ int(5) und enthalten den Wert -1 wenn die Variable NULL sein soll.
    Der NULL-Vergleich mit Feld führt zu NULL und ist nicht Wahr.
    Der Inhalt der Variablen selber wird in diesem Fall ignoriert.
    Also musst du die Null-Anzeiger auf -1 setzen, wenn die Bedingung nicht erfolgreich werden soll.

    Nullanzeiger kann man immer auch beo Parametern verwenden.
    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

  9. #9
    Registriert seit
    Jan 2012
    Beiträge
    1.215
    Entweder habt ihr die Fragestellung nicht richtig gelesen oder ich habe gerade ein Brett vorm Kopf:

    Dietlinde hat doch geschrieben, dass sie an den Selektionsfeldern nicht erkennen kann, ob die Selektion gewünscht ist oder nicht. Deshalb scheidet das Konstrukt "(feld1 = :wert1 or :wert1 = '') aus!

    Aus meiner Sicht ist das dynamische SQL die einzige Möglichkeit.

  10. #10
    Registriert seit
    Nov 2009
    Beiträge
    227
    Hallo zusammen und vielen Dank,

    ich denke, eine der beiden Versionen von Birgitta ist am besten.
    Nicht verstanden habe ich das mit dem between von Herrn Bender - ich glaube nicht das das geht -
    und das mit dem NULL von Herrn Fuerchau auch nicht.
    Da müsste das OR zu einem AND werden, und Null1 -1, wenn ich feld1 NICHT abfragen will?

  11. #11
    Registriert seit
    Feb 2001
    Beiträge
    20.716
    Auch bei Dynamic muss der Programmierer ja wissen, welche Felder er nicht in die Where-Klausel aufnimmt.
    Also kann er bei der statischen Variante einfach die NULL-Anzeiger für die nicht benötigten Felder setzen verwenden, da dies so wirkt, als wäre die Bedingung nicht vorhanden.
    Denn mit NULL kann man nur mit " is null" vergleichen und sonst nicht.

    @dibe

    Wenn du eine Spalte mit NULL vergleichst, ist das Ergebnis NULL.
    Da du aber alle mit Or verknüpfst, benötigst du mindestens 1 Bedingung die nicht NULL sondern Wahr ist um zum Ergebnis zu kommen.
    In RPG Kann man aber NULL halt nur mit einem NULL-Indikator markieren.

    Wenn du also z.B. Null2 bis Null6 mit -1 belegst, muss "Feld1 = : Wert1" zum Ziel führen, oder auch nicht wenn es ebenso ein akzeptables Ergebnis ist.

    Ach ja:
    Die 2. Variante von Birgitta ist dieselbe wie die in der ersten Antwort, nur komplizierter geschrieben.
    Warum soll ich Col1 mit sich selber vergleichen wenn die Variable leer ist und ich doch eigentlich alles mit or verknüpfe?
    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
    Jan 2012
    Beiträge
    1.215
    Die Antwort von Baldur klingt interessant. Aber verstanden habe ich sie auch nicht.

    Im where habe ich noch nie Null Indikators gesetzt. Was bedeutet denn:

    where ( feld1 = :wert1 :Null1)
    or feld2 = :wert2 :Null2)
    or feld3 = :wert3 :Null3)



    Ich denke, du meinst, dass ich mehrere numerische Variablen Null1, Null2, ... im RPG deklariere und z.B. Null1 und Null3 auf -1 setze? Dann würde nur die Selektion für feld2 geprüft? Ist das so?

    Falls ja, ist das eine coole Idee, aber ich verstehe noch nicht, weshalb das funktioniert.

Similar Threads

  1. Dynamischer Call per Prototype
    By dschroeder in forum NEWSboard Programmierung
    Antworten: 5
    Letzter Beitrag: 28-02-25, 13:42
  2. Antworten: 6
    Letzter Beitrag: 15-01-20, 08:17
  3. set :Z = geht nicht, ohne das set sehrwohl
    By dibe in forum NEWSboard Programmierung
    Antworten: 7
    Letzter Beitrag: 13-11-18, 08:14
  4. SQL Select into
    By alexander may in forum NEWSboard Programmierung
    Antworten: 4
    Letzter Beitrag: 30-03-05, 14:56
  5. SQL Selektion mit LIKE
    By RLurati in forum IBM i Hauptforum
    Antworten: 6
    Letzter Beitrag: 18-01-05, 11:38

Berechtigungen

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