[NEWSboard IBMi Forum]
Seite 1 von 2 1 2 Letzte

Thema: SQL0811

Hybrid View

  1. #1
    Registriert seit
    Apr 2012
    Beiträge
    360
    mein Problem ist es das der spezielle Fall sporadisch vorkommt.
    Falls ich es Teste funktioniert alles so wie es sollte.

  2. #2
    Registriert seit
    Feb 2001
    Beiträge
    20.790
    SQL-Fehler können nicht mit Monitor abgefangen werden, dafür ist der SQLCODE zuständig.

    Dein Problem ist wohl, dass die Where-Klausel ab und zu eben mehr als einen Datensatz liefert.
    In diesem Fall schlägt der SQL fehl und liefert lieber keine Daten.

    Du hast mehrere Möglichkeiten:

    select ....
    fetch first 1 rows only

    Damit wird einfach nur der 1. Datensatz gelesen, egal ob es mehrere gibt.

    Select Min(Feld1) into ...

    nimm halt den kleinsten Wert, alternativ geht natürlich auch MAX/SUM/AVG/...

    Oder prüfe die Daten besser, warum ggf. mehr da ist als du erwartest.
    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 2012
    Beiträge
    360
    Aber wie kann vorher schon prüfen/abfangen ob der Sqlfehler auftritt?
    Wie ist da so die Vorgehensweise?

  4. #4
    Registriert seit
    Aug 2001
    Beiträge
    2.943
    Zitat Zitat von tarkusch Beitrag anzeigen
    Aber wie kann vorher schon prüfen/abfangen ob der Sqlfehler auftritt?
    Wie ist da so die Vorgehensweise?
    Du prüfst nicht vorher oder hinterher.
    Sofern mehrere Datensätze zurückkommen können und Du z.B. nur wissen willst ob mindestens ein Datensatz vorhanden ist, musst Du, wie Baldur vorgeschlagen hat einfach FETCH 1 ROW ONLY hinzufügen und schon wird entweder kein oder genau 1 Datensatz ausgegeben:

    Code:
     /Free
      Clear isFound;
      Exec SQL   
         Select 1 into :isFound
            From AuftrPos
            where AutrNr = :HstAuftrag
                  and Status < 70
         Fetch First Row Only;
         If SQLCODE < *Zeros and SQLCODE <> -811;
            //Fehler
         ElseIf SQLCODE = 100 or isFound = *Zeros;
            //Kein Satz gefunden
         Else;
            //Satz vorhanden
         Endif;
    Birgitta
    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

  5. #5
    Registriert seit
    Aug 2003
    Beiträge
    1.508
    Kleiner Tipp am Rande:
    Wenn du das SQL Statement öfters aufrufst (vielleicht sogar innerhalb einer Schleife) solltest du lieber einen Cursor verwenden. Auch wenn du nur einen Satz lesen willst.
    Dadurch bleibt ab dem 2ten mal lesen, der ODP vorhanden und muss nicht neu erstellt werden.

    Du könntest es mit einem Select count(*) Into :v1 ... prüfen.
    Wobei das nicht das eigentliche Problem löst.
    Wenn du nur 1 Satz haben willst, musst du feststellen, welche Kriterien zutreffen müssen (WHERE-Klausel). Wenn hin und wieder doch mehrere Sätze vorkommen, dann sind die Kriterien nicht ausreichend und du musst das Konzept neu überdenken.

    Lass ein Monitor für diese Abfrage eingegränzt laufen. Dann siehst du bei welchen Kriterien mehrere Sätze gefunden werden.

    lg Andreas

  6. #6
    Registriert seit
    Apr 2012
    Beiträge
    360
    Ich habe mir die Daten angesehen und es sind defintiv mehrere Sätze zu einem Statement.

    Wie lasse ich eigentlich einen Monitor laufen? Da stehe ich völlig auf dem Schlauch.

    lg
    Tarki

  7. #7
    Registriert seit
    Aug 2003
    Beiträge
    1.508
    Zitat Zitat von tarkusch Beitrag anzeigen
    Wie lasse ich eigentlich einen Monitor laufen? Da stehe ich völlig auf dem Schlauch.
    iSeries Navigator --> Datenbanken --> deine Datenbank --> SQL Performance Monitors
    Rechts-Klick --> Neu --> usw.

    Oder im Green-Screen: STRDBMON

    Wichtig bei beiden ist den Monitor auch wieder manuell zu Beenden. Da er sonst "ewig" läuft.

  8. #8
    Registriert seit
    Aug 2001
    Beiträge
    2.943
    Zitat Zitat von andreaspr@aon.at Beitrag anzeigen
    Kleiner Tipp am Rande:
    Wenn du das SQL Statement öfters aufrufst (vielleicht sogar innerhalb einer Schleife) solltest du lieber einen Cursor verwenden. Auch wenn du nur einen Satz lesen willst.
    Dadurch bleibt ab dem 2ten mal lesen, der ODP vorhanden und muss nicht neu erstellt werden.
    Das stimmt so nicht! SELECT ... INTO oder VALUES ... INTO führen im Hintergrund einen DECLARE, OPEN, FETCH und CLOSE aus! Die ODPs bleiben ab dem 2. Mal öffen, sofern sie wiederverwendbar sind.

    Birgitta
    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

  9. #9
    Registriert seit
    Aug 2003
    Beiträge
    1.508
    Zitat Zitat von B.Hauser Beitrag anzeigen
    Das stimmt so nicht! SELECT ... INTO oder VALUES ... INTO führen im Hintergrund einen DECLARE, OPEN, FETCH und CLOSE aus! Die ODPs bleiben ab dem 2. Mal öffen, sofern sie wiederverwendbar sind.
    Das stimmt so auch nicht!
    Ja ich hab das Gerücht mal irgendwo gelesen oder gehört, aber Tatsache ist, dass der ODP jedes mal gelöscht wird.
    Eventuell dass es bei 7.1 so gemacht wird?
    Bis 6.1 wird der ODP jedefalls immer neu erstellt!

  10. #10
    Registriert seit
    Aug 2001
    Beiträge
    2.943
    Zitat Zitat von andreaspr@aon.at Beitrag anzeigen
    Das stimmt so auch nicht!
    Ja ich hab das Gerücht mal irgendwo gelesen oder gehört, aber Tatsache ist, dass der ODP jedes mal gelöscht wird.
    Eventuell dass es bei 7.1 so gemacht wird?
    Bis 6.1 wird der ODP jedefalls immer neu erstellt!
    Ich weiß zwar nicht wo Du die Gerüchte gehört hast, bzw. wieso du glaubst, dass der ODP jedesmal gelöscht wird. Der ODP wird nur nach der 1. Ausführung gelöscht (wie auch bei den Cursorn) und bleibt nach der zweiten Ausführung offen (sofern er wiederverwendbar ist) und wird erst geschlossen, wenn die Activierungsgruppe beendet wird, zumindest wenn die Option CLOSQLCSR = *ENDACTGRP ist.

    Hier ein Auszug aus dem Joblog (auf einer Maschine mit V5R4). SELECT ... INTO wird in einer Schleife mehrfach ausgeführt und das Programm sogar zwei Mal aufgerufen:
    Code:
    > call selintox             
       ODP erstellt.                                           
       Blockung für Abfrage.                                     
       Offener Datenpfad (ODP) gelöscht.                       
       Eingebettetes SELECT beendet.                           
       DSPLY  Der Gesamt-Umsatz in 2004 liegt bei 2780.00 Euro 
       ODP erstellt.                                            
       Blockung für Abfrage.                                    
       ODP nicht gelöscht.                                      
       Eingebettetes SELECT beendet.                            
       DSPLY  Der Gesamt-Umsatz in 2005 liegt bei 15276.21 Euro 
       ODP wiederverwendet.                                     
       ODP nicht gelöscht.                                      
       Eingebettetes SELECT beendet.                            
       DSPLY  Der Gesamt-Umsatz in 2006 liegt bei 11409.57 Euro 
    > call selintox                                            
      ODP wiederverwendet.                                     
      ODP nicht gelöscht.                                      
      Eingebettetes SELECT beendet.                            
      DSPLY  Der Gesamt-Umsatz in 2004 liegt bei 2780.00 Euro  
      ODP wiederverwendet.                                     
      ODP nicht gelöscht.                                      
      Eingebettetes SELECT beendet.
    Birgitta
    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

  11. #11
    Registriert seit
    Aug 2003
    Beiträge
    1.508
    Zitat Zitat von B.Hauser Beitrag anzeigen
    Ich weiß zwar nicht wo Du die Gerüchte gehört hast, bzw. wieso du glaubst, dass der ODP jedesmal gelöscht wird. Der ODP wird nur nach der 1. Ausführung gelöscht (wie auch bei den Cursorn) und bleibt nach der zweiten Ausführung offen (sofern er wiederverwendbar ist) und wird erst geschlossen, wenn die Activierungsgruppe beendet wird, zumindest wenn die Option CLOSQLCSR = *ENDACTGRP ist.
    Das meinte ich mit Gerücht
    Ich habe nämlich zuvor auch ein kleines Test-PGM gestartet, wo ich das gleiche Select INTO Statement 4 mal ausgeführt habe und jedes mal wurde der ODP neu erstellt wurde.

    Jetzt hab ich grad das gleiche Statement innerhalb einer Schleife 4 mal ausgeführt und plötzlich bleibt der ODP geöffnet.
    Außerhalb der Schleife scheint der ODP immer gelöscht zu werden. Warum auch immer!?!? (6.1)

    Weist du oder sonst wer eine vernünftige erklärung dafür??

    Ich habe (auch bei 5.4) jedenfalls erhebliche verbesserungen der Performance in diversen Programmen tätigen können indem ich einen Cursor verwendete, weil scheinbar nicht immer das Select Into Statement mit dem gleichen ODP verwendet wurde.

    Deshalb sag ich auch dass ein Cursor besser sei als ein Select Into, denn du kannst nie zu 100 % sagen, dass da der ODP offen bleibt, bei einem Cursor kann ich das schon. (Abhängig von den SET OPTIONs natürlich).

  12. #12
    Registriert seit
    Aug 2003
    Beiträge
    1.508
    Zitat Zitat von andreaspr@aon.at Beitrag anzeigen
    Jetzt hab ich grad das gleiche Statement innerhalb einer Schleife 4 mal ausgeführt und plötzlich bleibt der ODP geöffnet.
    Außerhalb der Schleife scheint der ODP immer gelöscht zu werden. Warum auch immer!?!? (6.1)

    Weist du oder sonst wer eine vernünftige erklärung dafür??
    Während der Beiträge im anderen Thrad (Plan Cache und Monitor) denke ich die Antwort zu haben.

    Für jedes Select wird ja generell ein eigener Cursor erstellt. So wird auch für ganz genau dem gleichem Select an einer anderen Stelle im Programm ein eigener Cursor erstellt.
    Dadurch wird der ODP vom ersten Select nicht für das zweite verwendet auch wenn es 1:1 das gleiche ist.

    Das ist der Grund warum der ODP eines SELECT INTOs innerhalb einer Schleife öfters verwendet wird jedoch das gleiche Statement hintereinander nicht.
    Da die Statements hintereinander jedes einen eigenen Cursor hat.

    Somit konnte ich die Thematik SELECT INTO und ODPs auch nun durchblicken.
    Danke Birgitta für den Denkanstoß!

Berechtigungen

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