|
Trigger in einer MS SQL Server-Datenbank
Frage: Ich versuche krampfhaft in einem Trigger den Wert eines Feldes in einer Tabelle zu setzen. Wenn der Anwender einen Datensatz ändert, soll automatisch das Feld letzte_bearbeitung (DateTime) gesetzt werden. Wie komme ich am schnellsten zu einem Ergebnis?
Antwort: Der Microsoft SQL Server 2000 unterscheidet sich beim Thema Trigger vom InterBase. Es gibt dort zwei Arten von Triggern. Die normalen Trigger sind alle After-Trigger, die erst nach der eigentlichen Aktion (UPDATE, INSERT oder DELETE) ausgelöst werden. Wenn aber Spaltenwerte vor dem UPDATE-Schreibvorgang auf die Tabelle vom Trigger ausgetauscht werden sollen, muss man zum INSTEAD OF-Trigger greifen. Die geschilderte Aufgabe lässt sich jedoch mit einem ganz normalen Trigger umsetzen. Allerdings muss man beachten, dass der Trigger im Worst Case auch für eine vollständige Datenmenge zuständig ist. Der Trigger wird unabhängig von der Anzahl der betroffenen Datensätze immer nur einmal am Ende gefeuert - damit aber dieses Verhalten nicht zum Problem wird, tauchen im Kontext eines Trigger zwei virtuelle Tabellen auf. Die Tabelle Inserted enthält die neu hinzugekommenen bzw. geänderten Datensätze, während die Tabelle Deleted die gelöschten Datensätze enthält. Somit könnte der Trigger über einen Join direkt auf die Daten zugreifen, aber das ist in unserem Fall gar nicht notwendig, wie das folgende Beispiel zeigt:
A) Testtabelle vorbereiten
Die zum Test verwendete Tabelle wird in der MS SQL Server-Datenbank tempdb angelegt:
USE tempdb
GO
CREATE TABLE TestTbl
(
recid INTEGER NOT NULL IDENTITY PRIMARY KEY,
wert VARCHAR(9) NOT NULL,
datum DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
)
GO
INSERT INTO dbo.TestTbl (wert) VALUES ('Eintrag 1')
INSERT INTO dbo.TestTbl (wert) VALUES ('Eintrag 2')
INSERT INTO dbo.TestTbl (wert) VALUES ('Eintrag 3')
GO
B) Trigger aktivieren
Beim Microsoft SQL Server sind im Trigger zwei Hilfstabellen sichtbar. Die Tabelle Inserted enthält die neu hinzugekommenen bzw. geänderten Datensätze, während die Tabelle Deleted die gelöschten Datensätze enthält. Dies ist immer dann wichtig, wenn der Trigger nicht nur einen Datensatz bearbeiten muss, sondern eine Datenmenge. Über die IN-Abfrage ermittelt der Trigger alle zu aktualisierenden Datensätze:
CREATE TRIGGER trTestTblUpdate ON dbo.TestTbl FOR UPDATE
AS
IF (@@ROWCOUNT = 0)
RETURN
BEGIN
UPDATE
dbo.TestTbl
SET
datum = CURRENT_TIMESTAMP
WHERE recid IN (SELECT recid FROM INSERTED)
END
GO
C) Trigger testen
Im Query Analyzer vom MS SQL Server 2000 schicke ich nun die folgenden Anweisungen ab, um das Verhalten des Triggers beim Aktualisieren von einem beziehungsweise von mehreren Datensätzen zu testen:
-- Trigger testen
UPDATE dbo.TestTbl SET wert = 'Neu 2' WHERE recid = 2
SELECT * FROM dbo.TestTbl
-- Trigger beim Mehrfach-Update testen
UPDATE dbo.TestTbl SET wert = 'Neu 2' WHERE recid > 1
SELECT * FROM dbo.TestTbl
|