[NEWSboard IBMi Forum]

Thema: SQL UDF

  1. #1
    Registriert seit
    Aug 2006
    Beiträge
    2.077

    SQL UDF

    Hallo *all,
    ich habe mir eine UDF geschrieben die mir kundenspezifische Preise ermitteln soll.

    Dummerweise läuft das Teil auf Fehler.

    Fehlermeldung
    Code:
     Nachrichten-ID . . . . :   SQL0305       Bewertung  . . . . . . :   30         
     Nachrichtenart . . . . :   Diagnose                                            
     Sendedatum . . . . . . :   15.08.14      Sendezeit  . . . . . . :   15:45:56   
                                                                                    
     Nachricht . . . :   Anzeigervariable erforderlich.                             
     Ursache  . . . . :  Eine Anweisung FETCH, eine eingebettete Anweisung SELECT,  
       eine Anweisung CALL, GET DESCRIPTOR, SET oder VALUES INTO hatte einen        
       Nullwert zur Folge, für Host-Variable SQLP_L2.RETURNVAL wurde jedoch keine   
       Anzeigervariable angegeben. Die relative Position der Host-Variablen in der  
       Klausel INTO oder der Parameterliste ist 2. Ist der Name der Host-Variablen
    Die UDF sieht so aus:

    Code:
     CREATE FUNCTION rptrade/artpreis3                       
    ( ARTIKELNR dec(10),                                    
      Kundennr  dec(10)                                     
     ) RETURNS                                              
    CHAR(10) LANGUAGE SQL READS SQL DATA BEGIN              
    DECLARE RETURNVAL CHAR ( 10 ) NOT NULL DEFAULT '0,00' ; 
    DECLARE preis1 dec ( 10 ) ;                             
    DECLARE preis2 dec ( 10 ) ;                             
      FOR CSRC1 AS C1 CURSOR                                
          FOR SELECT SOEIPR                                 
                 FROM rptrade/artpreis1                     
                 where SOID2 = ARTIKELNR                    
                 and   (sodnbi = 99999999                   
                 or sodnbi >= YEAR(CURRENT DATE)*10000 +    
                              MONTH(CURRENT DATE)*100 +     
                              DAY(CURRENT DATE))            
                 order by soid2, sodnbi                     
                       desc fetch first row only         
          DO SET preis1 = SOEIPR;                        
      END FOR ;                                          
      FOR CSRC1 AS C1 CURSOR                             
        FOR SELECT SOEIPR                                
               FROM rptrade/artpreis2                    
               where SOID4 = ARTIKELNR                   
               and   soid1 = kundennr                    
               and   (sodnbi = 99999999                  
               or sodnbi >= YEAR(CURRENT DATE)*10000 +   
                            MONTH(CURRENT DATE)*100 +    
                            DAY(CURRENT DATE))           
               order by soid4, sodnbi                    
                     desc fetch first row only           
          DO SET preis1 = SOEIPR;                        
      END FOR ;                                          
      if preis2 > 0 then set preis1 = preis2 ; end if ;  
      SET RETURNVAL = cast(preis1 as char(10));  
      RETURN LTRIM(RETURNVAL) ;                  
    END
    Jetzt vermute ich ja mal das ein SQL Statement kein Ergebniss liefert und daher z.B. Preis2 nicht gefüllt ist.

    Was will er mir mit dem Stichwort Anzeigevariable sagen?
    Für Hilfe dankbar

  2. #2
    Registriert seit
    Nov 2003
    Beiträge
    2.309

  3. #3
    Registriert seit
    Aug 2001
    Beiträge
    2.878
    Anzeiger-Variable meint meist, dass ein NULL-Wert irgendwo verwendet oder verglichen wird. Geprüft werden NULL-Werte i.d.R. über Anzeiger-Variablen.

    Wo berechnest Du eigentlich Preis2?
    Soweit ich das sehen kann nirgends. Preis2 wird mit einem NULL-Wert inititalisiert und anschließend wird dieser NULL-Wert mit 0 verglichen (IF Preis2 > 0) und das funktioniert nicht.

    1. Initialisiere alle deklarierte Variablen
    2. Anstatt das numerische Tagesdatum in den Cursorn zu berechnen würde ich eine separate variable definieren und nur einmalig initialisieren.
    3. Anstatt der Cursor mit For-Schleifen würde ich ein einfaches SELECT ... INTO verwenden.
    4. Sicherheitshalber würde ich den Preis über COALESCE in einen Default-Wert (z.B. 0) konvertieren.

    Etwa so:
    Code:
    CREATE FUNCTION rptrade/artpreis3 ( ARTIKELNR dec(10),                                    
                                         Kundennr  dec(10)  )                                   
            RETURNS CHAR(10) 
            LANGUAGE SQL 
            READS SQL DATA 
    BEGIN              
       DECLARE RETURNVAL CHAR ( 10 ) NOT NULL DEFAULT '0,00' ; 
       DECLARE preis1  dec ( 10, 0 ) NOT NULL Default 0;                             
       DECLARE Preis2  dec ( 10, 0 ) Not NULL Default 0;   
       Declare DateNum Dec( 8, 0 )  Not NULL Default 0;
    
       Set DateNum = Dec(VarChar_Format(Current_Timestamp, 'YYYYMMDD'), 8, 0);
    
       Select Coalesce(SOEIPR, 0) into Preis1
         From RPTRADE/ArtPreis1
         Where        SOID2 = ARTIKELNR                    
               and (   sodnbi  = 99999999                   
                    or sodnbi >= DateNum)            
         order by sodnbi desc 
      fetch first row only;
    
       Select Coalesce(SOEIPR, 0) into Preis2
         From RPTRADE/ArtPreis2
         where      SOID4 = ARTIKELNR                   
               and  soid1 = kundennr                    
               and (   sodnbi = 99999999                  
                    or sodnbi >= DateNum)           
               order by sodnbi desc 
       fetch first row only;           
                                             
      if Preis2 > 0 then set preis1 = Preis2; 
      end if ;  
      SET RETURNVAL = cast(preis1 as char(10));  
      RETURN LTRIM(RETURNVAL) ;                  
    END
    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

  4. #4
    Registriert seit
    Aug 2006
    Beiträge
    2.077
    Soviel zum Thema Copy & Paste. Beim 2. Select sollte natürlich Preis2 den Wert erhalten

    Ich werde morgen versuchen Deine Vorschläge umzusetzen, erstmal Danke für Deine Hinweise

    GG

  5. #5
    Registriert seit
    Aug 2006
    Beiträge
    2.077
    Hallo Birgitta,
    danke für Deine Hilfe, beim testen bekomme ich jetzt die Meldung

    Nachrichten-ID . . . . : SQL0171 Bewertung . . . . . . : 30
    Nachrichtenart . . . . : Diagnose
    Sendedatum . . . . . . : 16.08.14 Sendezeit . . . . . . : 08:01:5

    Nachricht . . . : Argument 2 der Funktion VARCHAR_FORMAT ungültig.
    Ursache . . . . : Datenart, Länge oder Wert des Arguments 2 der Funktion
    VARCHAR_FORMAT ist ungültig.

    Das müßte sich ja jetzt auf dieses Statement beziehen.
    Wo kann ich die richtige Syntax nachschauen?

    Set DateNum = Dec(VarChar_Format(Current_Timestamp, 'YYYYMMDD')
    8, 0);

    GG

    Ich habe jetzt nochmal hier im Forum geschaut und h´gehofft das ich das ,8,0 weglassen könnte, das funktioniert aber leider nicht

  6. #6
    Registriert seit
    Aug 2001
    Beiträge
    2.878
    Unter welchem Release arbeitest Du?
    Kannst Du den VarChar_Format-Befehl interaktiv (z.B. mit STRSQL) ausführen?
    In älteren Releasen ist die VarChar_Format-Funktion vielleicht noch nicht vorhanden.
    Etwa so:
    Code:
    select Dec(VarChar_Format(Current_Timestamp, 'YYYYMMDD'), 8, 0)  
    From sysibm/sysdummy1
    Sofern die Ausführung nicht möglich ist, musst Du das numerische Tagesdatum anderweitig ermittelt, evtl. auch so wie in Deinem ersten Beispiel, nur halt im SET-Statement.
    Etwa so:
    Code:
    Set DateNum = Dec(Year(Current_Date) * 10000 + Month(Current_Date) * 100 + Day(Current_Date), 8, 0);
    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

  7. #7
    Registriert seit
    Aug 2006
    Beiträge
    2.077
    Hallo Birgitta,
    ich habe das einzig wahre OS

    V5R4

    vermutlich noch für 2 Jahre. TöTö TöTö TöTö Tschingbumm.
    Also das 1. Statement funktioniert dort nicht.
    Das 2. läuft wie angenommen
    GG

  8. #8
    Registriert seit
    Aug 2006
    Beiträge
    2.077
    Heavy standing on the wire....

    gelöst, falsche Parameterreihenfolge

  9. #9
    Registriert seit
    Feb 2001
    Beiträge
    20.256
    Dann bist du ja schon mal weiter als ich.
    Ich schlage mich noch auf unabsehbare Zeit mit V5R2 und da noch nicht mal mit den letzten PTF's herum da keiner die Kiste mehr wartet.
    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

Berechtigungen

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