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

Thema: UDF V6R1

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

    UDF V6R1

    Hallo *all,

    ich bin auf dem Weg eine UDF zu erstellen die mir für einen Eingabewert einen HEX Wert zurückliefert.
    Leider ist es so das die Eingabewerte zu groß sind da der Rückgabewert max FFFF sein darf.
    Deswegen erstelle ich mir eine Tabelle wo ich die Eingabewerte reinschreiben will, die Anzahl der Sätze zähle und dann den Wert auch wegschreibe. (Für spätere Abfragen)

    Leider scheitere ich schon am Anfang.
    Beim ersten Aufruf ist es ja so, das die Tabelle leer ist. Also würde ich ein einfaches select count(*) machen und den Wert zurückgeben. Das will er aber nicht.

    Code:
    CREATE FUNCTION rptrade/zaehler /*10.10.19 14:34*/       
     ( DEBITOR dec(08) ) RETURNS                             
    CHAR(04) LANGUAGE SQL READS SQL DATA BEGIN               
    DECLARE RETURNVAL CHAR ( 04 ) NOT NULL DEFAULT '0000' ;  
      set returnval =                                        
      case when select count(*) from dat020 = 0 then 'XXXX'  
           else '0001'                                       
      end;                                                   
      RETURN LTRIM(RETURNVAL);                               
    END;                                                     
    
    Für Hinweise dankbar. Werde mal sehen wo ich vernünftige Doku für die UDFs finde 
    
    GG 4251

  2. #2
    Registriert seit
    Jan 2012
    Beiträge
    894
    Ich denke, du musst die Anzahl erst in eine Variable schieben:

    DECLARE anzahl decimal(10);
    select count(*) into anzahl from dat020;
    set returnval = case when anzahl = 0 then 'XXXX' else '0001'

    Gruß,
    Dieter

  3. #3
    Registriert seit
    Jan 2012
    Beiträge
    894
    Noch eine kleine Optimierung: Du willst ja eigentlich gar nicht wissen, wie viele Sätze in der Datei sind, sondern nur, ob es mehr als 0 sind. Deshalb würde ein "fetch first row only" verhindern, dass alle gezählt werden:
    select count(*) into anzahl from dat020 fetch first row only;

  4. #4
    Registriert seit
    Aug 2006
    Beiträge
    1.890
    Hallo,
    werde ich morgen mal ausprobieren.

    BTW. In der Tabelle sind hinterher Max. 200 Sätze, deswegen passt der Satz „Noch eine kleine Optimierung...“ ;-)

  5. #5
    Registriert seit
    Aug 2001
    Beiträge
    2.606
    Versuch mal bei dem CASE die SELECT-Anweisung in eine Klapper zu packen.

    Birgitta
    Birgitta Hauser

    Contractor for Fresche Solutions Inc.
    Anwendungsmodernisierung, Beratung, Schulungen im Bereich RPG, SQL und Datenbank
    IBM Champion 2020
    RPG und SQL-Schulungen
    Erstellen und Verarbeiten XML- und JSON-Daten mit SQL

  6. #6
    Registriert seit
    Aug 2006
    Beiträge
    1.890
    Danke, das hat schon mal funktioniert.

    Habe mir das Redbook runtergeladen https://www.redbooks.ibm.com/redbooks/pdfs/sg248326.pdf

    Muss jetzt mal schauen wo ich das Teil für V6 bekomme. Werde mich vermutlich nochmals melden ;-)

    GG 4250

  7. #7
    Registriert seit
    Feb 2001
    Beiträge
    18.495
    Wie Birgitta sagte, skalare Subselects sind grundsätzlich in Klapper ähm... Klammern zu setzen.

    Fetch first 1 rows only optimiert hier gar nichts, denn dies wirkt grundsätzlich nur auf das Ergebnis und nicht auf den Count oder einen Where.
    Je nach Index oder sonstigen Rahmenbedingungen kann ebenso ein Tablescan erfolgen.

    Der Count(*) ohne Where ist sowieso bereits SQL-Optimiert.

    Daher folgende Vereinfachung:

    CREATE FUNCTION rptrade/zaehler /*10.10.19 14:34*/
    ( DEBITOR dec(08) ) RETURNS
    CHAR(04) LANGUAGE SQL READS SQL DATA BEGIN
    return
    case when (select coalesce( count(*), 0) from dat020) = 0 then 'XXXX'
    else '0001'
    end;
    END;

    Der Coalesce ist erforderlich, da ein Subselect auch schon mal NULL zurückliefert wenn keine Daten vorhanden sind.

    Allerdings frage ich mich noch, wofür du den Eingangsparameter DEBITOR benötigst. Fehler der ggf. im Count?
    Dienstleistungen? Die gibt es hier: http://www.fuerchau.de
    Das Excel-AddIn: http://www.fuerchau.de/software/upload400.htm
    BI? Da war doch noch was: http://www.ftsolutions.de

  8. #8
    Registriert seit
    Jan 2012
    Beiträge
    894
    Klar, du hat recht. Bei count bringt fetch first row only nichts. War mein Denkfehler. Wir lösen die Problemstellung, zu wissen, ob bestimmte Einträge vorhanden sind, trotzdem mit fetch first row only, aber nicht mit count. Ich denke, dass es dann etwas bringt:
    Code:
    dcl-s vorhanden char(1) inz('N');
    exec sql select 'J' into :vorhanden from datei where ... fetch first row only;

  9. #9
    Registriert seit
    Aug 2006
    Beiträge
    1.890

    UDF stehe auf dem Schlauch

    Hallo *all,

    mir fehlt jetzt nur noch die Konvertierung von hex nach decimal. Finde es auf Anhieb nicht wie der cast aussehen muß. Weil ohne fällt das Teil ab 000A auf die Nase.

    Wie kann man eigentlich solche UDFs debuggen?

    Ansonsten sieht meine UDF so aus.

    Code:
    CREATE FUNCTION rptrade/zaehler /*11.10.19 10:51*/      
    ( DEBITOR dec(08) ) RETURNS                            
    CHAR(04)                                                
    LANGUAGE SQL MODIFIES SQL DATA ALLOW DEBUG MODE         
    DISALLOW PARALLEL                                       
    BEGIN                                                   
    DECLARE RETURNVAL CHAR   (04) NOT NULL DEFAULT '0000' ; 
    DECLARE i_zaehler decimal(04) DEFAULT 0;                
                                                           
     select d020werta into i_zaehler                       
            from dat020 where d020key = debitor;           
     if i_zaehler = 0 then                                 
        select d020werta into i_zaehler                    
               from dat020 order by d020werta desc         
                         fetch first row only;             
        set i_zaehler = i_zaehler + 1;                     
        insert into dat020 (d020key, d020werta)                     
               values(debitor, substr(hex(int(i_zaehler)), 5, 4));  
     end if;                                                        
     set returnval = substr(hex(int(i_zaehler)), 5, 4);             
     RETURN LTRIM(RETURNVAL);                                       
    END
    Geändert von KingofKning (11-10-19 um 10:25 Uhr) Grund: Noch Fragen offen

  10. #10
    Registriert seit
    Feb 2001
    Beiträge
    18.495
    Wie wäre es mit

    select 'J' into :vorhanden from datei where exists (...)
    Schließlich enthält der Exists implizit den Fetch first und ist für den Einzelsatzzugriff optimiert.
    Dienstleistungen? Die gibt es hier: http://www.fuerchau.de
    Das Excel-AddIn: http://www.fuerchau.de/software/upload400.htm
    BI? Da war doch noch was: http://www.ftsolutions.de

  11. #11
    Registriert seit
    Mar 2002
    Beiträge
    4.906
    Zitat Zitat von KingofKning Beitrag anzeigen
    Hallo *all,

    mir fehlt jetzt nur noch die Konvertierung von hex nach decimal. Finde es auf Anhieb nicht wie der cast aussehen muß. Weil ohne fällt das Teil ab 000A auf die Nase.

    Wie kann man eigentlich solche UDFs debuggen?

    Ansonsten sieht meine UDF so aus.

    Code:
    CREATE FUNCTION rptrade/zaehler /*11.10.19 10:51*/      
    ( DEBITOR dec(08) ) RETURNS                            
    CHAR(04)                                                
    LANGUAGE SQL MODIFIES SQL DATA ALLOW DEBUG MODE         
    DISALLOW PARALLEL                                       
    BEGIN                                                   
    DECLARE RETURNVAL CHAR   (04) NOT NULL DEFAULT '0000' ; 
    DECLARE i_zaehler decimal(04) DEFAULT 0;                
                                                           
     select d020werta into i_zaehler                       
            from dat020 where d020key = debitor;           
     if i_zaehler = 0 then                                 
        select d020werta into i_zaehler                    
               from dat020 order by d020werta desc         
                         fetch first row only;             
        set i_zaehler = i_zaehler + 1;                     
        insert into dat020 (d020key, d020werta)                     
               values(debitor, substr(hex(int(i_zaehler)), 5, 4));  
     end if;                                                        
     set returnval = substr(hex(int(i_zaehler)), 5, 4);             
     RETURN LTRIM(RETURNVAL);                                       
    END
    wenn ich das richtig verstehe, dann schreibst du einen Satz mit '0001' in dem Huddelfeld in die Datei, wenn ein Satz mit einer 0 (mit oder ohne Hierarchie) schon drinsteht.
    Im Returnwert gibst Du dann '0001' zurück.
    In allen anderen Fällen (kein Satz gefunden, oder schon zwei drin, geht Deine Procedure in die Grütze.

    Ist das so gewollt?

    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/

  12. #12
    Registriert seit
    Aug 2006
    Beiträge
    1.890
    Zitat Zitat von BenderD Beitrag anzeigen
    wenn ich das richtig verstehe, dann schreibst du einen Satz mit '0001' in dem Huddelfeld in die Datei, wenn ein Satz mit einer 0 (mit oder ohne Hierarchie) schon drinsteht.
    Im Returnwert gibst Du dann '0001' zurück.
    In allen anderen Fällen (kein Satz gefunden, oder schon zwei drin, geht Deine Procedure in die Grütze.

    Ist das so gewollt?

    D*B
    Kann ich jetzt nicht so bestätigen

    Code:
     Anfang auf Zeile . . .
     ....+....1....+....2..
        D020KEY   D020WERTA
              1     0001   
              2     0002   
              3     0003   
              4     0004   
              5     0005   
              6     0006   
              7     0007   
              8     0008   
              9     0009   
             10     000A   
     ********   Datenende
    Vermutlich werde ich mir morgen eine HEX nach DEC Funktion selber schreiben. Habe ich das letzte mal im Informatikunterricht 1982 auf einem CBM 8032 gemacht.
    Hätte nicht gedacht das ich das ein paar Tage später mal für ne AS/400 machen muß die die Funktion nicht kennt.

    GG 4250

Ähnliche Themen

  1. SQL Satzaufbau V6R1
    Von KingofKning im Forum NEWSboard Programmierung
    Antworten: 4
    Letzter Beitrag: 05-04-17, 10:36
  2. V6R1 strdbg
    Von KingofKning im Forum NEWSboard Programmierung
    Antworten: 4
    Letzter Beitrag: 27-01-16, 09:59
  3. V6R1 Datensicherung
    Von KingofKning im Forum IBM i Hauptforum
    Antworten: 12
    Letzter Beitrag: 11-11-15, 10:40
  4. Umstieg V5R4 -> V6R1 die II
    Von KingofKning im Forum IBM i Hauptforum
    Antworten: 2
    Letzter Beitrag: 29-10-15, 08:32
  5. V6R1 Backlevel
    Von KingofKning im Forum IBM i Hauptforum
    Antworten: 3
    Letzter Beitrag: 16-09-15, 18:21

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •