wawidl
Goto Top

SQL-Script (Update) ausführen, sobald Änderungen in Tabelle erfolgen

Hallo,

ich kenne mich zwar etwas mit SELECT / UPDATE etc aus, aber habe mich noch nicht ausreichend mit Prozeduren etc befasst.

Ich habe eine Tabelle, in die Daten geschrieben werden, zur weiteren Verarbeitung.

Wie ermögliche ich es, diese Tabelle auf Änderungen zu überwachen, um dann mein SQL-Script ausführen zu lassen?

Ich bitte um Hilfe und einfachste Erklärungen / Beispiele.

Danke

Content-ID: 310118

Url: https://administrator.de/contentid/310118

Ausgedruckt am: 23.11.2024 um 02:11 Uhr

emeriks
emeriks 17.07.2016 um 13:15:08 Uhr
Goto Top
Hi,
schau mal hier: CREATE TRIGGER (Transact-SQL)

E.
wawidl
wawidl 17.07.2016 um 16:13:39 Uhr
Goto Top
Danke für den Hinweis, da verstehe ich aber leider nur Bahnhof face-sad

Wenn ich einen Trigger anlege, wird mir etwas vorbelegt, aber weis nun auch nicht was ich brauche und was nicht.
Ich möchte ungern Try & Error anwenden.

Im Grunde hat meine Tabelle 3 Spalten (Nummer, Datum, Wert).
Es wird entweder nur ein Wert einer bestehenden Zeile geändert oder eine ganze Zeile neu hinzugefügt.

Diese Änderung möchte ich dann als Trigger verwenden, um dann ein UPDATE-Script durchzuführen.

UPDATE tabelle SET Wert = 1 WHERE Nummer = 'XXX'

Ich danke für kleine Beispiele.
129813
129813 18.07.2016 aktualisiert um 10:48:45 Uhr
Goto Top
Hi.
It would be very helpful to know which SQL-System you are using!
MS-SQL / MySQL / ......
You didn't write anything about that in your post, but this is essential to know for writing triggers which run automatically on the SQL server afterwards.

Regards
wawidl
wawidl 28.07.2016 um 16:38:36 Uhr
Goto Top
Mircosoft SQL Server 2014 Standard


I need only one simple example to understand a procedure.
emeriks
emeriks 28.07.2016 um 16:47:15 Uhr
Goto Top
Schau mal z.B. hier. Ich glaube, das Bsp. passt zu Deinem Fall.
Biber
Biber 28.07.2016 um 17:10:17 Uhr
Goto Top
Moin wawidl,

nur zur Problemklärung eine Nachfrage:

Zitat von @wawidl:

Im Grunde hat meine Tabelle 3 Spalten (Nummer, Datum, Wert).
Es wird entweder nur ein Wert einer bestehenden Zeile geändert oder eine ganze Zeile neu hinzugefügt.

Diese Änderung möchte ich dann als Trigger verwenden, um dann ein UPDATE-Script durchzuführen.

UPDATE tabelle SET Wert = 1 WHERE Nummer = 'XXX'
Frage: wenn Änderungen an deiner Im-Grunde-drei-Spalten-Tabelle stattfinden, willst du
  • genau dieselbe Tabelle ändern, und zwar die gerade geänderte Zeile
  • genau dieselbe Tabelle ändern, aber andere Zeilen in dieser Tabelle
  • oder aber eine andere Tabelle ändern/aktualisieren?

Und ebenfalls zur Sicherheit die Frage:
  • wenn ein Datensatz gelöscht wird, dann hat das keine nachfolgenden Änderungen zur Folge?


Ich fürchte, emeriks und du habt unterschiedliche Szenarien vor Augen.

Grüße
Biber
wawidl
wawidl 29.07.2016 aktualisiert um 19:40:39 Uhr
Goto Top
Danke dir Biber, gerne gebe ich weitere Infos.

In dieser Tabelle werden NUR neue Zeilen hinzugefügt, oder einzelne Zeilen mit einem Wert geändert.
Ich muss also nur dafür sorgen, dass meine Prozedur erkennt, WANN eine neue Zeile dazugekommen ist, bzw. ein Wert sich geändert hat.

Sofern dieser Trigger erkannt wurde, soll in einer anderen Tabelle ein SQL UPDATE erfolgen, als Zuordnung / Vergleich dient dann die eindeutige Nummer.
BirdyB
BirdyB 29.07.2016 um 19:43:41 Uhr
Goto Top
Hier sind Trigger nochmal gut erklärt(allerdings für mysql):
http://www.mysqltutorial.org/create-the-first-trigger-in-mysql.aspx
wawidl
wawidl 29.07.2016 um 20:31:17 Uhr
Goto Top
CREATE TRIGGER [dbo].[VERSANDGEWICHTBERECHNUNG] ON [dbo].[VERSANDGEWICHT]
FOR INSERT,UPDATE
AS 
	BEGIN
		UPDATE tBestellung
		SET cStatus='2'  
		FROM VERSANDGEWICHT A 
		INNER JOIN tBestellung I
		ON A.AUFTRAGSNUMMER = I.cBestellNr
	END
GO

Soweit bin ich jetzt ... UND es funktioniert FAST wie gewünscht!

Wenn es nun in der Tabelle "VERSANDGEWICHT" eine neue Zeile oder Änderung gibt, wird sofort "cStatus" in der Tabelle "tBestellung" aktualisiert!
Soweit klasse, ABER wie kann ich es nun umbauen, dass NUR die jeweils betroffenen Auftragsnummern aktualisiert werden?
Aktuell sind stets ALLE Zeilen = ALLE Aufträge betroffen, was natürlich unnötige Zeit ist.

Danke bis hier hin.
BirdyB
BirdyB 29.07.2016 um 21:10:52 Uhr
Goto Top
Siehe hier: http://dcx.sybase.com/1200/de/dbreference/create-trigger-statement.html

REFERENCING NEW as NewRow

Dann kannst du die neue Zeile direkt per NewRow ansprechen.
wawidl
wawidl 30.07.2016 um 11:16:32 Uhr
Goto Top
Ich konnte das Problem einfacher lösen.

In meiner SQL-Tabelle die überwacht wird, habe ich um eine Spalte "TODO" erweitert.
Steht hier TODO=1 wird der Trigger für diese Zeile angewendet, nach Abschluss TODO=0.

Mein Dritttool schreibt bei Updates oder Inserts dann eben TODO=1, somit wird der Trigger abgestoßen.

Mein erster Trigger läuft face-smile
BirdyB
BirdyB 30.07.2016 um 11:24:57 Uhr
Goto Top
Zitat von @wawidl:

Ich konnte das Problem einfacher lösen.

In meiner SQL-Tabelle die überwacht wird, habe ich um eine Spalte "TODO" erweitert.
Steht hier TODO=1 wird der Trigger für diese Zeile angewendet, nach Abschluss TODO=0.
Ich glaube nicht, dass diese Lösung einfacher ist. Vermutlich ist hier auch die Performance schlechter...
Ich würde es an deiner Stelle umbauen, dass der Trigger nur über die neue Zeile läuft, sonst pflügt der Trigger jedesmal durch die ganze Tabelle...
Mein Dritttool schreibt bei Updates oder Inserts dann eben TODO=1, somit wird der Trigger abgestoßen.

Mein erster Trigger läuft face-smile
Herzlichen Glückwunsch und allzeit gute Reise face-wink

Beste Grüße!


Berthold
Biber
Biber 01.08.2016 um 10:01:29 Uhr
Goto Top
Moin wawidl,

komme erst heute dazu, hier auch wieder mitzumischen.
Von daher kommentiere ich lieber von dem Kommentar an, an dem es IMHO schräg läuft.


Zitat von @wawidl:

CREATE TRIGGER [dbo].[VERSANDGEWICHTBERECHNUNG] ON [dbo].[VERSANDGEWICHT]
 FOR INSERT,UPDATE
 AS 
 	BEGIN
 		UPDATE tBestellung
 		SET cStatus='2'  
 		FROM VERSANDGEWICHT A 
 		INNER JOIN tBestellung I
 		ON A.AUFTRAGSNUMMER = I.cBestellNr
 	END
 GO

Soweit bin ich jetzt ... UND es funktioniert FAST wie gewünscht!

Wenn es nun in der Tabelle "VERSANDGEWICHT" eine neue Zeile oder Änderung gibt, wird sofort "cStatus" in der Tabelle "tBestellung" aktualisiert!
Soweit klasse, ABER wie kann ich es nun umbauen, dass NUR die jeweils betroffenen Auftragsnummern aktualisiert werden?
Aktuell sind stets ALLE Zeilen = ALLE Aufträge betroffen, was natürlich unnötige Zeit ist.

In MSSQL-Triggern stehen zwei "virtuelle Tabellen" zur Verfügung unter den Namen inserted und deleted..
Die Tabelle inserted enthält alle Zeilen der Tabelle, zu der der Trigger gehört und die "neu oder geändert" sind, also den neuen Zustand.
Die Tabelle deleted enthält alle Zeilen der Tabelle, zu der der Trigger gehört und die "gelöscht" worden sind bzw. den alten Zustand der geänderten Zeilen.

Jeweils mit allen Feldern, die auch die Originaltabelle hat.
Zusätzlich kannst du auch noch den Änderungsstatus jedes einzelnes Feldes prüfen mit der Funktion update(<feldname>) und so z.B. nur dann Folgeaktionen auslösen, wenn {{if update(versandgewicht) ein TRUE zurückliefert o.ä..

Mit diesen Möglichkeiten wäre dein Trigger oben mit der ja recht schlichten Logik "setze in einer anderen Tabelle den Status auf '2', wenn sich in Tabelle Versandgewicht irgendwas geändert hat":

CREATE TRIGGER [dbo].[VERSANDGEWICHTBERECHNUNG] ON [dbo].[VERSANDGEWICHT]
 FOR INSERT,UPDATE
 AS 
 	BEGIN
 		UPDATE tBestellung
 		SET cStatus='2'  
 		FROM inserted i 
 		INNER JOIN tBestellung b
 		ON i.AUFTRAGSNUMMER = b.cBestellNr
 	END
 GO

Das setzt allerdings das Vorhandensein eines Datensatzes mit der entsprechenden tBestellung.cbestellNr voraus.
Wenn dort nioch kein Satz vorhanden ist, wird auch keiner Upgedated.
Ist nicht schlimm - wenn vom UPDATE kein Satz betroffen ist, dann werden halt "0 Sätze upgedated",; das wirft aber keinen Fehler.

Grüße
Biber