Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Trigger -> Änderung in einem DBGrid (https://www.delphipraxis.net/189922-trigger-aenderung-einem-dbgrid.html)

Zwirbel 8. Aug 2016 15:44

Datenbank: Firbird • Version: 3 • Zugriff über: Seattle 10

Trigger -> Änderung in einem DBGrid
 
Hallo,

für alle Tabellen unserer Datenbank gibt es Felder wie:
Code:
  "Created" TIMESTAMP NOT NULL,
  "Modified" TIMESTAMP NOT NULL,
  "CreatedBy" SMALLINT NOT NULL,
  "ModifiedBy" SMALLINT NOT NULL,
Nun habe ich für diese Felder Trigger eingerichtet die dafür sorgen, dass die entsprechenden Felder je nach Situation angepasst werden.

Hier die Trigger:
Delphi-Quellcode:
/* Trigger für Defaultwerte von Created, Modified, CreatedBy und ModifiedBy */
SET TERM ^;
CREATE OR ALTER TRIGGER TR_TA_TimeTableList_Created_BI FOR TA_TimeTableList ACTIVE BEFORE INSERT
AS BEGIN
  IF (NEW."Created" IS NULL) THEN NEW."Created" = CURRENT_TIMESTAMP;
  IF (NEW."Modified" IS NULL) THEN NEW."Modified" = CURRENT_TIMESTAMP;
  IF (NEW."CreatedBy" IS NULL) THEN NEW."CreatedBy" = 0;
  IF (NEW."ModifiedBy" IS NULL) THEN NEW."ModifiedBy" = 0;
END ^

/* Trigger für Aktualisierung von Modified und ModifiedBy */
CREATE OR ALTER TRIGGER TR_TA_TimeTableList_Modified_BU FOR TA_TimeTableList ACTIVE BEFORE UPDATE
AS BEGIN
  NEW."Modified" = CURRENT_TIMESTAMP;
  NEW."ModifiedBy" = 0;
END ^
SET TERM ;^
Das funktioniert auch prinzipiell. Aber wenn ich nun in einem TDBGrid, das an einem TFDQuery/TDataSource hängt (was an einem TFDConnection hängt), einen Datensatz ändere, zum nächsten springe, dann wird im Grid die Änderung des "Modified" nicht sofort angezeigt, erst wenn man z. B. die Abfrage erneuert. Auf den zweiten Blick ist mir das sogar klar, das das so ist. Aber erwartet hatte ich was anderes, nämlich das im Grid sofort die Änderung zu sehen ist, wenn man was geändert hat und zu einem anderen Datensatz springt.

Wo und wie ist hier der Hebel anzusetzen, dass durch Trigger veränderte Werte in einem Grid angezeigt werden?

TIA, Markus

Neutral General 8. Aug 2016 15:55

AW: Trigger -> Änderung in einem DBGrid
 
Du musst die Daten neu laden. Da führt kein Weg dran vorbei.
Eine Hilfe dabei kann POST_EVENT sein.

dataspider 8. Aug 2016 16:00

AW: Trigger -> Änderung in einem DBGrid
 
Um die eigenen Änderungen zu sehen, reicht IMHO ein RefreshRecord nach dem Post.
Manche Komponenten haben auch ein Property, wo man das Verhalten steuern kann, ich kenne aber FDQuery nicht.

hoika 8. Aug 2016 16:00

AW: Trigger -> Änderung in einem DBGrid
 
Hallo,
das ist pure Absicht,
du siehst immer die Daten der aktuellen Transaktion (vor den Trigger-Updates).

siehe auch hier
http://stackoverflow.com/questions/1...are-editing-it

Heiko

Fritzew 8. Aug 2016 16:50

AW: Trigger -> Änderung in einem DBGrid
 
Zitat:

das ist pure Absicht,
du siehst immer die Daten der aktuellen Transaktion (vor den Trigger-Updates).
Das ist so nicht korrekt. Die Trigger werden in der aktuellen Transaction ausgeführt. Aber wie DataSpider geschrieben hat muss der aktuelle Record neu eingelesen werden.

hoika 8. Aug 2016 17:40

AW: Trigger -> Änderung in einem DBGrid
 
Hallo,#
ach so, ich dachte, es geht um ein Mehrbenutzer-System.


Heiko

himitsu 8. Aug 2016 17:47

AW: Trigger -> Änderung in einem DBGrid
 
Es gibt einige Zugriffskomponenten, die bieten direkt eine RefreshAfterPost-Option an, wo sie automatisch ein RefreshRecord nach einem Post ausführen.
Refresh = alle Datensätze / RefreshRecord nur der aktuelle Datensatz (dafür wird meißt das WHERE erweitert, um die DatensatzID) ... kommt dann drauf an, wie weit Triger die Daten ändern können und ob es sich auch auf andere Datensätze auswirken kann.

Der Insert-Trigger wäre nicht unbedingt nötig, denn dafür kann man die Default-Werte doch bestimmt auch direkt in der Tabelle definieren.
SQL-Code:
"Created" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
"Modified" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
"CreatedBy" SMALLINT NOT NULL DEFAULT 0, -- CURRENT_USER?
"ModifiedBy" SMALLINT NOT NULL DEFAULT 0,
Aber warum wird Modified schon beim Insert gesetzt, wo es da doch noch garnicht editiert sein kann? :zwinker:



Na dann hoffe ich mal, dass dein Programm im Laufe seines Lebens nicht mehr als 32.767 User kennt :angle:

p80286 8. Aug 2016 18:47

AW: Trigger -> Änderung in einem DBGrid
 
Zitat:

Zitat von himitsu (Beitrag 1344401)
SQL-Code:
"Created" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
"Modified" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
"CreatedBy" SMALLINT NOT NULL DEFAULT 0, -- CURRENT_USER?
"ModifiedBy" SMALLINT NOT NULL DEFAULT 0,
Aber warum wird Modified schon beim Insert gesetzt, wo es da doch noch garnicht editiert sein kann? :zwinker:



Na dann hoffe ich mal, dass dein Programm im Laufe seines Lebens nicht mehr als 32.767 User kennt :angle:

Wenn sich hinter CreatedBy/ModifiedBy eine unique ID aus einem Generator verbirgt, könnte das aber ganz schnell, ganz eng werden.

Gruß
K-H

Zwirbel 9. Aug 2016 09:00

AW: Trigger -> Änderung in einem DBGrid
 
Zitat:

Zitat von himitsu (Beitrag 1344401)
Es gibt einige Zugriffskomponenten, die bieten direkt eine RefreshAfterPost-Option an, wo sie automatisch ein RefreshRecord nach einem Post ausführen.

Welche Komponente meinst du hier konkret? In TFDQuery oder TDBGrid kann ich eine solche Option nicht finden. Es geht auch wirklich um eine Option oder um irgendeinen Event?

Zitat:

Zitat von himitsu (Beitrag 1344401)
Der Insert-Trigger wäre nicht unbedingt nötig, denn dafür kann man die Default-Werte doch bestimmt auch direkt in der Tabelle definieren.

Wie sollte ein Defaultwert für ein Datum/Zeit-Feld (wie "Created"/"Modified") aussehen? Genauso die Frage, wie es für "CreatedBy"/"ModifiedBy" aussehen könnte? Ich habe in der Richtung schon gesucht, ich bräuchte quasi so etwas wie eine Variable die meine Anwendung setzen kann, also wenn sich ein Anwender an unserer Anwendung (mit der UserId=5) anmeldet, dass ich diese "5" irgendwie an Firebird übergeben kann, dass es bei den Triggern dann für "CreatedBy"/"ModifiedBy" diesen Wert nimmt. Noch völlig unbeleckt von den Möglichkeiten einer SQL-Datenbank wüsste ich nicht wie das (natürlich möglichst elegant) gehen soll. Klar, ich könnte mir jetzt eine Pseudo-Tabelle basteln "ActiveUser" mit einem einzigen Feld drin "ActiveUserId". Beim Anmelden speichere ich dann in der Tabelle einen Datensatz mit der "5", um im obigen Beispiel zu bleiben. Dann müsste ich in meinen Triggern diese Tabelle "ActiveUser" abfragen. Aber da dreht sich mir irgendwie der Magen um, das wäre doch ziemlicher Unsinn. Wie geht es eleganter/performanter?

Zitat:

Zitat von himitsu (Beitrag 1344401)
SQL-Code:
"Created" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
"Modified" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
"CreatedBy" SMALLINT NOT NULL DEFAULT 0, -- CURRENT_USER?
"ModifiedBy" SMALLINT NOT NULL DEFAULT 0,

"CURRENT_USER" ist ein VarChar. Ich möchte auf keinen Fall in meinen Tabellen pro Datensatz eine Zeichenkette speichern mit dem User als String, das hielte ich für keine gute Idee. Außerdem wäre "CURRENT_USER" ja der aktuelle User der Firebird-Datenbank. Ich würde gerne den aktuellen User (als Integer) aus unserer eigenen Userverwaltung verwenden. So mache ich das in unserer aktuellen Anwendung auch. Da ich da aber keine Trigger verwenden kann, wird diese ganze "Created"...-Gedöns alles zu Fuß für jedes einzelne TTable/TQuery das auf einem Formular pappt erledigt. Da dachte ich nun, wunderbar mit SQL geht das ja alles viel einfacher, das erledigt quasi die Datenbank im Hintergrund.

Zitat:

Zitat von himitsu (Beitrag 1344401)
Aber warum wird Modified schon beim Insert gesetzt, wo es da doch noch garnicht editiert sein kann? :zwinker:

Da hast du Recht, das ist Unfug.

Zitat:

Zitat von himitsu (Beitrag 1344401)
Na dann hoffe ich mal, dass dein Programm im Laufe seines Lebens nicht mehr als 32.767 User kennt :angle:

Bei einem Kunden hat es ca. 50 User, bei den anderen <= 20. Da ist man mit dem SMALLINT auf der sicheren Seite. ;-)

TIA, Markus

Zwirbel 9. Aug 2016 09:11

AW: Trigger -> Änderung in einem DBGrid
 
Zitat:

Zitat von p80286 (Beitrag 1344405)
Zitat:

Zitat von himitsu (Beitrag 1344401)
SQL-Code:
"Created" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
"Modified" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
"CreatedBy" SMALLINT NOT NULL DEFAULT 0, -- CURRENT_USER?
"ModifiedBy" SMALLINT NOT NULL DEFAULT 0,
Aber warum wird Modified schon beim Insert gesetzt, wo es da doch noch garnicht editiert sein kann? :zwinker:

Na dann hoffe ich mal, dass dein Programm im Laufe seines Lebens nicht mehr als 32.767 User kennt :angle:

Wenn sich hinter CreatedBy/ModifiedBy eine unique ID aus einem Generator verbirgt, könnte das aber ganz schnell, ganz eng werden.

Ja, die IDs kommen aus einem Generator, aber in unserer Anwendung tummeln sich nur sehr wenige (<50) Anwender. Habt ihr denn Kunden mit mehr als 32.767 Anwendern in einer Datenbank-Anwendung? :shock: Vermutlich schon, sonst wärt ihr nicht erstaunt, dass ich da mit einem SMALLINT aus komme. Mir würde auch ein BYTE reichen, wenn es das gäbe. ;-)

Gruß, Markus


Alle Zeitangaben in WEZ +1. Es ist jetzt 20:21 Uhr.

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