Announcement

Collapse
No announcement yet.

Interbase-DB 5 und Trigger erstellen

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

  • Interbase-DB 5 und Trigger erstellen

    Hallo zusammen,

    Habe mit Unterstützung aus dem Forum erfolgreich eine DB von ORACLE nach Interbase portiert. Dafür meinen Dank an alle.
    Nun habe ich noch Probleme unter Interbase bezüglich Trigger-Erstellung:
    Und zwar soll ein Trigger die Tabelle "PGS_V_NEODAT_ZURUECK" immer dann mit allen Daten aus Tabelle "PGS_NEODAT" versorgen, die in dieser Tabelle in der Spalte "Status" den Wert 'Z' haben, wenn in der Tabelle "PGS_NEODAT" eine Änderung vorgenommen wurde. Vorher soll der gesamte Tabelleninhalt der Tabelle "PGS_V_NEODAT_ZURUECK" gelöscht werden.
    Beide Tabellen haben identische Spalten (ca 110, z.B. KLnr, patnr, exportdat, status ...ect).

    Für jede Hilfe schon mal meinen herzlichen Dank

    Gruß
    Paul

  • #2
    Hallo Paul,

    <pre>
    create trigger PGS_NEODAT_AU10 fro table PGS_NEODAT
    after update
    as
    begin
    if ((old.KLnr <> new.KLnr) or
    (old.patnr <> new.patnr) or
    ...
    (old.status <> new.status)) then
    begin
    Delete PGS_V_NEODAT_ZURUECK;
    insert into PGS_V_NEODAT_ZURUECK
    (klnr, patnr, ... status)
    select klnr, patnr, ... status from PGS_NEODAT
    where status = 'Z';
    end
    end
    </pre>

    Es könnte passieren das Du Probleme mit der Größe des Statements bekommt's. Das Limit liegt bei 32KB.

    Tschüß

    Torste

    Comment


    • #3
      Hallo Paul,

      in mein beispiel hat sich ein kleiner Fehler eingeschlichen.

      so ist es besser:

      <pre>
      create trigger PGS_NEODAT_AU10 fro table PGS_NEODAT
      after update
      as
      begin
      if ((old.KLnr <> new.KLnr) or
      (old.patnr <> new.patnr) or
      ...
      (old.status <> new.status)) then
      begin
      Delete from PGS_V_NEODAT_ZURUECK;
      insert into PGS_V_NEODAT_ZURUECK
      (klnr, patnr, ... status)
      select klnr, patnr, ... status from PGS_NEODAT
      where status = 'Z';
      end
      end
      </pre>

      Tschüß

      Torste

      Comment


      • #4
        Hallo Thorsten,

        vielen Dank für das Beispiel.
        Habe Deine Vorgaben aufgenommen und um die fehlenden Tabellenspalten ergänzt.
        Der Trigger sieht nun so aus:
        CREATE TRIGGER pgs_v_neodat_zurueck_up FOR pgs_neodat
        AFTER UPDATE
        AS
        BEGIN
        IF ((OLD.KLNR <> NEW.KLNR) OR
        (OLD.PATNR <> NEW.PATNR) OR
        ........
        (OLD.ERFJAHR <> NEW.ERFJAHR) OR
        (OLD.PRUEFFLAG <> NEW.PRUEFFLAG)) THEN
        BEGIN
        DELETE FROM pgs_v_neodat_zurueck;
        INSERT INTO pgs_v_neodat_zurueck
        (KLNR, PATNR, ........ ERFJAHR, PRUEFFLAG)
        SELECT KLNR, PATNR, ......... ERFJAHR, PRUEFFLAG
        FROM pgs_neodat
        WHERE status = 'Z';
        END
        END;

        Der Trigger wurde ohne Fehlermeldung generiert.
        Mit "ALTER TRIGGER pgs_v_neodat_zurueck_up ACTIVE" habe ich den Trigger nocht aktiviert und nun werkelt es.
        Für Deine Unterstützung ganz herzlichen Dank.

        Alle beste Grüße
        Paul

        PS: Falls ich bei den weiteren Triggern noch Hilfe benötige, würde ich mich wieder an Dich wenden. Geht das i. O.

        Comment


        • #5
          Hallo Paul,

          Du kannst mich gern fragen. Wie groß ist den das Statement geworden (einfach mal in eine Textdatei speichern und dann die Größe auslesen)?

          Tschüß

          Torste

          Comment


          • #6
            Hallo,<br><br>
            ich möchte nur eines zu Torsten's Beispiel beisteuern. Wenn ein Feld NULL sein kann, dann schlägt z.B.
            <pre>
            (old.KLnr <> new.KLnr)
            </pre>
            fehl, d.h. um verläßlich abzuprüfen, ob sich in einer Spalte etwas geändert hat, benötigt man z.B.
            <pre>
            (((old.KLnr IS NULL) AND (new.KLnr IS NOT NULL)) or (old.KLnr IS NOT NULL) AND (new.KLnr IS NULL)) or (old.KLnr <> new.KLnr))
            </pre>
            Schöne Grüße,<br>
            Thoma
            Thomas Steinmaurer

            Firebird Foundation Committee Member
            Upscene Productions - Database Tools for Developers
            Mein Blog

            Comment


            • #7
              Hallo Thomas,

              korrekter Einwand.

              Tschau

              Torste

              Comment


              • #8
                Hallo Thomas,

                vielen Dank für die zusätzlichen Info's, die ich allerdings noch einbauen muß.
                Leider hat sich noch ein weiteres Problem mit "doppelten Datensätzen" eingeschlichen. Unter ORACLE waren es seinerzeit "virtuell doppelte" Sätze. Jetzt sind sie unter Interbase aber tatsächlich doppelt. Vermutlich hat die Importroutine ein Problem.
                Eine Beschreibung des Problems habe ich in der Anwort an Torsten Grundke beschrieben.
                Vielleicht kannst Du ja auch mal einen Blick darauf werfen.

                Gruß
                Pau

                Comment


                • #9
                  Hallo Torsten,

                  vielen Dank für Deine weitere Unterstützungszusage. Die Ergänzung von Thomas Steinmaurer muß ich noch einbauen.
                  Das Statement hat jetzt eine Größe von 7 KB. Mit der letzten Ergänzung sollte die 15-KB-Schallmauer wohl noch nicht
                  erreicht werden.

                  Nun hat sich leider noch ein neues / altes Problem wieder eingestellt.
                  Es werden nun über die Importschnittstelle sämtliche Sätze importiert. Die Importprozedur hat leider 550 Zeilen und
                  würde vermutlich wegen der Länge den hier zur Verfügung stehenden Textrahmen sprengen. Ich würde aber die komplette
                  Routine bei Bedarf auch als Textdatei verschicken - falls ich Dir / Euch das zumuten darf - und wenn wir nicht über
                  diese Beschreibung und Auszüge aus der Routine weiterkommen.
                  Die Importroutine überprüft drei Werte in der DB mit den zu importierenden Rohdaten. An der entsprechenden Stelle im
                  Source sieht das wie folgt aus:
                  .......
                  // und jetzt das Array umwandeln...

                  Balken1.Max := AnzImp;

                  with PGSDatenModul do
                  begin
                  i := 1;
                  MaxGebDat := 0;
                  MaxEntlassDat := 0;
                  Importieren := True; // Wird nur "false" wenn Datensatz existiert und nicht überschrieben werden soll.

                  while Length(ImpArray[i]) > 0 do
                  begin
                  { Es wird geprüft, ob Datensatz schon existiert - wenn ja:
                  Prüfen, ob Importsatz neuer als gespeicherter ist - wenn ja:
                  überschreiben. }

                  with NeoTab do
                  begin
                  SuchKl := Pad(Copy(ImpArray[i], 1, 3), 3, ' ');
                  SuchPat := Pad(Copy(ImpArray[i], 5, 10), 10, ' ');

                  // SuchKl := Trim(Copy(ImpArray[i], 1, 3));
                  // SuchPat := Trim(Copy(ImpArray[i], 5, 10));

                  // ShowMessage(Copy(ImpArray[i], 1, 3) + CRLF + Copy(ImpArray[i], 5, 10));
                  // NeoSuche := Lookup('KlNr;PatNr', VarArrayOf([Copy(ImpArray[i], 1, 3), Copy(ImpArray[i], 5, 10)]), 'KlNr;PatNr');
                  NeoSuche := Lookup('KlNr;PatNr', VarArrayOf([SuchKl,SuchPat]), 'KlNr;PatNr');
                  if VarType(NeoSuche) = varNull then // Datensatz existiert noch nicht -> anlegen!
                  NeoTab.Append

                  else begin // Datensatz existiert, also: ...

                  Locate('KlNr;PatNr', NeoSuche, []);
                  AltesExpDat := NeoTabExportDat.Value;

                  NeuesExpDat := StrToDateTime(Copy(ImpArray[i], 408, 2) + '.' +
                  Copy(ImpArray[i], 411, 2) + '.' +
                  Copy(ImpArray[i], 414, 4) + ' ' +
                  Copy(ImpArray[i], 419, 2) + ':' +
                  Copy(ImpArray[i], 422, 2) + ':' +
                  Copy(ImpArray[i], 425, 2));

                  if NeuesExpDat > AltesExpDat then // ... überschreiben, wenn DIESER Export neuer als der VORIGE ist.
                  begin
                  NeoTab.Edit;
                  NeoTab.ClearFields;
                  end
                  else begin // Nicht importieren, weil Export identisch oder älter!
                  SchreibeError(NeoTabKlNr.Value,
                  NeoTabPatNr.Value,
                  'Nicht Importiert. Datensatz existiert bereits mit gleichem Exportdatum.');
                  if FehlerAnzeigen then
                  begin
                  MessageDlg('Es wurde ein Fehler in der Log-Tabelle dokumentiert. Bitte die Fehlerurs

                  Comment


                  • #10
                    Hallo,

                    ich habe es mir gedacht! Das ganze noch einmal und ohne Routine:

                    Hallo Torsten,

                    vielen Dank für Deine weitere Unterstützungszusage. Die Ergänzung von Thomas Steinmaurer muß ich noch einbauen.
                    Das Statement hat jetzt eine Größe von 7 KB. Mit der letzten Ergänzung sollte die 15-KB-Schallmauer wohl noch nicht
                    erreicht werden.

                    Nun hat sich leider noch ein neues / altes Problem wieder eingestellt.
                    Es werden nun über die Importschnittstelle sämtliche Sätze importiert. Die Importprozedur hat leider 550 Zeilen und
                    würde vermutlich wegen der Länge den hier zur Verfügung stehenden Textrahmen sprengen. Ich würde aber die komplette
                    Routine bei Bedarf auch als Textdatei verschicken - falls ich Dir / Euch das zumuten darf - und wenn wir nicht über
                    diese Beschreibung und Auszüge aus der Routine weiterkommen.
                    Die Importroutine überprüft drei Werte in der DB mit den zu importierenden Rohdaten. An der entsprechenden Stelle im
                    Source sieht das wie folgt aus:
                    ...kommt separat.....
                    Ich hoffe, das wird nicht zu viel und zu unübersichtlich...(sorry)

                    Es geht beim Import im Pronzip um zwei Spalten: "KLNR und PATNR" - die als Charakter definiert
                    wurden und beim Import mit führenden "blanks" befüllt werden:

                    ImpStr(Pad(Strap(Copy(ImpArray[i], 1, 3), '0'), 3, ' '), 'KlNr');

                    ImpStr(Pad(Strap(Copy(ImpArray[i], 5, 10), '0'), 10, ' '), 'PatNr');

                    Wenn ich das ganze nun ohne diese führenden "blanks" durchführe, funktioniert der Import wieder
                    und die "doppelten" Sätze werden über ein Logfile gehändelt.
                    ohne führende "blanks" auffüllen:
                    //ImpStr(Trim(Copy(ImpArray[i], 1, 3)), 'KlNr');
                    //ImpStr(Trim(Copy(ImpArray[i], 5, 10)), 'PatNr');

                    Die "blanks" waren seinerzeit in der ORACLE-DB notwendig, damit die Datensätzte pro "KLNR" in einer
                    Grid nach "PATNR" richtig sortiert (aufsteigend) aufgelistet wurden. "KLNR" und "PATNR" mußten seinerzeit
                    leider von NUM auf CHAR umgestellt werden.
                    Vermutlich weil die ORACLE-DB mit dem NLS_LANGUAGE "GERMAN" installiert, in der "init.ora" aber ohne Angabe (lt. Oracle
                    gilt dann Standard und somit NLS_LANGUAGE "US") initialisiert worden ist, war dieses notwendig (Sortierung innerhalb der
                    "KLNR" nach "PATNR" nur dann richtig, wenn alle Komponenten beispielsweise den deutschen Zeichensatz verwenden (richtig?).

                    Meine Fragen nun:
                    Wie verhält sich das "blank"-Zeichen in der Interbase-DB. Wenn ich komplett auf die führenden "blanks" verzichte,
                    werden die Sätze dann grundsätzlich nicht mehr doppelt eingelesen?
                    Beim ersten Versuch mit den "getrimmten" (in der Routine auskommentiert) Angaben hat die Importroutine die "doppelten"
                    Sätze wieder korrekt herausgefischt. Ist das aber auch dauerhaft so?
                    Meine Unsicherheit deshalb, weil ich seinerzeit die Importroutine schon einmal dahingehend geändert hatte. Nach einer
                    gewissen Zeit stellten sich die Probleme wieder ein - das war allerdings bei der ORACLE-DB und den "virtuell doppelten"
                    Datensätzen.

                    Merkwürdigerweise trat dieses Problem auch bis letzte Woche bei den verschiedenen Tests mit der neue Interbase-DB nicht auf.
                    Obwohl ich mehrfach versucht habe, die gleichen Sätze zu importieren, hat die Routine funktioniert und die "doppelten"
                    herausgefiltert.
                    Kann das denn überhaupt mit dem führenden "blank" zusammenhängen? Die Interbase-DB habe ich ja komplett neu aufgesetzt mit
                    dem Zeichensatz "ISO8859_1". Die Daten von der ORACLE-DB mit "IB DataPump V3.4" transferiert. Umlaute werden beispielsweise
                    in der neuen Interbase-DB auch richtig angezeigt - sowohl über den SQL-Explorer als auch über die Delphi-Anwendung.
                    Die NT-Maschine hat den deutschen Sprachtreiber installiert. Die "BDE" hat als LANGDRIVER "ascii ANSI".
                    Was fehlt noch?
                    Was könnte man noch machen?
                    Muß ggf. die Importroutine geändert werden?
                    Für jede(n) Hilfe/Tip dankbar.

                    Gruß
                    Pau

                    Comment


                    • #11
                      hallo,

                      und hier die Routine (auszugsweise):

                      Die Importroutine überprüft drei Werte in der DB mit den zu importierenden Rohdaten. An der entsprechenden Stelle im
                      Source sieht das wie folgt aus:
                      .......
                      // und jetzt das Array umwandeln...

                      Balken1.Max := AnzImp;

                      with PGSDatenModul do
                      begin
                      i := 1;
                      MaxGebDat := 0;
                      MaxEntlassDat := 0;
                      Importieren := True; // Wird nur "false" wenn Datensatz existiert und nicht überschrieben werden soll.

                      while Length(ImpArray[i]) > 0 do
                      begin
                      { Es wird geprüft, ob Datensatz schon existiert - wenn ja:
                      Prüfen, ob Importsatz neuer als gespeicherter ist - wenn ja:
                      überschreiben. }

                      with NeoTab do
                      begin
                      SuchKl := Pad(Copy(ImpArray[i], 1, 3), 3, ' ');
                      SuchPat := Pad(Copy(ImpArray[i], 5, 10), 10, ' ');

                      // SuchKl := Trim(Copy(ImpArray[i], 1, 3));
                      // SuchPat := Trim(Copy(ImpArray[i], 5, 10));

                      // ShowMessage(Copy(ImpArray[i], 1, 3) + CRLF + Copy(ImpArray[i], 5, 10));
                      // NeoSuche := Lookup('KlNr;PatNr', VarArrayOf([Copy(ImpArray[i], 1, 3), Copy(ImpArray[i], 5, 10)]), 'KlNr;PatNr');
                      NeoSuche := Lookup('KlNr;PatNr', VarArrayOf([SuchKl,SuchPat]), 'KlNr;PatNr');
                      if VarType(NeoSuche) = varNull then // Datensatz existiert noch nicht -> anlegen!
                      NeoTab.Append

                      else begin // Datensatz existiert, also: ...

                      Locate('KlNr;PatNr', NeoSuche, []);
                      AltesExpDat := NeoTabExportDat.Value;

                      NeuesExpDat := StrToDateTime(Copy(ImpArray[i], 408, 2) + '.' +
                      Copy(ImpArray[i], 411, 2) + '.' +
                      Copy(ImpArray[i], 414, 4) + ' ' +
                      Copy(ImpArray[i], 419, 2) + ':' +
                      Copy(ImpArray[i], 422, 2) + ':' +
                      Copy(ImpArray[i], 425, 2));

                      if NeuesExpDat > AltesExpDat then // ... überschreiben, wenn DIESER Export neuer als der VORIGE ist.
                      begin
                      NeoTab.Edit;
                      NeoTab.ClearFields;
                      end
                      else begin // Nicht importieren, weil Export identisch oder älter!
                      SchreibeError(NeoTabKlNr.Value,
                      NeoTabPatNr.Value,
                      'Nicht Importiert. Datensatz existiert bereits mit gleichem Exportdatum.');
                      if FehlerAnzeigen then
                      begin
                      MessageDlg('Es wurde ein Fehler in der Log-Tabelle dokumentiert. Bitte die Fehlerursache überprüfen.', mtWarning, [mbOk], 0);
                      FehlerAnzeigen := False;
                      end;
                      Importieren := False;
                      end;

                      end;
                      Balken1.StepIt;
                      end;
                      .......
                      Ich hoffe, das wird nicht zu viel und zu unübersichtlich...(sorry)
                      ......

                      Gruß
                      Pau

                      Comment


                      • #12
                        Hallo Paul,

                        schick mir mal den vollständigen Quellcode.
                        Email: [email protected]

                        Tschüß

                        Torste

                        Comment

                        Working...
                        X