I SQL Server kan du oprette DML-triggere, der kun udfører kode, når en specifik kolonne opdateres.
Udløseren udløses stadig, men du kan teste, om en specifik kolonne blev opdateret eller ej, og derefter kun køre kode, hvis denne kolonne blev opdateret.
Du kan gøre dette ved at bruge UPDATE()
funktion inde i din trigger. Denne funktion accepterer kolonnenavnet som dets argument. Det returnerer en boolean.
Eksempel
Her er tabellen:
CREATE TABLE t1 (
id int IDENTITY(1,1) NOT NULL,
c1 int DEFAULT 0,
c2 int DEFAULT 0,
c3 int DEFAULT 0
);
Og her er udløseren:
CREATE TRIGGER trg_t1
ON t1
AFTER INSERT, UPDATE
AS
IF ( UPDATE (c1) )
BEGIN
UPDATE t1
SET c3 = c3 + 1
WHERE id IN (SELECT DISTINCT id FROM inserted)
END;
I dette eksempel opretter jeg en tabel kaldet t1
og en trigger kaldet trg_t1
.
Jeg bruger en IF
sætning sammen med UPDATE()
funktion til at teste om c1
kolonne blev opdateret.
Når triggeren kører, vil den kun udføre den efterfølgende kode, hvis denne betingelse er sand.
Udløs triggeren
Lad os indsætte en række, men vi indsætter kun en værdi i c1
kolonne.
INSERT INTO t1 (c1)
VALUES (1);
SELECT * FROM t1;
Resultat:
+------+------+------+------+ | id | c1 | c2 | c3 | |------+------+------+------| | 1 | 1 | 0 | 1 | +------+------+------+------+
Som forventet udløste triggeren, og kolonnen c3
blev også opdateret.
Dette skete, fordi jeg inkluderede INSERT
argument i min triggers definition (dvs. jeg specificerede AFTER INSERT, UPDATE
hvilket betyder, at udløseren udløses, hver gang data indsættes eller opdateres). Hvis jeg kun havde angivet AFTER UPDATE
, ville det ikke have udløst, når jeg indsatte data – det ville kun udløses, når jeg opdaterer eksisterende data.
Husk at tabellen blev defineret med DEFAULT 0
, så c2-kolonnen var som standard nul.
Lad os nu opdatere c1
kolonne.
UPDATE t1
SET c1 = c1 + 1
WHERE id = 1;
SELECT * FROM t1;
Resultat:
+------+------+------+------+ | id | c1 | c2 | c3 | |------+------+------+------| | 1 | 2 | 0 | 2 | +------+------+------+------+
Igen, c3
kolonne blev opdateret sammen med c1
.
Lad os nu lave en opdatering til c2
kolonne (denne kolonne er ikke inkluderet i triggeren).
UPDATE t1
SET c2 = c2 + 1
WHERE id = 1;
SELECT * FROM t1;
Resultat:
+------+------+------+------+ | id | c1 | c2 | c3 | |------+------+------+------| | 1 | 2 | 1 | 2 | +------+------+------+------+
Så denne gang, c2
blev opdateret, men c3
var det ikke. Det er fordi c1
kolonnen blev ikke opdateret, og vores trigger opdaterer kun c3
når c1
er opdateret.
Det samme ville være sket, hvis vi havde indsat en række uden at angive c1 i INSERT
erklæring.
Hvad hvis jeg opdaterer kolonnen med samme værdi?
Hvis du opdaterer en kolonne med samme værdi, vises UPDATE()
funktion vil returnere sand.
Her er et eksempel.
Vi ved fra vores tidligere eksempler, at c1-kolonnen indeholder en værdi på 2
.
Lad os eksplicit opdatere den kolonne med den samme værdi:1
UPDATE t1
SET c1 = 2
WHERE id = 1;
SELECT * FROM t1;
Resultat:
+------+------+------+------+ | id | c1 | c2 | c3 | |------+------+------+------| | 1 | 2 | 1 | 3 | +------+------+------+------+
Så nu c3
er steget, selvom værdien for c1
er stadig den samme.
Lad os gøre det igen, men denne gang indstilles det til sig selv (dvs. ændre c1 = 1
til c1 = c1
).
UPDATE t1
SET c1 = c1
WHERE id = 1;
SELECT * FROM t1;
Resultat:
+------+------+------+------+ | id | c1 | c2 | c3 | |------+------+------+------| | 1 | 2 | 1 | 4 | +------+------+------+------+
Igen, c3
er steget.
Mislykkede opdateringsforsøg
Det er vigtigt at bemærke, at UPDATE()
funktion angiver blot, om en INSERT
eller UPDATE
forsøg blev lavet på en specificeret kolonne i en tabel eller visning. Det vil stadig returnere sandt, hvis forsøget var mislykket.