När du skapar en utlösare i SQL Server har du möjlighet att aktivera den tillsammans med den utlösande satsen (d.v.s. SQL-satsen som aktiverade triggern), eller aktivera den istället av det uttalandet.
För att aktivera utlösaren istället för den utlösande satsen, använd INSTEAD OF
argument.
Detta är i motsats till att använda FOR
eller AFTER
argument. När du använder dessa argument aktiveras utlösaren endast när alla operationer som anges i den utlösande SQL-satsen har startat framgångsrikt.
Exempel
Skapa en exempeltabell:
CREATE TABLE t1 (
id int IDENTITY(1,1) NOT NULL,
c1 int DEFAULT 0,
c2 int DEFAULT 0,
c3 int DEFAULT 0
);
Skapa utlösaren:
CREATE TRIGGER trg_t1
ON t1
INSTEAD OF UPDATE
AS
UPDATE t1
SET c3 = c3 + 1
WHERE id IN (SELECT DISTINCT id FROM inserted);
Infoga en exempelrad:
INSERT INTO t1 (c1, c2, c3)
VALUES (1, 1, 1);
SELECT * FROM t1;
Det här är vad vi har hittills:
+------+------+------+------+ | id | c1 | c2 | c3 | |------+------+------+------| | 1 | 1 | 1 | 1 | +------+------+------+------+
Låt oss nu köra en UPDATE
uttalande mot tabellen (detta aktiverar utlösaren).
UPDATE t1
SET c1 = c1 + 1
WHERE id = 1;
SELECT * FROM t1;
Resultat:
+------+------+------+------+ | id | c1 | c2 | c3 | |------+------+------+------| | 1 | 1 | 1 | 2 | +------+------+------+------+
Som förväntat, UPDATE
uttalandet i det utlösande uttalandet ersattes med det i utlösaren.
Min trigger specificerade att varje gång det görs ett försök till uppdatering av tabellen, uppdatera c3
kolumn istället.
Kör endast när en specifik kolumn uppdateras
Du kan också använda UPDATE()
funktion för att ange kod som endast ska köras när en angiven kolumn uppdateras.
Vi kan till exempel ändra vår trigger enligt följande:
ALTER TRIGGER trg_t1
ON t1
INSTEAD OF UPDATE
AS
IF ( UPDATE(c1) )
BEGIN
UPDATE t1
SET c3 = c3 + 1
WHERE id IN (SELECT DISTINCT id FROM inserted)
END;
Kör nu föregående UPDATE
uttalande igen:
UPDATE t1
SET c1 = c1 + 1
WHERE id = 1;
SELECT * FROM t1;
Resultat:
+------+------+------+------+ | id | c1 | c2 | c3 | |------+------+------+------| | 1 | 1 | 1 | 3 | +------+------+------+------+
Återigen, c3
kolumnen ökas.
Men låt oss nu försöka uppdatera c2
kolumn:
UPDATE t1
SET c2 = c2 + 1
WHERE id = 1;
SELECT * FROM t1;
Resultat:
+------+------+------+------+ | id | c1 | c2 | c3 | |------+------+------+------| | 1 | 1 | 1 | 3 | +------+------+------+------+
Inget ändras. c3
kolumnen förblir densamma.
Inte ens c2
kolumnen uppdateras. Detta beror på att triggern fortfarande körs istället för den utlösande satsen.
Kör Trigger istället för DELETE
Vi kan modifiera triggern så att den körs istället för vilken DELETE
som helst uttalanden.
ALTER TRIGGER trg_t1
ON t1
INSTEAD OF DELETE
AS
UPDATE t1
SET c3 = c3 + 1
WHERE id IN (SELECT DISTINCT id FROM deleted);
Låt oss nu försöka ta bort alla rader och välj sedan alla rader från tabellen.
DELETE FROM t1;
SELECT * FROM t1;
Resultat:
+------+------+------+------+ | id | c1 | c2 | c3 | |------+------+------+------| | 1 | 1 | 1 | 4 | +------+------+------+------+
Observera att för att den här utlösaren skulle fungera korrekt, var jag tvungen att fråga den deleted
tabell i min utlösare (i motsats till den inserted
tabell i de föregående exemplen).
Dessa två tabeller skapas och hanteras av SQL Server.
Den deleted
Tabell lagrar kopior av de berörda raderna under DELETE
och UPDATE
uttalanden. Under körningen av en DELETE
eller UPDATE
sats, rader raderas från triggertabellen och överförs till den borttagna tabellen.
Den inserted
Tabell lagrar kopior av de berörda raderna under INSERT
och UPDATE
uttalanden. Under en infogning eller uppdateringstransaktion läggs nya rader till i både den infogade tabellen och triggertabellen. Raderna i den infogade tabellen är kopior av de nya raderna i triggertabellen.
Några begränsningar att tänka på
Du kan definiera maximalt en INSTEAD OF
trigger per INSERT
, UPDATE
, eller DELETE
uttalande på en tabell eller vy.
Du kan inte definiera INSTEAD OF
triggers på uppdateringsbara vyer som använder WITH CHECK OPTION
.