Announcement

Collapse
No announcement yet.

Rückmeldung für neuen Datensatz

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Rückmeldung für neuen Datensatz

    Umgebung : D5, IBX452, IB6.01. Eine Tabelle (Zahlungstermin) bekommt eine fortlaufende Vorgangsnummer. Hierfür ist ein Generator und ein Trigger installiert. Aus dem Formular soll folgendes passieren : <br>
    Button Neu - Neuer Datensatz mit neuer Nummer, Aktuelles Formulardatum. Dazu habe ich leider nur folgende Konstruktion hinbekommen :<br>
    Create Procedure InsertZV<br>
    (<br>
    dat date<br>
    )<br>
    returns<br>
    (<br>
    lfd integer<br>
    )<br>
    as<br>
    begin<br>
    insert into Zahlungsvorgang(Erfassungsdatum)<br>
    values<br>
    (<br>
    :dat<br>
    );<br>
    select max(lfdnummer) from Zahlungsvorgang into :lfd;<br>

    suspend;<br>
    end;<br>

    Geht das nicht schöner ?

  • #2
    Hi,

    ganz einfach: Trigger wegwerfen und in Delphi TIBDataSet verwenden. Dort kann über die Eigenschaft GeneratorField beim Insert automatisch ein Generatorwert zugewiesen werden, der in Delphi mit TabellenName['ID'] auch auslesbar ist

    Grüße
    Wolfgan

    Comment


    • #3
      Hallo,

      kein Unterschied zur Stored-Proc bei der Geschwindigkeit ? Es sind bis zu 10 Anwender, die gleichzeitig neue Datensätze anlegen. Ich vermutete, es ist günstiger, alles auf den Server zu verlegen ! Gibt es eine Funktionsbeschreibung zu IBDataset, ich bekomme kein Insert hin.

      Gruss G

      Comment


      • #4
        Hallo,

        wenn man einen neuen Datensatz über eine Stored Procedure anlegt, kann man dort gleich alle Dinge auf einmal erledigen: <br>
        1. Neuen Generatorwert für den Primärschlüssel abfragen und der Primärschlüsselspalte zuweisen. Die Abfrage über MAX ist zum einen sehr ineffektiv und zum anderen ungenau, wenn der "falsche" Isolation Level verwendet wird.<br>
        2. Den im Schritt 1 ermittelten Wert als Rückgabewert an den Client zurückliefern, so dass dieser den Primärschlüsselwert "kennt".<br>

        Im Vergleich zum Automatismus von TIBDataSet benötigt die Stored Procedure nur einen Aufruf der Datenbank, während TIBDataSet zwei braucht (zuerst Generatorwert abholen und erst dann INSERT). Wenn die Datenbank ausgelastet wird, ist der Weg über die Stored Procedure immer effektiver als der TIBDataSet-Automatismus.

        Das folgende Beispiel einer Stored Procedure stammt aus meiner IBX-Beispielanwendung <i>RedSys2</i>, die hier im Forum im Ordner <i>Delphi | IBX | RedSys2</i> heruntergeladen werden kann:
        <pre>
        /* ++++++++++++++++++++++++++++++++++++++++++++++++++ +++++++++++++ */
        /* Ausgebuchtes Manuskript wird als KOR1-Stand gespeichert */
        /* Fall a) Erstmaliger KOR1-Stand: Neuen Datensatz in DOCBLOB */
        /* Neuen Wert von DOCBLOBID als Output */
        /* Fall b) Update des KOR1-Standes */
        /* ++++++++++++++++++++++++++++++++++++++++++++++++++ +++++++++++++ */

        CREATE PROCEDURE ImportKOR1 (iManuskriptID INTEGER, iCount INTEGER)
        RETURNS (iKOR1BLOBID INTEGER)
        AS
        DECLARE VARIABLE BLOBID INTEGER;
        BEGIN
        SELECT KOR1_BLOBID
        FROM Manuskript
        WHERE ManuskriptID = :iManuskriptID
        INTO :BLOBID;
        /* Aktualisierung oder neue KOR-Stufe? */
        IF (:BLOBID IS NULL) THEN
        BEGIN
        /* Neuen Datensatz in DOCBLOB anlegen */
        BLOBID = GEN_ID(GEN_DOCBLOBID,1);
        INSERT INTO DOCBLOB (DOCBLOBID) VALUES (:BLOBID);
        /* Datensatz in Manuskript aktualisieren */
        UPDATE MANUSKRIPT
        SET KOR1_BLOBID = :BLOBID
        WHERE MANUSKRIPTID = :iManuskriptID;
        END
        /* Zeichenanzahl + Ausbuch-Daten in jedem Fall aktualisieren */
        UPDATE MANUSKRIPT SET
        ZEICHENANZAHL = :iCount,
        AUSBUCHDATUM = NULL,
        DOCNAME = NULL,
        RECHNER = NULL,
        KOR1_DATUM = 'TODAY'
        WHERE MANUSKRIPTID = :iManuskriptID;
        /* Neuen BLOBID-Wert zurückliefern */
        iKOR1BLOBID =BLOBID;
        END
        ^
        </pre>
        &#10

        Comment


        • #5
          Vielen Dank,
          klappt für alle Tabellen bis auf eine Gut. Diese Tabelle hat inzwischen 20 000 Datensätze, einen primary und einen normalen index. Das Einfügen über eine SP oder auch über Dataset dauert zeitweise 10 sec oder mehr, bis eine Rückmeldung da ist.<br>
          Da auch ein Zugriff über ISDN erfolgt, ist das besonders übel. Die anderen Tabellen mit 4-5000 Datensätzen, mit teilweise doppelt sovielen Feldern und Indexen mache da keine Probleme.<br>
          Kennt jemand einen Lösungsansatz ?

          Gruß Günte

          Comment


          • #6
            Hallo,

            das liegt nicht an der SP, sondern vermutlich an anderen offenen Datenmengen im Programm, bei denen das <i>FetchAll</i>-Problem dazu führt, dass alle Datensätze dieser Tabelle nach dem Einfügen neu abgeholt werden. Was protokolliert TIBSQLMonitor beim Aufruf der SP mit

            Comment


            • #7
              Hallo,<br>
              die Insertprocedure füllt 7 Felder, auf dem Server wird intern eine neue Nummer für den primary Index vergeben.<br>
              Der Monitor zeigt vieles mehrfach an:<br>

              [Application: Neuling Net 2]
              : [Start transaction]

              [Application: Neuling Net 2]
              IBSPInsertteile: [Prepare] SELECT RDB$PARAMETER_NAME, RDB$PARAMETER_TYPE FROM RDB$PROCEDURE_PARAMETERS WHERE RDB$PROCEDURE_NAME = 'INSERTTEILE' ORDER BY RDB$PARAMETER_NUMBER

              Plan: PLAN SORT ((RDB$PROCEDURE_PARAMETERS INDEX (RDB$INDEX_18)))

              [Application: Neuling Net 2]
              IBSPInsertteile: [Execute] SELECT RDB$PARAMETER_NAME, RDB$PARAMETER_TYPE FROM RDB$PROCEDURE_PARAMETERS WHERE RDB$PROCEDURE_NAME = 'INSERTTEILE' ORDER BY RDB$PARAMETER_NUMBER

              [Application: Neuling Net 2]
              IBSPInsertteile: [Fetch] SELECT RDB$PARAMETER_NAME, RDB$PARAMETER_TYPE FROM RDB$PROCEDURE_PARAMETERS WHERE RDB$PROCEDURE_NAME = 'INSERTTEILE' ORDER BY RDB$PARAMETER_NUMBER

              [Application: Neuling Net 2]
              IBSPInsertteile: [Fetch] SELECT RDB$PARAMETER_NAME, RDB$PARAMETER_TYPE FROM RDB$PROCEDURE_PARAMETERS WHERE RDB$PROCEDURE_NAME = 'INSERTTEILE' ORDER BY RDB$PARAMETER_NUMBER

              [Application: Neuling Net 2]
              IBSPInsertteile: [Fetch] SELECT RDB$PARAMETER_NAME, RDB$PARAMETER_TYPE FROM RDB$PROCEDURE_PARAMETERS WHERE RDB$PROCEDURE_NAME = 'INSERTTEILE' ORDER BY RDB$PARAMETER_NUMBER

              [Application: Neuling Net 2]
              IBSPInsertteile: [Fetch] SELECT RDB$PARAMETER_NAME, RDB$PARAMETER_TYPE FROM RDB$PROCEDURE_PARAMETERS WHERE RDB$PROCEDURE_NAME = 'INSERTTEILE' ORDER BY RDB$PARAMETER_NUMBER

              [Application: Neuling Net 2]
              IBSPInsertteile: [Fetch] SELECT RDB$PARAMETER_NAME, RDB$PARAMETER_TYPE FROM RDB$PROCEDURE_PARAMETERS WHERE RDB$PROCEDURE_NAME = 'INSERTTEILE' ORDER BY RDB$PARAMETER_NUMBER

              [Application: Neuling Net 2]
              IBSPInsertteile: [Fetch] SELECT RDB$PARAMETER_NAME, RDB$PARAMETER_TYPE FROM RDB$PROCEDURE_PARAMETERS WHERE RDB$PROCEDURE_NAME = 'INSERTTEILE' ORDER BY RDB$PARAMETER_NUMBER

              [Application: Neuling Net 2]
              IBSPInsertteile: [Fetch] SELECT RDB$PARAMETER_NAME, RDB$PARAMETER_TYPE FROM RDB$PROCEDURE_PARAMETERS WHERE RDB$PROCEDURE_NAME = 'INSERTTEILE' ORDER BY RDB$PARAMETER_NUMBER

              SEOFReached

              [Application: Neuling Net 2]
              : [Commit (Hard commit)]

              [Application: Neuling Net 2]
              IBSPInsertteile: [Prepare] Execute Procedure "INSERTTEILE" :"PNR", :"ART", :"ANZ", :"EIN", :"RUECK", :"NACH"

              Plan:

              [Application: Neuling Net 2]
              : [Start transaction]

              [Application: Neuling Net 2]
              IBSPInsertteile: [Prepare] Select F.RDB$COMPUTED_BLR, F.RDB$DEFAULT_VALUE, R.RDB$FIELD_NAME from RDB$RELATION_FIELDS R, RDB$FIELDS F where R.RDB$RELATION_NAME = :RELATION and R.RDB$FIELD_SOURCE = F.RDB$FIELD_NAME and ((not F.RDB$COMPUTED_BLR is NULL) or (not F.RDB$DEFAULT_VALUE is NULL))

              Plan: PLAN JOIN (R INDEX (RDB$INDEX_4),F INDEX (RDB$INDEX_2))

              [Application: Neuling Net 2]
              : [Commit (Hard commit)]

              [Application: Neuling Net 2]
              IBSPInsertteile: [Execute] Execute Procedure "INSERTTEILE" :"PNR", :"ART", :"ANZ", :"EIN", :"RUECK", :"NACH"

              PNR = 37000
              ART = 5050
              ANZ = 1
              EIN = 0
              RUECK = 0
              NACH = 0

              [Application: Neuling Net 2]
              IBTR: [Commit retaining (Soft commit)]

              Ist das richtig ? Oder wird wegen eines Fehlers in der Programmierung Funktionen mehrfach ausgeführt ?

              Gruß Günte

              Comment


              • #8
                Hallo,

                bei diesem Aufrufprotokoll ist nichts auffälliges zu sehen, so dass ich zunächst innerhalb der Stored Procedure nach dem langsamen Teil suchen würde. Wie schnell laufen diese Aufrufe ab, wenn sie von Hand aus Interactive SQL heraus abgesetzt werden? Ist das eventuell eine WAIT-Transaktion, die auf das Ende einer anderen Transaktion warten muss

                Comment


                • #9
                  Hallo,<br>
                  Über ISQL gleiches Tempo. Jetzt gehts es, nachdem ich ein Backup und Restore durchgeführt habe !
                  <br>
                  Gibt bei Interbase evtl. Fehler in den Indextabellen, die dann nicht mehr benutz werden, wenn sie defekt sind ? Kann man das ohne Restore reparieren?

                  Gruß Günte

                  Comment


                  • #10
                    Hallo,

                    der regelmässige Backup-/Restore-Zyklus ist aus verschiedenen Gründen sinnvoll, daher würde ich das so beibehalten

                    Comment

                    Working...
                    X