[NEWSboard IBMi Forum]

Hybrid View

  1. #1
    Registriert seit
    Feb 2001
    Beiträge
    20.254
    Trotzdem verwechselst du da was.
    "dcl-s String" ist eine Single-Variable während "dta" ein Prozedurparameter ist.
    Und "options(*varsize)" entspricht nicht "varchar".
    *varsize = Parameter per reference aber beliebiger Länge, die Länge wird nicht übergeben.
    varchar = Feld mit einer 2/4-Byte Längeninformation vorneweg

    Die klassische Definition im RPGLE erlaubt hier bis 7 Stellen, also knapp 10MB, ich habe 99.999.999 ausprobiert (also 99999999A) ohne Fehler.
    Die Free-Definition erlaubt da dann eben die klassische Grenze von knapp 16MB.
    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

  2. #2
    Registriert seit
    Dec 2003
    Beiträge
    53
    @all, danke für die Antworten

    @fuerchau, auch Dir Danke für die Antwort, Du hast natürlich vollkommen Recht.
    Mir ging es bei der Feld-Definition im RDi auch eigentlich nur um die Meldung von RDi bzgl. der maximalen Feldlänge, völlig unabhängig von der alten Prozedur bzw. den Prozedur-Parametern. Jetzt da ich weiß, dass ich den kompletten Satz aus der *.csv-Datei in ein Feld bekomme, werde ich mir vermutlich sowieso eine neue Funktion mit free und SQL basteln, die mir einen String mit jeweils einem Datensatz der *.csv-Datei an das Programm zurückgibt.

  3. #3
    Registriert seit
    Aug 2001
    Beiträge
    2.877
    Hmmm, ich würde eine SQL (Tabellen) Funktion basteln, die mir die komplette Tabele auflöst.

    Schau Dir mal die SQL-Funktionen GET_CLOB_FROM_FILE, sowie die Tabellen Funktion SYSTOOLS.SPLIT() an.

    Mit GET_CLOB_FROM_FILE kannst Du direkt auf die IFS-Datei zugreifen.
    Mit SPLIT() kannst Du einen String in einzelne Zeilen aufsplitten.

    Dann brauchst Du nur eine Common Table Expression (CTE), die die IFS-Datei zunächst einzelne Sätze (beim CRLF) aufsplittet. In einer zweiten CTE splittest Du dann die Zeilen in Spalten auf.
    Im Endgültigen SELECT musst Du das Ganze nur noch in Spalten ausgeben ... und voilà du liest eine CSV-Datei direkt aus dem IFS und gibst das Ganze in Spalten aus.

    Etwa so:

    Code:
    With x as (Select Ordinal_Position as RowKey, Element as RowInfo
                 from Table(SysTools.Split(Get_Clob_From_File('/home/Hauser/Employee.csv'), x'0D25')) a
                 Where Trim(Element) > ''),
         y as (Select x.*, Ordinal_Position ColKey,
                      Trim(B '"' from Element) as ColInfo 
                 from x cross join Table(SysTools.Split(RowInfo, ',')) a)
    Select RowKey,
           Min(Case When ColKey = 1 Then ColInfo End) EmployeeNo,     
           Min(Case When ColKey = 2 Then ColInfo End) Name,
           Min(Case When ColKey = 3 Then ColInfo End) FirstName,
           Min(Case When ColKey = 4 Then ColInfo End) Address,
           Min(Case When ColKey = 5 Then ColInfo End) Country,
           Min(Case When ColKey = 6 Then ColInfo End) ZipCode,
           Min(Case When ColKey = 7 Then ColInfo End) City
    From y
    Where RowKey > 1
    Group By RowKey;

    Im übrigen wenn Du mit SQL arbeitest, darf eine VarChar-Variable 32767 Byte nicht überschreiten. längere alphanumerische Variablen, die Du mit SQL verarbeiten möchtest, musst Du mit dem Schlüssel-Wort SQLTYPE als CLOB definieren (maximum 16 MB).

    Du kannst natürlich auch mir (embedded) SQL direkt auf IFS-Dateien zugreifen. In diesem Fall musst Du dann mit File-Referenz-Variablen arbeiten, die bebenfalls mit SQLTYPE definiert werden. In diesem Fall kannst du sogar IFS-Dateien bis zu 2 GB verarbeiten.

    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
    Feb 2001
    Beiträge
    20.254
    Alles gut und schön, aber warum immer alles selber machen, wenn es bereits CPYFRMIMPF gibt?
    Hier wird insbesonders auch auf die Zeichenfeldproblematik mit Anführungszeichen, STRDLM + STRESCCHR, berücksichtigt, Kopfzeile ausgeblendet und Typkonvertierung incl. Null-Flag durchgeführt.
    Fehler werden in einer Protokolldatei ausgegeben, also alles das, was man mit obigem statischen SQL nicht machen kann.
    Ich muss mir nur 1x die Mühe machen die Zieltabelle korrekt zu erstellen;-).
    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

  5. #5
    Registriert seit
    Aug 2001
    Beiträge
    2.877
    und warum sollte ich mir die Mühe machen einmalig eine Zieltabelle zu erstellen und die Daten dann da reinkopieren, um sie im Anschluss dann auszulesen und die Daten zu verarbeiten?

    Anstatt einmalig ein SQL-Statement zu erstellen, dass die Daten direkt aus dem IFS über ein SELECT statement ausliest und verarbeiten kann und zwar OHNE Zwischendatei. Da es sich um SQL handelt, können die Daten mit Hilfe von WHERE-Bedingungen gezielt gefiltert und auch z.B. mit einem INSERT Statement direkt dahin übertragen werden, wo sie hingehören.

    Im übrigen werden in meinem Beispiel die führenden und folgenden Anführungszeichen entfernt und auch die Überschrift ignoriert.

    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

  6. #6
    Registriert seit
    Feb 2001
    Beiträge
    20.254
    Dann lies doch bitte meinen Beitrag genauer. Mit SQL löst du nicht die Probleme STRDLM + STRESCCHR.
    Außerdem kann es schon mal vorkommen, dass das Trennzeichen in einer Zeichenkette vorkommt und dann scheitert der Split.
    Und meine Erfahrung sagt mir, dass es sich dabei eher selten um Einmalaktionen handelt sondert i.d.R. es sich um Importschnittstellen handelt. Und das würde ich dann schon (in meiner persönlichen Ansicht) stabiler lösen wollen.
    Der weitere Vorteil ist die Typsicherheit da es keiner weiteren Konvertierung bezgl. Zahlen und Datum gibt. Die Daten in der Tabelle sind direkt mit weiteren SQL-Methoden weiterverarbeitbar.
    Für Einmalaktionen verwende ich da gerne den einfachen 5250-Upload.

    Und ob ich mir die Mühe mache, den SQL solange auszuprobieren bis er passt oder ob ich mal eben einen CREATE TABLE und CPYFRMIMPF aufrufe sei mal dahningestellt was da schneller ist.

    Es gibt einfach viele Lösung bei der IBM i incl. diverser Excel-Tools und ich nehme für mich meistens den einfachen Weg.
    Das sind ja auch nur Vorschläge.
    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 2006
    Beiträge
    2.077
    Naja, die Lösung von Birgitta ist sicherlich charmant, wir sollten aber in Zukunft evtl dazu schreiben ab welchem Release das funktioniert.
    Ich vermute mal V6R1 geht noch nicht. (Nicht getestet) Deswegen ist es immer schön auch mal eine "klassiche Lösung" zu sehen.
    Und gerade im Forum was ja quasi ein Nachschlagewerk ist, ist es schön mehrere Lösungen zu sehen.

    GG 4139

  8. #8
    Registriert seit
    Feb 2001
    Beiträge
    20.254
    Einspruch: das hat mit "Klassisch" weniger zu tun als mehr mit "Stabil", "Sicher", "Performant".
    Letzteres ist bei kleineren Dateien eher unauffällig, aber messbar.

    Wenn man Birgittas SQL mal auflöst, ist da doch eine Menge an Einzelschritten durchzuführen:
    - komplettes Einlesen der IFS-Datei
    - Erstellen eines kompletten Zeilen-Arrays im Speicher
    - Erstellen eines Spalten-Arrays als Tabelle je Zeile
    - Gruppierungs-Array anlegen
    - den kleinsten Wert je Spalte ermitteln und zuordnen

    Konvertieren (casten) von Datum und Zahlwerten in den unterschiedlichen Ausprägungen ist da noch nicht berücksichtigt.

    Da kann mir keiner behaupten, dass dies performanter sein soll als der CPYFRMIMPF, vor allem, wenn die Importdateien gerne mal mehrere MB groß werden können.
    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
    Aug 2014
    Beiträge
    179
    Hallo liebes Forum,

    ich schätze die Beiträge sehr und trage auch selbst gerne zu Lösungen bei. Und doch wünsche ich mir mehr sachliche Diskussion und keine Diskussion in dem Stil: meine Lösung ist besser als deine. Für jede Aufgabenstellung gibt es mehrere Lösungen und die Leser des Forums sind gestandene IT-Fachleute, denen ich es zutraue, sich ein eigenes Urteil zu bilden, was die Vielfalt und Anwendbarkeit der Lösungen betrifft.

    In diesem Sinne stelle ich meine Idee mit der SQL-Function Split() vor. Die Function kam mit 7.3 TR 6 auf die Maschine. Der Sourcecode der Function kann mit dem Navigator eingesehen werden, damit ist es möglich, diese Function auf einem älteren Release zu implementieren.

    Unter dem Pfad /home/import/csv/adressen.csv sind folgende Daten gespeichert. Am Ende jedes Datensatzes ist ein Linefeed

    PHP-Code:
    10001,Leisha Leysner,80689,München,Amarellenweg
    10002
    ,Darion Willimczik,81669,München,Schleibingerstraße
    10003
    ,Helvi Holzwardt,81673,München,Dornbergstraße
    10004
    ,Theofánis Arndgen,80997,München,Reinoltstraße
    10005
    ,Tybi Klimczok,80999,München,Frühaufstraße
    10006
    ,Lieschen Bredenkötter,80804,München,Max-von-Gruber-Straße
    10007
    ,Andree Flächsenhaar,81369,München,Adunistraße
    10008
    ,Heber Uschkerat,80937,München,Karlsteinstraße
    10009
    ,Olyvia Füchtling,80331,München,Neuturmstraße
    10010
    ,Art Berendes,80999,München,Grünwedelstraße 
    Folgendes Statement liest die Datei und splittet sie in die einzelnen Datensätze

    Carriage Return = chr(13)
    Linefeed = chr(10)

    Code:
    select Ordinal_Position as Pos, Element
      from TABLE (SYSTOOLS.SPLIT(get_clob_from_file('/home/import/csv/adressen.csv'), chr(10)));
    Das Ergebnis

    PHP-Code:
    Pos Element
    -----------------------------------------------------------------------
    1    10001,Leisha Leysner,80689,München,Amarellenweg
    2    10002
    ,Darion Willimczik,81669,München,Schleibingerstraße
    3    10003
    ,Helvi Holzwardt,81673,München,Dornbergstraße
    4    10004
    ,Theofánis Arndgen,80997,München,Reinoltstraße
    5    10005
    ,Tybi Klimczok,80999,München,Frühaufstraße
    6    10006
    ,Lieschen Bredenkötter,80804,München,Max-von-Gruber-Straße
    7    10007
    ,Andree Flächsenhaar,81369,München,Adunistraße
    8    10008
    ,Heber Uschkerat,80937,München,Karlsteinstraße
    9    10009
    ,Olyvia Füchtling,80331,München,Neuturmstraße
    10   10010
    ,Art Berendes,80999,München,Grünwedelstraße 
    Das RPG-Programm sieht es so aus
    Code:
             ctl-opt dftactgrp(*no) main(main);
          //------------------------------------------------------------------//
          //                                                                  //
          // Einlesen einer CSV-Datei und Verarbeiten mit Split()             //
          //                                                                  //
          //-----------------                                                 //
          // R.Ross 01.2020 *                                                 //
          //------------------------------------------------------------------//
          // SQL-Options                                                      //
          //------------------------------------------------------------------//
    
             exec sql set option datfmt=*iso, timfmt=*iso, commit=*chg,
                                 closqlcsr=*endactgrp;
    
          //------------------------------------------------------------------//
          // Array Records - wird mit SQL gefüllt                             //
          //------------------------------------------------------------------//
    
             dcl-ds  DsRecords   qualified dim(10000) inz;
                      Id         int(10);
                      Text       varchar(256);
             end-ds;
    
          //------------------------------------------------------------------//
          // Main                                                             //
          //------------------------------------------------------------------//
             dcl-proc main;
    
             dcl-s   LocFile     varchar(256);
             dcl-s   LocCounter  uns(10);
    
               LocFile = '/home/import/csv/adressen.csv';
    
               exec sql declare cursor01 cursor for
                select Ordinal_Position, Element
                  from table (
                       systools.split(get_clob_from_file(:LocFile), chr(10)));
    
               exec sql open cursor01;
    
               exec sql fetch cursor01 for 10000 rows  // Fetch into Array
                         into :DsRecords;
    
               if sqlcode >= *zero;
                  exec sql GET DIAGNOSTICS :LocCounter = ROW_COUNT;
               endif;
    
               exec sql close cursor01;
    
             end-proc;
          //------------------------------------------------------------------//
    mit einem weiteren Split() auf den Datensatz werden die einzelnen Felder ausgelesen

    Code:
    select Ordinal_Position as Pos, Element
      from TABLE (SYSTOOLS.SPLIT('10001,Leisha Leysner,80689,München,Amarellenweg', ','));
    Das liefert folgendes Ergebnis

    PHP-Code:
    Pos Element
    ------------------
    1    10001
    2    Leisha Leysner
    3    80689
    4    München
    5    Amarellenweg 
    Herzliche Grüße
    Rainer Ross

    Ab und zu entwickle ich auch mal Spiele für die IBM i
    http://www.myhofi.com/tms/HTML/SlotMachine.html
    http://www.myhofi.com/chess/index.html

    aber normalerweise Webanwendungen so schnell wie Greenscreen
    http://www.myhofi.com/tms/HTML/Myapp.html

    hier ist der Kurs dazu
    https://www.toolmaker.de/schulungen/...ibm-i-kompakt/

  10. #10
    Registriert seit
    May 2002
    Beiträge
    1.121
    Die Function kam mit 7.3 TR 6 auf die Maschine. Der Sourcecode der Function kann mit dem Navigator eingesehen werden, damit ist es möglich, diese Function auf einem älteren Release zu implementieren.
    Allerdings müsste man dann einen Zugang zu einer Maschine haben, welche mindestens auf 7.3 TR6 läuft....

    Aber wir sollen ja dieses Jahr eine neue Maschiene bekommen. Freun mich dann schon es probieren zu können.

    Und ich finde alle Lösungen okay. Immer wieder schön zu sehen, dass viele Weg nach Rom führen ;-)

    Liebe Grüße
    Ronald

  11. #11
    Registriert seit
    Feb 2001
    Beiträge
    20.254
    Ich bekomme auch gerne Dateien mit mehr als 10000 Zeilen;-).
    Da würde ich dir eher eine Table-Function nach Birgittas Methode mit einzelnem Satz-Return empfehlen.
    Nach deiner Methode scheiterst du an der 16MB-Grenze;-).
    Auch die Split-Funktion wird da eine wohl eine ähnliche Grenze haben.

    Nach dem Fetch steht die Anzahl der Zeilen bereits in der SQLCA SQLER3;-).
    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
    Jul 2001
    Beiträge
    2.646
    Zitat Zitat von malzusrex Beitrag anzeigen
    Allerdings müsste man dann einen Zugang zu einer Maschine haben, welche mindestens auf 7.3 TR6 läuft....
    zum Testen wüsste ich da ja was ;-)

    Und ansonsten gilt wie immer: der GF auf die Füsse treten, daß auch die IT am Ball bleibt. Wir kennen alle die Diskussionen, aber erstaunlicherweise ist leider gerade unser Markt da sehr hartnäckig, Altblech zu betreiben.
    (Und das schreibe ich als jemand, der zwangsweise für einen Kunden eine CISC-Maschine betreibt...)
    www.RZKH.de
    IBM Champion 2022, 2023, 2024
    IBM i Community Advocate https://www.youracclaim.com/badges/6...c-7ad4ba147af6
    Common / CEAC
    http://pub400.com

Similar Threads

  1. Größe einer Collection begrenzen
    By M Scheid in forum IBM i Hauptforum
    Antworten: 2
    Letzter Beitrag: 03-12-14, 17:52
  2. CPI Größe
    By jojoschluckfirma in forum NEWSboard Programmierung
    Antworten: 2
    Letzter Beitrag: 03-12-14, 13:51
  3. Antworten: 3
    Letzter Beitrag: 20-12-13, 09:27
  4. Größe IFS
    By kuddel in forum IBM i Hauptforum
    Antworten: 3
    Letzter Beitrag: 05-02-03, 07:19
  5. Größe des IFS, wie ermitteln?
    By Spirou in forum IBM i Hauptforum
    Antworten: 6
    Letzter Beitrag: 17-04-02, 09:54

Berechtigungen

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