AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Datenbanken Trigger oder Events der DB-Komponenten zum Updaten von Fremdtabelle
Thema durchsuchen
Ansicht
Themen-Optionen

Trigger oder Events der DB-Komponenten zum Updaten von Fremdtabelle

Ein Thema von BlueStarHH · begonnen am 1. Jan 2018 · letzter Beitrag vom 2. Jan 2018
Antwort Antwort
Seite 1 von 2  1 2      
BlueStarHH

Registriert seit: 28. Mär 2005
Ort: Hamburg
849 Beiträge
 
Delphi 11 Alexandria
 
#1

Trigger oder Events der DB-Komponenten zum Updaten von Fremdtabelle

  Alt 1. Jan 2018, 16:50
Datenbank: Firebird • Version: 2.5 • Zugriff über: IBDAC
Wir stellen in 2 Niederlassungen Rechnungen aus.
In der ersten Niederlassung soll beim Einfügen/Löschen/Ändern einer Rechnungsposition in einer Lager-Tabelle der Bestand des Artikels aktualisiert werden.
In der zweiten Niederlassung ist dies nicht nötig. D.h. die Lager-Tabelle wird dort nicht benutzt.

Dazu fallen mir zwei Lösungen ein:
a) Die Rechnungspositionen-Tabelle hat mehrere Trigger (AfterInsert, AfterDelete, AfterUpdate) die, die Lager-Tabell aktualsieren. In jedem Trigger wird geprüft, ob die Lager Lager-Tabelle geändert werden soll oder nicht. Dazu wird ein Flag in einer Einstellungs-Tabelle geprüft. Das ist in der einen Niederlassung gesetzt und in der anderen Niederlassung nicht. Nachteil: In der Niederlassung, wo die Lager-Tabelle nicht genutzt werden soll, werden die Trigger ständig aufgerufen und das Flag per select abgefragt. Das bremst die DB ja aus, was nicht sein muss.

b) Statt der Trigger verwenden ich die OnAfterInsert, OnAfterDelete, OnAfterPost Events der Datenbank-Komponenten direkt im Programm-Code. Vorteil: Ich muss das Flag nicht ständig "aufwändig" mit einem select abfragen sonder kann es die ganze Programmlaufzeit in einem Boolean vorhalten. Auch können hier weitere Dinge berücksitigt werden, auf die es in den Triggern keinen Zugriff gibt (z.B. eingeloggte User). Nachteil: Wenn diese Events nicht ausgelöst werden (weil es z.B. Updates per SQL, an den Komponenten vorbei, gibt) wird die Lager-Tabelle nicht aktualisiert. Darauf muss man dann immer achten.

Welche Lösung würdet ihr nehmen und warum? Gibt es evtl. noch eine weitere Möglichkeit? Habe ich weitere Vor-/Nachteile der beiden Lösungen übersehen?

Geändert von BlueStarHH ( 1. Jan 2018 um 16:53 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.453 Beiträge
 
Delphi 12 Athens
 
#2

AW: Trigger oder Events der DB-Komponenten zum Updaten von Fremdtabelle

  Alt 1. Jan 2018, 16:54
Sind das zwei separate Datenbanken?
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
BlueStarHH

Registriert seit: 28. Mär 2005
Ort: Hamburg
849 Beiträge
 
Delphi 11 Alexandria
 
#3

AW: Trigger oder Events der DB-Komponenten zum Updaten von Fremdtabelle

  Alt 1. Jan 2018, 17:21
Sind das zwei separate Datenbanken?
Ja.
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.453 Beiträge
 
Delphi 12 Athens
 
#4

AW: Trigger oder Events der DB-Komponenten zum Updaten von Fremdtabelle

  Alt 1. Jan 2018, 17:26
Dann deaktiviere doch den Trigger in der Datenbank, in der er nicht benötigt wird.
How to deactivate triggers?
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
BlueStarHH

Registriert seit: 28. Mär 2005
Ort: Hamburg
849 Beiträge
 
Delphi 11 Alexandria
 
#5

AW: Trigger oder Events der DB-Komponenten zum Updaten von Fremdtabelle

  Alt 1. Jan 2018, 17:43
Dann deaktiviere doch den Trigger in der Datenbank, in der er nicht benötigt wird.
How to deactivate triggers?
Danke, auf die einfachsten Ideen kommt man manchmal nicht.

Doch wie würde das ganze nun aussehen, wenn wir die Software auch in einer dritten Niederlassung verwenden würden und dort die Lager-Tabelle nur für einige ausgewählte Artikel gepflegt werden soll. Trigger oder Komponenten-Events? Bei jeder Trigger-Ausführung muss ich dann per select prüfen, ob für diesen Artikel die Lager-Tabelle gepeflt werden soll. Das in einem Komponenten-Event zu machen erscheint mir schneller. Da ich dort zumindest beim Einfügen eines Artikels schon die Info habe, ob dieser in der Lager-Tabelle gepflegt werden soll. Die Trigger-Lösung fühlt sich aber dennoch irgendwie "richtiger" an.
  Mit Zitat antworten Zitat
Delphi.Narium

Registriert seit: 27. Nov 2017
2.490 Beiträge
 
Delphi 7 Professional
 
#6

AW: Trigger oder Events der DB-Komponenten zum Updaten von Fremdtabelle

  Alt 1. Jan 2018, 18:35
Triggerlösung, da nur von der Datenbank abhängig, egal wie die Daten in die Datenbank kommen, das funktioniert dann immer.

Ansonsten muss jeder Weg, der Daten in die Datenbank bringt, die passende Geschäftslogik selbst mitbringen.

D.h.: Ggfls. redundante Implementierung identischer Logik. Das ist fehleranfällig und hat meist einen sehr hohen Pflegebedarf.

Jede Änderung der Logik muss dann an x Stellen mitgepflegt werden.

Ist je Datenbank oder je Niederlassung eine etwas andere Geschäftslogik erforderlich, wird die auch nur einmal je Datenbank in deren Triggern gepflegt.

In welchen Mengen werden die Daten eingeflegt? Muss die Select-Abfrage in "Massen" ausgeführt werden oder ab und an mal, wenn gerade jemand was an den Daten ändert. Dann sind ein paar Millisekunden für eine zusätzliche Abfrage eher vernachlässigbar.
Werden die Rechnungen einzeln, bei Bedarf erstellt oder eher zu "ein paar Millionen" im Batch?

Ist nur ein Schalter zu prüfen, dann hat die passende Tabelle halt eben nur einen Datensatz mit einer Spalte und dem entsprechenden Wert. Das ist dann so schnell, wie das oracletypische select sysdate from dual; .

Je nach Datenbank kann man sich das dann noch in eine Funktion packen und im Trigger in der Form
SQL-Code:
if UseLager then begin
-- mach was mit den Daten
end
nutzen.

Bei Oracle kann man in Packages im Initialisierungsteil (http://oracle-apex.blog/?p=45) Werte in Variabeln einlesen. Die behalten dann Gültigkeit, bis man die Datenbank runterfährt oder das Package neu lädt. Wenn man nun in 'nem Trigger auf diese Variabeln des Packages zugreift, so hat man da keine Select-Laufzeit-Probleme. Das ist genauso schnell, wie der Zugriff auf irgendeine beliebige Variabel in 'nem beliebigen Programm. Keine Ahnung, ob man das auf andere Datenbanken übertragen kann, aber als Denkansatz für die Lösungssuche eventuell brauchbar.
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.453 Beiträge
 
Delphi 12 Athens
 
#7

AW: Trigger oder Events der DB-Komponenten zum Updaten von Fremdtabelle

  Alt 1. Jan 2018, 18:43
Bei jeder Trigger-Ausführung muss ich dann per select prüfen, ob für diesen Artikel die Lager-Tabelle gepeflt werden soll.
Könntest du mal den Trigger-Code zeigen, wie er dann aussehen würde?

Das in einem Komponenten-Event zu machen erscheint mir schneller.
Das ist nicht zwingend der Fall, da dort ja noch der Traffic Client/Server hinzukommt. Hat man nur wenige zu pflegende Artikel fällt das nicht ins Gewicht, bei vielen eventuell schon. Im letzteren Fall ist auch der Verlust durch die überflüssigen Trigger zu vernachlässigen.
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.063 Beiträge
 
Delphi 12 Athens
 
#8

AW: Trigger oder Events der DB-Komponenten zum Updaten von Fremdtabelle

  Alt 1. Jan 2018, 20:44
Zitat:
Das bremst die DB ja aus, was nicht sein muss.
On irgendjemandem diese Nanosekunde auffällt?
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PoSex im Delphi viel seltener praktiziert.
  Mit Zitat antworten Zitat
jobo

Registriert seit: 29. Nov 2010
3.072 Beiträge
 
Delphi 2010 Enterprise
 
#9

AW: Trigger oder Events der DB-Komponenten zum Updaten von Fremdtabelle

  Alt 1. Jan 2018, 20:50
Zu dem Gesagten noch ein paar Gedanken:
Triggerlösung o.ä. würde ich aus Konsistenzgründen immer bevorzugen!
Die Lagerlogik käme ja sinngemäß nicht unbedingt bei Rechnungsstellung, sondern bei Bestellung?
Ich kann mir nicht vorstellen, dass eine besondere Last an der Stelle entsteht, vielleicht gibt es Tagespeaks, wenn besonders viele Bestellungen ausgeführt werden, aber es ist etwas anderes als ein Batch Lauf. Trigger sind nicht schön, aber keine unglaublichen Ressourcenfresser- an sich-, ein unglückliches Select Statement im Trigger, ein fehlender Index, .. dagegen ein Problem, nicht nur im Trigger.

Die Oracle Package Variablen sind m.E. relativ einzigartig, sowas kann man vermutlich allgemein nur mit einer Mittelschicht nachbilden, die ja offenbar nicht existiert. Ich weiß auch nicht, ob ich das an der Stelle einsetzen würde. So oder so, es ist ja kein Oracle System.
Gruß, Jo

Geändert von jobo ( 1. Jan 2018 um 20:53 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von IBExpert
IBExpert

Registriert seit: 15. Mär 2005
672 Beiträge
 
FreePascal / Lazarus
 
#10

AW: Trigger oder Events der DB-Komponenten zum Updaten von Fremdtabelle

  Alt 1. Jan 2018, 23:34
unterschiedliche Metadaten bei sonst gleicher DB ist eine nicht so dolle idee, weil dadurch
ohne Ende Baustellen aufgerissen werden, wenn du mal einen Metadatenabgleich machen musst

Leg dir lieber eine Tabelle an, in der die Features deiner lokalen Datenbank an oder abschaltbar sind
und lasse das über einen überall identischen Trigger machen, der eben ggf den lokalen Wert dieser
Tabelle abfragt und wenn der nicht gesetzt ist, dann einfach nix macht

so nach dem motto

Code:
CREATE OR ALTER trigger RG_AI for RG
active AFTER insert position 0
as
begin
  if (exists(select lagerbuchung from parametertabelle where lagerbuchung='J'))
  then
  begin
    ----...... was auch immer dann kommt
  end
end
Wir verwalten im größten Projekt 150 replizierte Datenbanken an verschiedenen Standorten, wenn
da jeder auch nur minimal andere Metadaten hätte würden wir bekloppt werden. Das ist da zwar
noch wesentlich komplexer aufgebaut, aber der o.a. Tip sollte die eine Sackgasse ersparen.

und falls du angst haben solltest das der weg zu langsam ist, packe die Tabelle in eine GTT
Global Temporary Table on commit preserve und frag das von da ab, ist dann nur im RAM.

Ist aber nicht wirklich wichtig, solche simplen Selects kann eine brauchbarer Firebird Server
locker 250000 - 500000 mal pro Sekunde abarbeiten, wenn die aus dem Trigger aufgerufen werden.

Ach noch was: Ab fb3 geht das auch über eine Stored Function und würde den code etwa so aussehen
Lassen

Code:

create function LagerBuchungAktiv()
returns boolean
as
begin
  if (exists(select lagerbuchung from parametertabelle where lagerbuchung='J'))
  then return true;
  else return false;
end;


CREATE OR ALTER trigger RG_AI for RG
active AFTER insert position 0
as
begin
  if (LagerBuchungAktiv())
  then
  begin
    ----...... was auch immer dann kommt
  end
end
Holger Klemt
www.ibexpert.com - IBExpert GmbH
Oldenburger Str 233 - 26203 Wardenburg - Germany
IBExpert and Firebird Power Workshops jederzeit auch als Firmenschulung

Geändert von IBExpert ( 1. Jan 2018 um 23:49 Uhr)
  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 03:56 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