Willkommen bei Entwickler-Forum.
Ergebnis 1 bis 7 von 7
  1. #1
    Aufsteiger
    Registriert seit
    23.03.2007
    Beiträge
    60

    Standard [Gelöst] trigger after insert gelingt mir nicht

    Guten Tag,

    ich versuche gerade einige Funktionen auf den Server auszulagern.
    Dazu möchte ich Trigger und stored procs benutzen um Netzwerk und Client zu entlasten.

    Nach dem Eintragen einer Vorgabe sollen daraus Detaildatensätze erzeugt werden.
    Diese Detaildatensätze sollen auf dem Server erzeugt werden.

    Tabelle 1:
    ID erzeugt durch Generator, diverse, Vorgabe von, bis, Wochenplan

    Tabelle 2:
    ID erzeugt durch Generator, diverse, Je Tag einen eindeutigen Verweis auf den Tagesplan

    Hier meine Trigger. Dieser scheint korrekt, erzeugt aber keine eindeutigen Werte (Fehler -811)
    Ich vermute, das Abfragen des Generators klappt nicht?

    Dies ist der Trigger für die ID
    Code:
    CREATE TRIGGER SET_TAGESVORGABENID FOR TAGESVORGABEN ACTIVE
    BEFORE INSERT POSITION 0
    as
    begin
      if (new.ID is null) then new.ID = gen_id(gen_TAGESVORGABEN, 1);
      if (new.ID = '0') then new.ID = gen_id(gen_TAGESVORGABEN, 1);
    end
    Diese ID wird mit Gen_ID(gen_tagesvorgaben,1) abgefragt und incrementiert.

    Code:
    CREATE OR ALTER trigger arbeitsplaene_ai0 for arbeitsplaene
    active after insert position 0
    AS
      DECLARE VARIABLE aktMandant integer;
      DECLARE VARIABLE aktFirma integer;
      DECLARE VARIABLE aktFiliale integer;
      DECLARE VARIABLE aktAbteilung integer;
      DECLARE VARIABLE aktGruppe integer;
      DECLARE VARIABLE aktMitarbeiter integer;
      DECLARE VARIABLE laufdatum Date;
      DECLARE VARIABLE TP integer;
      DECLARE VARIABLE akttimestamp timestamp;
    begin
      laufdatum = new.startdatum;
      TP = 0;
      akttimestamp = current_timestamp;
      while (laufdatum < new.enddatum) do
      begin
        if (new.wochenplan is not NULL) then
        begin
          if (extract(weekday from laufdatum) = 0) then
            select SONNTAG from WOCHENPLAENE as W where W.id = ID into :TP;
          else
          if (extract(weekday from laufdatum) = 1) then
            select MONTAG from WOCHENPLAENE as W where W.id = ID into :TP;
          else
          if (extract(weekday from laufdatum) = 2) then
            select DIENSTAG from WOCHENPLAENE as W where W.id = ID into :TP;
          else
          if (extract(weekday from laufdatum) = 3) then
            select MITTWOCH from WOCHENPLAENE as W where W.id = ID into :TP;
          else
          if (extract(weekday from laufdatum) = 4) then
            select DONNERSTAG from WOCHENPLAENE as W where W.id = ID into :TP;
          else
          if (extract(weekday from laufdatum) = 5) then
            select FREITAG from WOCHENPLAENE as W where W.id = ID into :TP;
          else
          if (extract(weekday from laufdatum) = 6) then
            select SAMSTAG from WOCHENPLAENE as W where W.id = ID into :TP;
          if (TP <> 0) then
          begin
            aktMandant = new.Mandant;
            aktFirma = new.Firma;
            aktFiliale = new.Filiale;
            aktAbteilung = new.Abteilung;
            aktGruppe = new.Gruppe;
            aktMitarbeiter = new.Mitarbeiter;
            update or insert INTO TAGESVORGABEN (ID, Mandant, Firma, Filiale, Abteilung, Gruppe, Mitarbeiter, Datum, Tagesplanorig, Tagesplanman, geaendert_am)
            values (Gen_ID(gen_tagesvorgaben,1), :aktMandant, :aktFirma, :aktFiliale, :aktAbteilung, :aktGruppe, :aktMITARBEITER, :laufdatum, :TP, :TP, :akttimestamp);
          end
          TP = 0;
        end
        laufdatum = laufdatum + 1;
      end
    end
    Ich hoffe Ihr könnt mir dabei helfen.

    Gruß

    Peter
    Geändert von petermaennchen (03.11.2015 um 09:07 Uhr)

  2. #2
    Aufsteiger
    Registriert seit
    23.03.2007
    Beiträge
    60

    Standard

    Hier noch die Tabellen zum Post oben:

    Code:
    CREATE TABLE ARBEITSPLAENE
    (
      ID Integer NOT NULL,
      MANDANT Integer NOT NULL,
      FIRMA Integer NOT NULL,
      FILIALE Integer,
      ABTEILUNG Integer,
      GRUPPE Integer,
      MITARBEITER Integer,
      STARTDATUM Date,
      ENDDATUM Date,
      WOCHENPLAN Integer,
      SCHICHTPLAN Integer,
      ROLLPLAN Integer,
      GEAENDERT_AM Timestamp,
      GEAENDERT_VON Integer,
      PRIMARY KEY (ID)
    );
    GRANT DELETE, INSERT, REFERENCES, SELECT, UPDATE
     ON ARBEITSPLAENE TO  SYSDBA WITH GRANT OPTION;

    Code:
    REATE TABLE TAGESVORGABEN
    (
      ID Integer NOT NULL,
      MANDANT Integer NOT NULL,
      FIRMA Integer NOT NULL,
      FILIALE Integer,
      ABTEILUNG Integer,
      GRUPPE Integer,
      MITARBEITER Integer NOT NULL,
      DATUM Date,
      TAGESPLANORIG Integer,
      TAGESPLANMAN Integer,
      KERNZEITFEHLER Smallint,
      FEHLERSTATUS Varchar(20),
      BEMERKUNG Varchar(250),
      GEAENDERT_AM Timestamp,
      GEAENDERT_VON Integer,
      PRIMARY KEY (ID)
    );
    GRANT DELETE, INSERT, REFERENCES, SELECT, UPDATE
     ON TAGESVORGABEN TO  SYSDBA WITH GRANT OPTION;

  3. #3
    Aufsteiger
    Registriert seit
    23.03.2007
    Beiträge
    60

    Standard

    Man soll auch mal Pause machen!

    Blind wie ich bin habe ich im Statement des Triggers die ID'S falsch angegeben

    Code:
    select SONNTAG from WOCHENPLAENE as W where W.id = ID into :TP;
    muß heissen

    Code:
    select SONNTAG from WOCHENPLAENE as W where W.id = new.Wochenplan into :TP;
    Das klappt.

    Falls Ihr noch generelle Anmerkungen hättet wie ich was eleganter lösen könnte freue ich mich drüber.
    Der Einstieg dauert doch ein wenig.

    Gruß

    Peter

  4. #4
    Stammgast
    Registriert seit
    24.10.2011
    Beiträge
    1.199

    Standard

    Also die Datumswurstelei ist in FB leider etwas mühselig, weil die Datumsfunktionen etwas mager sind.

    Aber das kann man umgehen indem man eine Hilfstabelle für die Wochentage anlegt, die die ID von "extract(weekday.." mit dem Textwert des Wochentages hält.
    Damit wird aus Deinem ganzen If then ein einziges Select.
    Diese Wochentagstabelle kannst Du in dem ganzen Projekt wahrscheinlich eh gut gebrauchen und überall für Umrechnungen, Ein- und Ausgaben verwenden, die mit Wochentagen oder deren Nummern arbeiten.

    Dann zur Whileschleife, die sollte auch durch ein Select ersetzbar sein und dann ist Dein ganzer Triggerbody nur ein
    Insert ... into
    Select .. from Vorgaben (und ggF. weitere Hilfstabellen, auch die Wochentagstabelle)
    where ..
    Gruß, defo

  5. #5
    Aufsteiger
    Registriert seit
    23.03.2007
    Beiträge
    60

    Standard

    Hallo Defo,

    vielen Dank für deine Anmerkungen.
    Das mit dem Select statt while muß ich noch mal überdenken. Wird das schneller?
    Man könnte ja alle Montage etc. über den Zeitraum holen und in einem Rutsch eintragen

    Die Wochentagsbezeichnung benötige ich nur auf dem Client. Das hat mein Compiler incusive:

    Code:
    FormatSettings.LongDayNames[DayOfWeek(date)]
    In der Tabelle Wochentage steht nicht der Name des Wochentages sondern ein Verweis auf den Tagesplan (die ID).
    Die Spalte hat den Namen des Wochentages damit ich nichts verwechsle (je nach Land)

    Gruß

    Peter

  6. #6
    Stammgast
    Registriert seit
    24.10.2011
    Beiträge
    1.199

    Standard

    Zitat Zitat von petermaennchen Beitrag anzeigen
    Das mit dem Select statt while muß ich noch mal überdenken. Wird das schneller?
    Man könnte ja alle Montage etc. über den Zeitraum holen und in einem Rutsch eintragen
    Meine Prognose ist "ja", wenn Du bereits je Wochentag mit einer Teiloptimierung liebäugelst, dann mach gleich alles.

    Zitat Zitat von petermaennchen Beitrag anzeigen
    Die Wochentagsbezeichnung benötige ich nur auf dem Client. Das hat mein Compiler incusive:
    Wieso gönnst Du es Deiner DB nicht genauso schlau zu sein, wie Deinem Compiler?

    Zitat Zitat von petermaennchen Beitrag anzeigen
    In der Tabelle Wochentage steht nicht der Name des Wochentages sondern ein Verweis auf den Tagesplan (die ID).
    Die Spalte hat den Namen des Wochentages damit ich nichts verwechsle (je nach Land)
    Ernsthaft?! Montag bis Sonntag als Spalten und dann noch mal auf Englisch, Französisch usw.?
    Sorry, entweder ich hab's falsch verstanden oder es wäre eine Fehlkonstruktion.

    Mal so eine grundsätzliche Überlegung
    Was gibt es da zu verwechseln? Meine Empfehlung eingangs, eine Minitabelle mit Wochentagen zu erschaffen und dafür dieses .. If then Konstrukt x7 einfürallemal los zu sein, die geht doch nicht nur um Technik und oder Performance. Ob Tabelle oder Funktion, damit schmilzt es auf max. eine Zeile zusammen und es gibt nichts mehr zu verwechseln.
    Und wenn sowas serverseitig bereitgestellt wird, gibt es auch nie Probleme im Client. Dort wendet man einfach das gleiche Prinzip an und muss gar nicht darüber nachdenken, ob in Amerika die Wochentage einen anderen Offset haben (bspw).
    Gruß, defo

  7. #7
    Aufsteiger
    Registriert seit
    23.03.2007
    Beiträge
    60

    Standard

    Zitat Zitat von defo Beitrag anzeigen
    Meine Prognose ist "ja", wenn Du bereits je Wochentag mit einer Teiloptimierung liebäugelst, dann mach gleich alles.


    Wieso gönnst Du es Deiner DB nicht genauso schlau zu sein, wie Deinem Compiler?


    Ernsthaft?! Montag bis Sonntag als Spalten und dann noch mal auf Englisch, Französisch usw.?
    Sorry, entweder ich hab's falsch verstanden oder es wäre eine Fehlkonstruktion.

    Mal so eine grundsätzliche Überlegung
    Was gibt es da zu verwechseln? Meine Empfehlung eingangs, eine Minitabelle mit Wochentagen zu erschaffen und dafür dieses .. If then Konstrukt x7 einfürallemal los zu sein, die geht doch nicht nur um Technik und oder Performance. Ob Tabelle oder Funktion, damit schmilzt es auf max. eine Zeile zusammen und es gibt nichts mehr zu verwechseln.
    Und wenn sowas serverseitig bereitgestellt wird, gibt es auch nie Probleme im Client. Dort wendet man einfach das gleiche Prinzip an und muss gar nicht darüber nachdenken, ob in Amerika die Wochentage einen anderen Offset haben (bspw).
    Da hab ich mich wohl falsch ausgedrückt:

    In den Spalten Montag - Sonntag steht die ID eines zugehörigen Tagesplanes. Dieser wiederum besteht aus vielen Details.
    Ich hätte die Spalten auch Eins, Zwei oder so nennen können, aber der Sinn erschließt sich mir nicht.

    Die Bezeichnung des Wochentages wird aus dem Betriebssystem zurück geliefert (Landeseinstellungen) und hat meiner Meinung nach nichts in der DB verloren.

    So, nun vielleicht noch was zum Algorithmus:
    Ein Wochenplan basiert auf der Annahme, dass über einen längeren Zeitraum jeweils am Montag Plan x gilt, am Dienstag vielleicht auch (vielleicht aber auch nicht) und dieses für den genannten Zeitraum initialisiert wird.
    Diese Grundlage steht halt im Wochenplan, gilt für den einen das ganze Jahr, für den anderen nur drei Monate, für den dritten gar nicht.

    Ich hoffe jetzt wird das klarer. Ich glaube auch nicht, dass das ohne while schneller läuft, es müssten ja immer noch die Wochentage aus dem Datum extrahiert werden. Das ist meiner Meinung nach auch ein serieller Durchlauf.

    Ich habe jetzt auch den Teil mit dem Rollierenden System (also nicht mehr Woche als Container sondern ein beliebiger Zeitraum) fertig und es läuft.

    Gruß an alle

    Peter

 

 

Lesezeichen

Berechtigungen

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