AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Trigger rekursiv

Ein Thema von stahli · begonnen am 19. Jul 2009 · letzter Beitrag vom 29. Jul 2009
Antwort Antwort
Seite 1 von 2  1 2      
Benutzerbild von stahli
stahli

Registriert seit: 26. Nov 2003
Ort: Halle/Saale
4.336 Beiträge
 
Delphi 11 Alexandria
 
#1

Trigger rekursiv

  Alt 19. Jul 2009, 14:41
Datenbank: FB • Version: 2.1 • Zugriff über: IBX
Hallo alle,

ich nutze jetzt erstmals Trigger und Stored Procedure ... (muss man ja gar keine Angst vor haben und mit IBExpert geht das ja fast wie von alleine).

Jetzt will ich aber nach jeder Änderung in einer Tabelle alle Datensätze neu anpassen. Als Beispiel sei mal gegeben: "MyTable" mit den Feldern ID, A, B, und Pos.
Nach jeder Änderung in MyTable soll der Wert in Pos für alle Datensätze neu berechnet werden.
Dafür habe ich eine stored procedure CalcAllPos, erstellt, die das erledigt.

Nun rufe ich diese procedure in einem Trigger AfterPostUpdateDelete auf, was zu einem rekursiven Aufruf des Triggers und der Prozedur und einem Stacküberlauf führt.

Wie löst man das Problem am besten?

Eine Definition des neues Wertes im Trigger über new.Pos kann ich nicht verwenden, da ALLE Datensätze der Tabelle neu berechnet werden sollen.

Globale Variablen (als Flag) unterstützt FB ja offenbar nicht.
Nun könnte ich vielleicht ein Tabellenfeld dafür einführen oder ich könnte die Pos-Daten in eine eigene Tabelle "MyTablePos" auslagern und über eine ID zur "MyTable" verbinden. Änderungen in "MyTablePos" würden dann nicht noch einmal die Trigger von MyTable auslösen.

Gibt es aber vielleicht einen besseren Weg?


Stahli
  Mit Zitat antworten Zitat
TBx
(Administrator)

Registriert seit: 13. Jul 2005
Ort: Stadthagen
1.875 Beiträge
 
Delphi 12 Athens
 
#2

Re: Trigger rekursiv

  Alt 19. Jul 2009, 15:09
Ich vermute jetzt mal, dass Du über pos die Reihenfolge der Datensätze für eine Auswertung festlegen willst.

Prinzipiell sollte das über mehrere Trigger gelöst werden:[list][*]BeforeInsert: Prüfen, ob ein Wert für pos gesetzt ist
  • ja: dann in allen Datensätzen, die einen pos-Wert >= new.pos haben pos incrementieren
  • nein: den höchsten pos-Wert ermitteln, incrementieren und in new.pos ablegen
[*] beforeUpdate: Prüfen, ob der pos-Wert geändert wurde, wenn ja:[list][*]prüfen, ob new.pos is null[list][*] ja: in allen Datensätzen, die einen Pos-Wert >= old.pos haben, den pos-Wert decrementieren, den nun höchsten pos-Wert ermitteln, incrementieren und als new.pos setzen[*]nein: prüfen, ob old.pos > new.pos[list:af58ac1ec3][*]ja: alle pos-Werte in den Datensätzen, die >new.pos und[list=1]new.pos und[list=1] old.pos haben decrementieren[/list:u:af58ac1ec3]

Ich hoffe, das hilft als Denkanstoss.

Gruß
Thomas Breitkreuz
Gruß Thomas
- Admin DelphiPRAXIS
- Admin Delphi-Treff
- Embarcadero MVP
  Mit Zitat antworten Zitat
Benutzerbild von stahli
stahli

Registriert seit: 26. Nov 2003
Ort: Halle/Saale
4.336 Beiträge
 
Delphi 11 Alexandria
 
#3

Re: Trigger rekursiv

  Alt 19. Jul 2009, 15:24
Es ist etwas komplizierter.
Pos wird in Abhängigkeit von A + B berechnet und ist davon abhängig, wie oft A + B in der Tabelle vorkommen.
Ich kann mich daher nur auf die Tabellendaten nach irgendeiner Änderung beziehen und dabei ist es egal, ob etwas eingefügt, gelöscht oder geändert wurde (es kommt eben nur auf die neuen Daten in der Tabelle an).
Es handelt sich also um berechnete Ergebnisse, die aber alle Datensätze der Tabelle berücksichtigt.

Wenn ich die Procedure selbst starte ist ja alles ok. Nur wenn ich sie aus einen Trigger heraus aufrufe starten wie Änderungen wieder den Trigger etc.

Ich werde wohl die "berechneten Ergebnisse" in eine extra Tabelle auslagern. Das scheint mir am sinnvollsten und ich versuche das gerade mal umzusetzen ...
  Mit Zitat antworten Zitat
TBx
(Administrator)

Registriert seit: 13. Jul 2005
Ort: Stadthagen
1.875 Beiträge
 
Delphi 12 Athens
 
#4

Re: Trigger rekursiv

  Alt 19. Jul 2009, 15:36
das ist dann eigentlich der klassische Anwendungsfall für Views. Die Daten jeweilig bei Datensatzoperationen neu zu schreiben ist überflüssig, wenn diese jederzeit berechnet werden können.

Wozu brauchst Du denn die Werte?
Thomas Breitkreuz
Gruß Thomas
- Admin DelphiPRAXIS
- Admin Delphi-Treff
- Embarcadero MVP
  Mit Zitat antworten Zitat
Benutzerbild von stahli
stahli

Registriert seit: 26. Nov 2003
Ort: Halle/Saale
4.336 Beiträge
 
Delphi 11 Alexandria
 
#5

Re: Trigger rekursiv

  Alt 19. Jul 2009, 15:51
Es gibt eine Gruppen mit einer ID.
Innerhalb einer Gruppe gibt es Einträge von einem bestimmten Typ (Text als varchar).
Jeder Eintrag hat ein Feld Pos.
Gibt es innerhalb einer Gruppe mehrere Einträge des gleichen Typs sollen diese nummeriert werden:

Zitat:
GrId, Id, Typ, Pos
1, 1, hd, 1
1, 2, hd, 2
1, 3, dd, null
1, 4, d, null
2, 5, d, 1
2, 6, d, 2
2, 7, e, null
2, 8, d, 3
Die Numerierung soll nur erfolgen, wenn mehr als ein Eintrag pro Typ in einer Gruppe existiert.
Die Änderungen in der Tabelle sind recht selten, die Abfragen rel. häufig. Daher will ich die Ergebnisse fest in der Datenbank ablegen.
Da jede Änderung berücksichtigt werden soll, will ich die Neuberechnung gern über Trigger anstoßen...
  Mit Zitat antworten Zitat
TBx
(Administrator)

Registriert seit: 13. Jul 2005
Ort: Stadthagen
1.875 Beiträge
 
Delphi 12 Athens
 
#6

Re: Trigger rekursiv

  Alt 19. Jul 2009, 16:01
Wodurch ergibt sich die Nummerierung in den Gruppen? Aus der Datensatzanlage? Soll diese Nummerierung editierbar sein?
Thomas Breitkreuz
Gruß Thomas
- Admin DelphiPRAXIS
- Admin Delphi-Treff
- Embarcadero MVP
  Mit Zitat antworten Zitat
Benutzerbild von stahli
stahli

Registriert seit: 26. Nov 2003
Ort: Halle/Saale
4.336 Beiträge
 
Delphi 11 Alexandria
 
#7

Re: Trigger rekursiv

  Alt 19. Jul 2009, 16:11
Die Nummerierung ergibt sich aus der bisherigen Nummerierung und der ID.
Neue Einträge werden entsprechend angefügt.

1.md
2.md
wird hier ein Eintrag "md" angefügt erhält er Nr. 3.

1.wd
2.wd
3.wd
Wird der 2. Eintrag gelöscht der der 3. Eintrag zu Nr. 2.

1.d
2.d
Wird der 2. Eintrag gelöscht entfällt die Nummerierung für der 1. Eintrag (dann nur noch "d", da er dann der einzige Eintrag ist).


Für eine Zuweisung der Nummer muss halt immer untersucht werden, wieviele gleiche Typen es in einer Gruppe gibt.

Editierbar soll das Feld nicht sein.
  Mit Zitat antworten Zitat
mkinzler
(Moderator)

Registriert seit: 9. Dez 2005
Ort: Heilbronn
39.851 Beiträge
 
Delphi 11 Alexandria
 
#8

Re: Trigger rekursiv

  Alt 19. Jul 2009, 18:21
Du könntest das Pos-Feld auch als virtuelles Feld in der Abfrage (SP) liefern
Markus Kinzler
  Mit Zitat antworten Zitat
Blup

Registriert seit: 7. Aug 2008
Ort: Brandenburg
1.429 Beiträge
 
Delphi 10.4 Sydney
 
#9

Re: Trigger rekursiv

  Alt 20. Jul 2009, 07:15
Bei so einer Datenstruktur gibt es Lock-Konflikte, wenn mehr als eine Transaktion innerhalb einer Gruppe in die Tabelle schreibt.
Bei vielen Datensätzen kann das recht langsam werden, da jede einzelne Änderung den Trigger auslöst. Im Update-Trigger muss geprüft werden, dass sich wirklich ein Feld abgesehen von POS ändert.

Das Feld POS würde ich in eine zweite Tabelle auslagern (nur ID und POS), damit entfallen automatisch rekursiven Triggeraufrufe.
  Mit Zitat antworten Zitat
Benutzerbild von stahli
stahli

Registriert seit: 26. Nov 2003
Ort: Halle/Saale
4.336 Beiträge
 
Delphi 11 Alexandria
 
#10

Re: Trigger rekursiv

  Alt 20. Jul 2009, 11:14
Moin,

mit dem Auslagern in eine eigene extra Tabelle habe ich es jetzt gelöst.
Allerdings wäre es mir angenehmer gewesen (weniger aufwändig), wenn ein Trigger sich einfach nicht selbt auslöst oder man dies einfach über ein globales Flag abfangen könnte.

Danke
Stahli
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 04:45 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz