[NEWSboard IBMi Forum]
  1. #1
    Registriert seit
    Sep 2008
    Beiträge
    67

    Question Insert mit SQL Prozedur liefert Resultset mittels Final Table

    Mittels dem FINAL Table Statement lassen sich elegant die nach dem einfügen des Datensatzes generierten Werte (Autoincrement, [Row-Change]-Timestamp-Werte) auslesen:
    Code:
    SELECT * FROM FINAL TABLE (INSERT INTO [meinetable](col1, col2) values('A', 'B'));
    Jetzt haben wir schön für die Datenzugriffssicht SQL Prozeduren angelegt, die z.B. für den Insert ein Resultset basierend auf der FINAL Table zurückliefern, gebastelt. (Auf den physischen Tabellen sitzt eine View, d.h. die CRUD-Anweisungen werden auf die View abgesetzt, so auch aus der SQL-Prozedur).

    Bei einigen Tabellen habe ich jetzt Probleme bekommen, dass der zweite INSERT über die SQL Prozedur nicht mehr funktionieren wollte:
    Code:
    SQL-Status: 22011
    Vendorencode: -138
    Nachricht: [SQL0138] Argument *N der Funktion SUBSTRING oder LEFT ungültig. Ursache  . . . . :  Argument 2 oder Argument 3 der Funktion SUBSTRING oder Argument 2 der Funktion LEFT liegt entweder außerhalb des gültigen Bereichs oder ist ein Ausdruck, der nicht als ganze Zahl bewertet wird. -- Bei der Funktion SUBSTRING gibt Argument 2 die Position des ersten Zeichens des Ergebnisses und Argument 3 die Länge des Ergebnisses an. Argument 2 muss eine gültige Position des ersten Arguments sein. Argument 3 darf die Länge von Argument 1 zwischen Argument 2 und dem Ende der Zeichenfolge nicht überschreiten. -- Bei der Funktion LEFT gibt Argument 2 die Länge des Ergebnisses an. Argument 2 darf die Länge von Argument 1 nicht überschreiten. -- Ist Argument 1 eine Zeichenfolge oder eine Binärzeichenfolge, entspricht ein Zeichen einem Byte; ist Argument 1 eine Grafikzeichenfolge, ein Zeichen oder ein DBCS-Zeichen, entspricht ein Zeichen einem DBCS-Zeichen. -- Ist das Argument *N, ist eines der Argumente ungültig, aber die Nummer des Arguments ist nicht bekannt. Fehlerbeseitigung:  Ist das Argument *N, die vorherigen Nachrichten im Jobprotokoll anzeigen (Befehl DSPJOBLOG) oder F10 (Nachrichten im  Jobprotokoll anzeigen) in dieser Anzeige drücken, um das fehlerhafte Argument zu bestimmen. Ein oder mehrere in der Funktion SUBSTRING oder LEFT angegebene Argumente ändern. Die Skalarfunktion INTEGER kann verwendet werden, um das Argument in ein ganzzahliges Ergebnis umzusetzen. Die Anforderung wiederholen.
    Was ich herausgefunden habe, dass es an den Parametern der SQL Prozedur liegen könnte und das die vom System automatisch ermittelten Datentypen der Finaltable vielleicht hier mit den Parametern in die Quere kommen.

    Hier die Sourcen der verwendeten Objekte.
    Table:
    Code:
    [CREATE TABLE VAG13P (
     AG13ID   INT GENERATED ALWAYS AS IDENTITY(INCREMENT BY 1) PRIMARY KEY, 
     AG13ID12 INT NOT NULL   with default 0,
     AG13MENG DECIMAL(11, 3) NOT NULL WITH DEFAULT 0,  -- Menge
     AG13RAB  DECIMAL(5, 2) NOT NULL WITH DEFAULT 0,  -- Rabatt 1 
    -- Systemfelder
     Created  FOR AG13DATA TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP , 
     Changed  FOR AG13DATE TIMESTAMP NOT NULL GENERATED ALWAYS FOR EACH ROW ON UPDATE AS ROW CHANGE TIMESTAMP ,
     Jobuser  FOR AG13BENA VARCHAR(50) NOT NULL DEFAULT USER ,
     UserEdit FOR AG13BENE VARCHAR(50) NOT NULL DEFAULT USER ,
     WrkStnName FOR AG13WSNAM VARCHAR(50) NOT NULL DEFAULT '' ,
     ClientProgramID FOR AG13CPGMID VarChar(50) NOT NULL DEFAULT '' ,
     ClientApplName FOR AG13CPGM VarChar(50) NOT NULL DEFAULT '',
    -- Fremdschlüssel
     FOREIGN KEY(AG13ID12) REFERENCES VAG12P(AG12ID) ON UPDATE RESTRICT ON DELETE CASCADE
    )
    RCDFMT AG13F1;
    View:
    Code:
    CREATE or REPLACE VIEW mdblib.vVag13P01  AS
     SELECT 
      a.*
      ,CAST(a.CHANGED as VarChar(26)) Version
      
     FROM mdblib.Vag13P a
    ;
    SQL-Procedure für INSERT:
    Code:
    CREATE PROCEDURE hgwobj.vag13_insert( 
     IN pag13ID12 INTEGER,
     IN pag13meng decimal(11,3),
     IN pag13rab decimal (5,2),
    -- Systemfelder
     IN pWRKSTNNAME VARCHAR(50),
     IN pCLIENTPROGRAMID VARCHAR(50),
     IN pCLIENTAPPLNAME VARCHAR(50)
    )
    LANGUAGE SQL MODIFIES SQL DATA
    DYNAMIC RESULT SETS 1
    set option COMMIT = *CHG 
    BEGIN
    
    DECLARE C1 CURSOR WITH RETURN TO CALLER FOR 
    SELECT * FROM FINAL TABLE (
     INSERT INTO vVag13P01
     (
      ag13ID12, ag13meng, ag13rab,
      WRKSTNNAME,  CLIENTPROGRAMID, CLIENTAPPLNAME
     )
     VALUES
     (
      pag13ID12, pag13meng, pag13rab,
      pWRKSTNNAME, pCLIENTPROGRAMID, pCLIENTAPPLNAME
     )
    );
    -- Cursor öffnen u. zurückgeben
    OPEN C1;
    SET RESULT SETS WITH RETURN TO CALLER CURSOR C1;
    END;
    Ich hatte den Fehler bereits in einer anderen Insert-Prozedur behoben, hier musste ich den Datentyp des Parameters von Timestamp(0) auf Timestamp ändern. Im obigen Fall hilft es, den dritten Parameter ( IN pag13rab decimal (5,2)) von decimal(5,2) auf decimal(11,3) zu ändern.

    Leider verstehe ich nicht warum. Meine Vermutung ist, dass das Final Table den maximalen Bereich pro Datentyp für alle gleichartigen Spalten festlegt, oder das FINAL Table mit der Art u. Weise wie ich den Cursor zurück liefere nicht zurechtkommen mag.

    Bislang hatte ich die Parameter immer 1:1 anhand der Tabellendefinition der Spalten gemacht, oder ist das falsch?
    Warum verhält es sich nur manchmal so?

  2. #2
    Registriert seit
    Feb 2001
    Beiträge
    18.682
    Ein Insert in eine View funktioniert in der Regel nur sauber, wenn die View keine berechneten Felder hat.
    Du solltest ggf. besser die Felder, die du zurückerhalten willst, genau benennen an Stelle von

    SELECT * FROM FINAL TABLE

    Meine Empfehlung ist hier, den Insert in dieser Kombination eher auf die Tabelle als auf die View zu machen.
    Wenn du unbedingt den Timestamp casten willst, dann mach das in diesem Select.
    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

  3. #3
    Registriert seit
    Sep 2008
    Beiträge
    67
    Hallo Herr Fürchau, danke für die Antwort.

    Was ich herausgefunden habe:
    • Egal ob physische Tabelle oder View, der zweite Insert schlägt fehl
    • Egal ob ich im SELECT x FINAL TABLE die Spalten angebe oder mit JOKER-Zeichen arbeite, der zweite Insert schlägt fehl
    • Im Jobprotokoll beschwert sich das System über den o.g. Fehler für die Spalte WSNAM (also eines der Systemfelder am Ende der Tabelle)
      Code:
      SQL-Status: 22011
      Vendorencode: -138
      Nachricht: [SQL0138] Argument *N der Funktion SUBSTRING oder LEFT ungültig.
      Entferne ich diese Systemfelder (Ersteller, Erstellzeit etc.) aus der SQL Prozedur u. dem darin enthaltenen Spalten auch beim Insert, beanstandet mir die Runtime zuletzt einen Fehler mit der Spalte "Rabattwert"

    Code:
    SQL-Status: 22023
    Vendorencode: -406
    Nachricht: [SQL0406] Umsetzungsfehler bei der Zuordnung zu Spalte RABATTWERT. Ursache  . . . . :  Bei dem Versuch, Spalte RABATTWERT mit einer Anweisung INSERT, UPDATE, ALTER TABLE oder REFRESH TABLE einen Wert zuzuordnen, ist ein Umsetzungsfehler der Art 6 aufgetreten. Wurde eine Vorkompilierung durchgeführt, ist der Fehler aufgetreten, als eine numerische Konstante in dieselben Attribute wie Spalte RABATTWERT umgesetzt werden sollte. Mögliche Fehlerarten sind: -- Fehlerart 1 - Überlauf. -- Fehlerart 2 - Gleitkommaüberlauf. -- Fehlerart 3 - Gleitkommaunterlauf. -- Fehlerart 4 - Gleitkommaumsetzungsfehler. -- Fehlerart 5 - Ungenaues Ergebnis. -- Fehlerart 6 - Ungültige numerische Daten. -- Fehlerart 7 - Ungültige DBCS-Daten. Fehlerbeseitigung:  Die Anweisung so ändern, dass der Ergebniswert in Spalte RABATTWERT passt und gültig ist, oder die Tabelle oder Sicht unter Angabe einer neuen Art oder einer neuen Länge für Spalte RABATTWERT erneut erstellen, so dass der Ergebniswert zugeordnet werden kann. Technische Beschreibung  . . . . . . . :  Während der Vorkompilierung wurde versucht, numerische Konstanten in INSERT- und UPDATE-Anweisungen in die Attribute der Zielspalte umzusetzen. Dies hätte eine Leistungssteigerung beim Aufrufen des Programms zur Folge.
    Das Problem liegt also nicht an den Systemfeldern die es anfangs im Joblog beanstandet, sondern eigentlich an dem numerischen Rabattfeld mit Decimal(5,2). Wenn ich diesen Prozedurparameter mit IN pRabattWert decimal (11,3) definiere, funktioniert es. Am Select des Final-Table Statements dürfte es nicht liegen, da ich hier mit
    Code:
    SELECT RabattId, Menge, cast(RabattWert as decimal(5,2)) RabattWert... FROM FINAL TABLE (
    keinen Erfolg hatte.

    Bislang hatte ich folgende Datentypen verwendet:
    • Int(eger) für ganze Zahlen
    • Decimal(x,y) für Fließkommazahlen
    • [N]VarChar(x) für Texte

    Ist Decimal hier evtl. nicht ideal und führt zu Konvertierungsproblemen gerade auch mit C# im Nachgang?

    PS: Ich hatte die Feldnamen im Zuge der Überarbeitung angepasst u. die Suffixe des Tabellennamens für die Spalten weggelassen!!!

  4. #4
    Registriert seit
    Feb 2001
    Beiträge
    18.682
    Das Problem ist halt manchmal der Autocast.
    Wenn die Feldtypen nicht stimmen, versucht SQL eine Typanpassung.
    Bei dynamischem SQL klappt dies meistens, beim statischen SQL (wie in der Prozedur) kann es da scon Probleme geben. Wobei diese hier eher C-spezifisch sind.

    Die Frage ist hier: Wie rufst du die Prozedur denn auf "select * from MyProc(?, ?, ...)"?
    Wichtig ist hier ggf. die korrekte Parameterdefinition im Command-Objekt.
    Im Normalfall solltest du deinen CommandText mit Parametermarkern "?" definieren und dann Parameters.Refresh (o.ä.) aufrufen um die korrekte Definition festzustellen.

    Benannte Parameter werden ggf. dabei nicht unterstützt.

    Arbeitest du ohne Parametermarker so ist die korrekte Übergabe der Werte zwingend Voraussetzung.
    Bei Zahlen sind genau so viele Ziffern erforderlich wie erwartet, ebenso auch das Komma bzw. der Punkt.
    Z.B. insert into MyTable (F1, F2) values(123456789,12 , 12345,12 )
    Dabei sind dann ebenso Vornullen zu formatieren.

    SQL legt dann auf dem Server ein cached Statement mit genau der Parameter-Definition an, die der 1. Aufruf vorgibt. Wenn du dann beim nächsten Aufruf andere Parameter übergibst, kommt es zu Konvertierungsproblemen.
    Deshalb bei solchen Sachen immer mit Parametermarkern arbeiten.
    Casts sind da auch nicht hilfreich, da Konstanten vom Optimizer intern entfernt und wiederum selber als Parametermarker definiert werden und wiederum der Typ an Hand der Konstante bestimmt wird.
    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

  5. #5
    Registriert seit
    Sep 2008
    Beiträge
    67

    Unhappy

    Zitat Zitat von Fuerchau Beitrag anzeigen
    Das Problem ist halt manchmal der Autocast.
    Wenn die Feldtypen nicht stimmen, versucht SQL eine Typanpassung.
    ...
    Die Frage ist hier: Wie rufst du die Prozedur denn auf "select * from MyProc(?, ?, ...)"?
    Über SQL Prozedur ausführen im Nachgang an die Erstellungsroutine der SQL Prozedur habe ich eine "Test"-Rubrik wo ich im o.g. Fall z.B. 2 x mal den gleichen Command absetze:
    Code:
    call hgwobj.vag13_insert(5, 23, 22.233, 'WRKSTN', 'SQL', 'SQL Prozedur ausführen');
    call hgwobj.vag13_insert(5, 23, 22.233, 'WRKSTN', 'SQL', 'SQL Prozedur ausführen');
    Der erste klappt, der zweite nicht.

    Wenn ich das FINAL Table in der SQL-Prozedur weglasse u. stattdessen "old-school" über IDENTITY_VAL_LOCAL() arbeite um mir die ID des Inserts zu holen und im Anschluss den Cursor über den/die Sätze zurückgebe klappt es ja ohne Probleme!

    Hier der geänderte Teil der SQL Prozedur:
    Code:
    BEGIN
    
    
    DECLARE pId INTEGER DEFAULT 0;
    DECLARE C1 CURSOR WITH RETURN TO CALLER FOR 
    SELECT * FROM vVag13P01 where id = pId;
    
    
     INSERT INTO vVag13P01
     (
      RabattId, Menge, RabattWert
      ,WRKSTNNAME,  CLIENTPROGRAMID, CLIENTAPPLNAME
     )
     VALUES
     (
      pRabattId, pMenge, pRabattWert
      ,pWRKSTNNAME, pCLIENTPROGRAMID, pCLIENTAPPLNAME
     );
    
    
    SET pId = IDENTITY_VAL_LOCAL();
    
    
    IF (pId > 0 ) THEN
    -- Cursor öffnen u. zurückgeben
     OPEN C1;
     SET RESULT SETS WITH RETURN TO CALLER CURSOR C1;
    END IF; 
    
    
    END;
    Auch wenn ich es in einem BEGIN/END-Block zusammenfasse um saubere Variablen vom gleichen Typ zu haben, kommt der gleiche Fehler:
    Code:
    BEGIN
    DECLARE pRabattId INTEGER;
    DECLARE pMenge  decimal(11,3);
    DECLARE pRabattWert decimal (5,2);
    -- Systemfelder
    DECLARE pWRKSTNNAME  VARCHAR(50);
    DECLARE pCLIENTPROGRAM VARCHAR(50);
    DECLARE pCLIENTAPPLNAME VARCHAR(50);
    SET pRabattId   = 5;
    SET pMenge   = 00000001.000;
    SET pRabattWert  = 000.33;
    SET pWRKSTNNAME  = 'WRKSTN';
    SET pCLIENTPROGRAM  = 'CPGMID';
    SET pCLIENTAPPLNAME  = 'APPLNAME';
    
    -- call hgwobj.vag13_insert(5, 1, 2, 'WRKSTN', 'SQL', 'SQL Prozedur ausführen');
    
    call hgwobj.vag13_insert(pRabattId, pMenge, pRabattWert, pWRKSTNNAME, pCLIENTPROGRAM, pCLIENTAPPLNAME);
    
    SET pMenge   = 00000002.200;
    SET pRabattWert  = 001.33;
    call hgwobj.vag13_insert(pRabattId, pMenge, pRabattWert, pWRKSTNNAME, pCLIENTPROGRAM, pCLIENTAPPLNAME);
    
    
    rollback;
    END;
    Fazit für mich ist erstmal, dass ich das FINAL Table hier lieber sein lasse u. mir den Cursor selbst basierend auf der generierten ID zurückliefern lasse. Das ist vermutlich auch für Tabellen ohne Autoinkrementspalte der einzige Weg, die Änderungen der Datenbank abzufragen.

  6. #6
    Registriert seit
    Feb 2001
    Beiträge
    18.682
    Oder mal eine Fehlermeldung an IBM abgeben. Auch die IBM soll ja nicht ganz fehlerfrei arbeiten.
    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

  7. #7
    Registriert seit
    Mar 2002
    Beiträge
    4.930
    ... ich finde irgendwie kein close auf den Cursor. Declare cursor ist eine rein deklarative Compiler Anweisung, beim open wird dann ein impliziter prepare mit gemacht. Das müsste eigentlich noch ein warning (cursor state not valid) beim zweiten Aufruf bringen.
    Darüber hinaus gibt es noch ein paar Dinge, die ich nicht verstehe:
    - warum erfolgt die Rückgabe per ResultSet?
    - warum erfolgt die Rückgabe nicht über in/out parameter? (alle Felder hin, die generierten Werte kommen als out verändert zurück)
    - weshalb der cast auf den Timestamp?
    - warum heißt der changed Timestamp Version (als Version taugt der nicht, das kann schief gehen!)?
    - generell sollte man condition handler für error vorsehen, sonst düst man unversehens raus.

    Dieter Bender
    AS400 Freeware
    http://www.bender-dv.de
    Mit embedded SQL in RPG auf Datenbanken von ADABAS bis XBASE zugreifen
    http://sourceforge.net/projects/appserver4rpg/

  8. #8
    Registriert seit
    Feb 2001
    Beiträge
    18.682
    Der Timestamp-Cast ist wohl dem ODBC-Zugriff (C#) geschuldet, da dieser ggf. damit nicht zurechtkommt.
    Für den CLose ist doch eigentlich der Aufrufer zuständig, wobei dieser ja vom Cursor-Namen nichts kennt.
    Aber ohne Final Table scheints ja zu funktionieren.
    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

  9. #9
    Registriert seit
    Sep 2008
    Beiträge
    67

    Smile

    Hallo Herr Bender,
    Hallo Herr Fürchau,

    danke für die Antwort. Aktuell habe ich ein Ticket bei IBM zu dem Thema laufen. Mal sehen was zu dem Thema mit dem Final Table herauskommt.

    Zitat Zitat von BenderD Beitrag anzeigen
    1. ... ich finde irgendwie kein close auf den Cursor. Declare cursor ist eine rein deklarative Compiler Anweisung, beim open wird dann ein impliziter prepare mit gemacht. Das müsste eigentlich noch ein warning (cursor state not valid) beim zweiten Aufruf bringen.
    Darüber hinaus gibt es noch ein paar Dinge, die ich nicht verstehe:
    - 2. warum erfolgt die Rückgabe per ResultSet?
    - 3. warum erfolgt die Rückgabe nicht über in/out parameter? (alle Felder hin, die generierten Werte kommen als out verändert zurück)
    - 4. weshalb der cast auf den Timestamp?
    - 5. warum heißt der changed Timestamp Version (als Version taugt der nicht, das kann schief gehen!)?
    - 6. generell sollte man condition handler für error vorsehen, sonst düst man unversehens raus.

    Dieter Bender
    1. Das Resultset soll an die aufrufende Instanz (C# Command-Objekt bzw. ILERPG) zurückgeliefert werden können. Ich habe es eben nochmals gestestet, wenn ich den CLOSE Aufrufe kommt kein Resultset zurück. Ein Warning habe ich keines in den Nachrichten bzw. Joblog gesehen.
    2. Eine Rückgabe per Result ist meiner Meinung nach flexibler, d.h. ich liefere einen Satz zurück u. nicht mittels Versorgung von 50 INOUT Parametern. Das wäre im C# der Tot eine solche Parameterlatte in einer Schleife in eine DataTable zu pumpen bzw. bei Verwendung von typisierten DataSets (In-Memory-Datenbank mit Relation) arbeitet man mit TableAdaptern - diese benötigen ein Resultset u. können keine Satzweise Verarbeitung.
    3. siehe 2.
    4. Wie Herr Fürchau angemerkt hat, ist leider der ODBC Treiber nicht in der Lage TIMESTAMP(6) darzustellen, sondern schafft maximal TIMESTAMP(0) - zumindest in der Standardeinstellung. Durch den CAST auf einen String erzeuge ich quasi eine "Pseudo-GUID" -mit Gültigkeit für den einen Datensatz - bitte nicht falsch Verstehen, es ist kein Primary Key!
    5. Bislang keine Probleme gehabt - zählt "Version" zu den reservierten Schlüsselwörtern? Wäre RowVersion besser?
    6. Thema Exceptionhandling ist hier an dieser Stelle nicht gewollt - die Aufrufende Instanz der Logikschicht (AS400 über den SQLCode u. C# bekommt bei Fehler eine OdbcException) soll je nach Fehler reagieren.

  10. #10
    Registriert seit
    Feb 2001
    Beiträge
    18.682
    Statt ODBC-Treiber sollte man den OLEDB-Treiber (IBMDASQL) verwenden.
    Dann braucht man auch keine ODBC-Registrierung.
    Zur Vereinfachung der Konfiguration kann man eine "xxx.UDL"-Datei erstellen. Diese lässt sich per Doppelklick auch einfach konfigurieren.
    In einer OLEDB-Connection gebe ich die Konfiguration einfach so an:

    ConnectionString = "File Name=c:\test.udl"
    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.930
    Zitat Zitat von Gutmann Beitrag anzeigen
    Hallo Herr Bender,
    Hallo Herr Fürchau,

    danke für die Antwort. Aktuell habe ich ein Ticket bei IBM zu dem Thema laufen. Mal sehen was zu dem Thema mit dem Final Table herauskommt.



    1. Das Resultset soll an die aufrufende Instanz (C# Command-Objekt bzw. ILERPG) zurückgeliefert werden können. Ich habe es eben nochmals gestestet, wenn ich den CLOSE Aufrufe kommt kein Resultset zurück. Ein Warning habe ich keines in den Nachrichten bzw. Joblog gesehen.
    2. Eine Rückgabe per Result ist meiner Meinung nach flexibler, d.h. ich liefere einen Satz zurück u. nicht mittels Versorgung von 50 INOUT Parametern. Das wäre im C# der Tot eine solche Parameterlatte in einer Schleife in eine DataTable zu pumpen bzw. bei Verwendung von typisierten DataSets (In-Memory-Datenbank mit Relation) arbeitet man mit TableAdaptern - diese benötigen ein Resultset u. können keine Satzweise Verarbeitung.
    3. siehe 2.
    4. Wie Herr Fürchau angemerkt hat, ist leider der ODBC Treiber nicht in der Lage TIMESTAMP(6) darzustellen, sondern schafft maximal TIMESTAMP(0) - zumindest in der Standardeinstellung. Durch den CAST auf einen String erzeuge ich quasi eine "Pseudo-GUID" -mit Gültigkeit für den einen Datensatz - bitte nicht falsch Verstehen, es ist kein Primary Key!
    5. Bislang keine Probleme gehabt - zählt "Version" zu den reservierten Schlüsselwörtern? Wäre RowVersion besser?
    6. Thema Exceptionhandling ist hier an dieser Stelle nicht gewollt - die Aufrufende Instanz der Logikschicht (AS400 über den SQLCode u. C# bekommt bei Fehler eine OdbcException) soll je nach Fehler reagieren.
    ad 1.: das ResultSet muss bei der Rückgabe geöffnet sein. Die Frage bezog sich darauf, dass es vor dem erneuten open closed sein muss (also am Anfang close!)
    ad 2/3.: Das ist halt die Crux mit den stored Procedures, da gibt es im handling der verschiedenen SQL Dialekte Unterschiede, die halt zu Randproblemen führen können.
    ad 4.: der insert in die View mit dem cast ist schon ein wenig schwindelig...
    ad 5.: VERSION ist in der Tat reserviertes Wort (könnte man aber rausmaskieren mit :"VERSION", was ich meinte war, dass Timestamps nicht eindeutig sind.
    ad 6.: Ohne Continue handler kriegt man innerhalb der Procedure nichts mehr mit und düst direkt raus. Das ist gerade im verteilten Umfeld nicht so toll, da sollte man zumindest das ein oder andere noch protokolieren...

    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
    Sep 2008
    Beiträge
    67
    IBM hat ein PTF SI64636 erstellt damit der Fehler mit dem Final-TABLE Statement behoben ist. Testen werden wir das ganze allerdings erst zum Jahreswechsel.

Ähnliche Themen

  1. RPG-Prozedur aus C# aufrufen
    Von svit im Forum NEWSboard Programmierung
    Antworten: 2
    Letzter Beitrag: 03-03-16, 11:11
  2. Antworten: 9
    Letzter Beitrag: 22-12-15, 12:08
  3. CLLE als Prozedur ins Serviceprogramm
    Von Etherion im Forum NEWSboard Programmierung
    Antworten: 6
    Letzter Beitrag: 30-09-14, 13:36
  4. RPG Resultset verarbeieten
    Von mk im Forum NEWSboard Programmierung
    Antworten: 3
    Letzter Beitrag: 22-09-14, 06:58
  5. IBMDA400 liefert keine Daten
    Von JMH im Forum IBM i Hauptforum
    Antworten: 7
    Letzter Beitrag: 15-01-14, 14:53

Stichworte

Berechtigungen

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