Delphi-PRAXiS
Seite 2 von 3     12 3      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Trigger auf Datenbankebene? (https://www.delphipraxis.net/193414-trigger-auf-datenbankebene.html)

himitsu 27. Jul 2017 15:47

AW: Trigger auf Datenbankebene?
 
CREATE TRIGGER wirft da aber doch hoffentlich einen Fehler, wenn man einen zweiten Trigger erstellen will? :stupid:

Meistens hat man doch in etwa sowas:
SQL-Code:
CREATE FUNCTION TriggerFunction() ...;
CREATE TRIGGER TriggerName ON Table ... DO TriggerFunction();
Bei einigen DBMS kann man da aber auch Parameter bei den Trigger-Funktionen nutzen.
SQL-Code:
CREATE FUNCTION TriggerFunction(Param VARCHAR) ...;
CREATE TRIGGER TriggerName ON Table ... DO TriggerFunction('abc');
Und die selbe Trigger-Funktion kann man auch an mehrere Tabellen hängen.
Es gibt fast immer irgendwelche virtuellen Datenbank-Schema-Tabellen, wo man eine Liste aller aktuell existierenden Tabellen auslesen kann
und dann entweder clientseitig oder DB-seitig über einen EXECUTE-Befehl nacheinander die vielen CREATE TRIGGER zusammensetzen und ausführen.
SQL-Code:
CREATE FUNCTION TriggerFunction() ...;
CREATE TRIGGER TriggerName ON TableA ... DO TriggerFunction();
CREATE TRIGGER TriggerName ON TableB ... DO TriggerFunction();
CREATE TRIGGER TriggerName ON TableC ... DO TriggerFunction();

mkinzler 27. Jul 2017 15:47

AW: Trigger auf Datenbankebene?
 
Oder über Monitoring der Zugriffskomponenten

http://docwiki.embarcadero.com/RADSt...chung_(FireDAC)

Uwe Raabe 27. Jul 2017 16:42

AW: Trigger auf Datenbankebene?
 
Zitat:

Zitat von MES (Beitrag 1377622)
Zitat:

Zitat von Uwe Raabe (Beitrag 1377601)
Wäre ein zentrales BeforePost-Event auf Programmebene eventuell eine Alternative? Das wäre zudem noch datenbankunabhängig.

Wie kann ich die realisieren?

Hängt von deiner Arbeitsweise ab. Wenn z.B. alle Queries statisch in Datenmodulen liegen, kann man diese von einem gemeinsamen Vorfahren ableiten, der sich in das BeforePost-Event reinhängt. Alternativ wäre auch eine Interposer-Class denkbar, die das DoBeforePost überschreibt. Die Unit könnte in etwas so aussehen und müsste dann in den gewünschten Fällen in der Uses-Anweisung hinter FireDAC.Comp.Client aufgeführt werden. Das funktioniert allerdings nicht bei expliziten UPDATE Queries, sondern nur bei Verwendung der DataSet-Methoden Insert, Edit und Post.

Delphi-Quellcode:
unit FDQueryInterposer;

interface

type
  TFDQuery = class(FireDAC.Comp.Client.TFDQuery)
  protected
    procedure DoBeforePost; override;
  end;

implementation

procedure TFDQuery.DoBeforePost;
begin
  { hier bei Bedarf die entsprechenden Felder setzen }
  inherited;
end;

end.

jobo 27. Jul 2017 16:57

AW: Trigger auf Datenbankebene?
 
Zitat:

Zitat von himitsu (Beitrag 1377626)
Meistens hat man doch in etwa sowas:

@himitsu
wenn ich das richtig im Kopf habe, arbeitest Du häufig mit Postgres? Da kann man beliebige Triggerfunktionen an den Trigger hängen, auch für mehrere Trigger/Tabellen die gleiche Triggerfunktion.
Hab ich neulich noch für eine Log Funktion/Werteänderung gemacht.

Das geht aber so easy nicht mit jeder Datenbank.

Um es straight forward zu lösen, müsste m.E. tatsächlich ein Usermapping mit einer Tabelle, die aktive Sitzungen notiert, erfolgen. Daraus könnte sich dann ein Insert/Update/ Trigger pro Tabelle bedienen (delete fällt ja weg bei der Konstruktion).

Ich habe bei dem erwähnten Log Mechnismus oben, nach der Erstellung der Trigger "blinde Updates" (alter Wert = neuer Wert) über alle relevanten Daten laufen lassen und so nachträglich mit etwas Handarbeit "historische" Logdaten für initiales Insert und Update (=StatusQuo) erzeugt.
Nicht geloggte Userdaten usw. lassen sich damit natürlich im Nachhinein nicht erfinden.
Aber man hat dennoch für künftiges Reporting einen einheitlichen Stand.

In einem reinen C/S System mit nur einem Client (einer Art) kann man natürlich auch über den Client arbeiten. Hier kann man auch problemlos weitere Daten verwenden, Rechnername usw. bei Mehrfachanmeldung oder was man so braucht.

nahpets 27. Jul 2017 17:27

AW: Trigger auf Datenbankebene?
 
Eine BeforePost-Methode kann man mehreren Datenbankkomponenten zuweisen.

Beispiel:
Delphi-Quellcode:
type
  TForm1 = class(TForm)
    qryAnschriften: TZQuery; // oder sonstein genutzter Komponententyp
    qryRechnungen: TZQuery; // oder sonstein genutzter Komponententyp
...
    procedure AnyTableBeforePost(DataSet: TDataSet);
...

procedure TForm1.FormCreate(Sender: TObject);
begin
  qryAnschriften.BeforePost := AnyTableBeforePost;
  qryRechnungen.BeforePost := AnyTableBeforePost;
  ...
end;

procedure TForm1.AnyTableBeforePost(DataSet: TDataSet);
begin
  DataSet.FieldByName('Username').AsString := DeineGetUserNameFunktionOderVariabelOderSowas;
  DataSet.FieldByName('Datum').AsString := Now;
end;
Nachteil: Wird, am Programm vorbei, direkt auf der Datenbank gearbeitet oder mit anderen Clients, fehlen die im BeforePost gesetzten Informationen natürlich.

himitsu 27. Jul 2017 18:09

AW: Trigger auf Datenbankebene?
 
Zitat:

Zitat von jobo (Beitrag 1377636)
arbeitest Du häufig mit Postgres? Da kann man beliebige Triggerfunktionen an den Trigger hängen, auch für mehrere Trigger/Tabellen die gleiche Triggerfunktion.
Hab ich neulich noch für eine Log Funktion/Werteänderung gemacht.

Die Dokumentation von z.B. MSSQL hat das ähnlich.
https://docs.microsoft.com/en-us/sql...r-transact-sql
Hier klingt es sogar danach, dass man auch direkt ganze SQL-Statements da ausführen lassen kann, anstatt nur eine TriggerFunktion aufzurufen.

p80286 27. Jul 2017 19:43

AW: Trigger auf Datenbankebene?
 
Zitat:

Zitat von mikhal (Beitrag 1377602)
Ich würde es im Programm realisieren: In deiner Zugriffskomponente (vermutlich Query) gibt es das Event BeforePost, hier kannst du den Benutzernamen ermitteln und in die gewünschten Tabellenfelder eintragen.

Dann ist aber jeder DB-Nutzer, der Dein Programm nicht nutzt, außen vor. Darüber muß man sich im klaren sein.

Gruß
K-H

mikhal 27. Jul 2017 20:07

AW: Trigger auf Datenbankebene?
 
Ja, das ist wohl so. Aber eine solche Forderung geht aus der Frage des TE nicht hervor. Wahrscheinlich wurde die Anforderung erst später angefragt.

Grundsätzlich ist die Verwendung eines Datenbank-Triggers hier der bessere Weg, wenn man diese Daten grundsätzlich bei jedem Insert- oder Update-Statement verwenden möchte. Aber dann benötigt der TE eine Tabelle mit den Benutzern, gegen die sich die Anwender anmelden müssen, damit er die Namen ziehen kann. War auch mein erster Gedanke, aber ist wohl beim TE nicht vorgesehen oder war nicht geplant. Wenn ich es richtig verstanden habe, werden DB-User angemeldet, die über eine Rolle verfügen. Und ja, er muss die Trigger für jede Tabelle anlegen, ein Aufwand, den er nicht treiben wollte.

Über das Event muss er das dann aber auch machen, kann aber wie oben beschrieben eine Standard-Routine verwenden, um den Aufwand zu reduzieren.

Grüße
Mikhal

jobo 28. Jul 2017 09:25

AW: Trigger auf Datenbankebene?
 
Zitat:

Zitat von mikhal (Beitrag 1377656)
Ja, das ist wohl so.
..

Grundsätzlich ist die Verwendung eines Datenbank-Triggers hier der bessere Weg,
..

Klar, ein Server ist ein Server.
Wenn es wasserdicht sein soll, müssen solche Operationen auf dem DB Server erfolgen.

Wenn ich ein C/S System so definiere, dass mein (Delphi)Client den einzigen Zugriff hat (und diesen Zustand auch erfolgreich sicherstellen kann), dann kann ich natürlich hier alle möglichen Mätzchen machen, von Logging bis Business Logic.
Sobald mehr als ein System auf die DB durchgreift (vor allem schreibend), bin ich natürlich gekniffen. Theoretisch entgleitet das bereits, wenn ich einen Release Candidate des gleichen Sytems auf eine Produktivdb loslasse. Naja, ich will den Teufel nicht an die Wand malen. Wenn man weiß was man tut, ist vieles möglich.

Ich hatte allerdings die Anforderung des TE so verstanden, dass er nicht alle / so viel Altdaten "nachverarbeiten" will. Aber vlt geht es darum gar nicht.

Zitat:

Zitat von himitsu (Beitrag 1377646)
Die Dokumentation von z.B. MSSQL hat das ähnlich.

Ja, kann sein. Ich hab keinen so detailierten Überblick was die DB auf Triggerebene alles können / unterscheidet.
Aber das von Dir erwähnte Verfahren kenne ich so halt von Postgres und eben nicht von Maria.

p80286 28. Jul 2017 12:50

AW: Trigger auf Datenbankebene?
 
Zitat:

Zitat von jobo (Beitrag 1377674)
(und diesen Zustand auch erfolgreich sicherstellen kann)

Um die Bedeutung zu unterstreichen hättest Du einen etwas größeren Font wählen sollen.

Gruß
K-H


Alle Zeitangaben in WEZ +1. Es ist jetzt 02:21 Uhr.
Seite 2 von 3     12 3      

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz