sql >> Databasteknik >  >> RDS >> Sqlserver

Kör endast en utlösare när vissa kolumner är uppdaterade (SQL-server)

SQL Server har UPDATE() funktion som du kan använda i dina DML-utlösare för att kontrollera om en specifik kolumn har uppdaterats eller inte.

Även om den här funktionen bara accepterar en kolumn, finns det inget som hindrar dig från att inkludera flera UPDATE() satser med AND eller OR för att testa för flera kolumnuppdateringar.

Exempel

Här är tabellen:

CREATE TABLE t1 (
    id int IDENTITY(1,1) NOT NULL,
    c1 int DEFAULT 0,
    c2 int DEFAULT 0,
    c3 int DEFAULT 0,
    c4 int DEFAULT 0
);

Och här är triggern:

CREATE TRIGGER trg_t1
ON t1
AFTER INSERT, UPDATE
AS
IF ( UPDATE(c1) OR UPDATE(c2) )
BEGIN
UPDATE t1
SET c4 = c4 + 1
WHERE id IN (SELECT DISTINCT id FROM inserted)
END;

I det här fallet, c4 kolumnen kommer bara att öka om antingen c1 eller c2 kolumner uppdaterades. Detta kommer att inträffa även om bara en av dessa två kolumner uppdateras (beroende på att jag använder OR i motsats till AND ).

Låt oss nu testa utlösaren genom att infoga data i c1 .

INSERT INTO t1 (c1) 
VALUES (1);

SELECT * FROM t1;

Resultat:

+------+------+------+------+------+
| id   | c1   | c2   | c3   | c4   |
|------+------+------+------+------|
| 1    | 1    | 0    | 0    | 1    |
+------+------+------+------+------+

Som förväntat, c4 uppdaterades också när c1 uppdaterades.

Detta gäller även när c2 är uppdaterad.

UPDATE t1 
SET c2 = c2 + 1
WHERE id = 1;

SELECT * FROM t1;

Resultat:

+------+------+------+------+------+
| id   | c1   | c2   | c3   | c4   |
|------+------+------+------+------|
| 1    | 1    | 1    | 0    | 2    |
+------+------+------+------+------+

Och naturligtvis skulle det också gälla när båda är uppdaterade.

Men det gör det inte tillämpas om vi uppdaterar c3 (men inte c1 eller c2 ).

UPDATE t1 
SET c3 = c3 + 1
WHERE id = 1;

SELECT * FROM t1;

Resultat:

+------+------+------+------+------+
| id   | c1   | c2   | c3   | c4   |
|------+------+------+------+------|
| 1    | 1    | 1    | 1    | 2    |
+------+------+------+------+------+

Kräver att båda kolumnerna uppdateras

Vi kan ändra OR till AND för att ange att c4 kolumnen uppdateras endast om både c1 och c2 håller på att uppdateras.

Låt oss ändra vår trigger för att specificera detta:

ALTER TRIGGER trg_t1
ON t1
AFTER INSERT, UPDATE
AS
IF ( UPDATE(c1) AND UPDATE(c2) )
BEGIN
UPDATE t1
SET c4 = c4 + 1
WHERE id IN (SELECT DISTINCT id FROM inserted)
END;

Uppdatera nu c1 bara.

UPDATE t1 
SET c1 = c1 + 1
WHERE id = 1;

SELECT * FROM t1;

Resultat:

+------+------+------+------+------+
| id   | c1   | c2   | c3   | c4   |
|------+------+------+------+------|
| 1    | 2    | 1    | 1    | 2    |
+------+------+------+------+------+

c1 uppdaterades som specificerat, men c4 var inte.

Samma sak skulle hända om vi uppdaterade c2 men inte c1 .

Men låt oss nu uppdatera både c1 och c2 .

UPDATE t1 
SET c1 = c1 + 1, c2 = c2 + 1
WHERE id = 1;

SELECT * FROM t1;

Resultat:

+------+------+------+------+------+
| id   | c1   | c2   | c3   | c4   |
|------+------+------+------+------|
| 1    | 3    | 2    | 1    | 3    |
+------+------+------+------+------+

Som väntat, denna gång c4 uppdaterades också.

Mislyckade uppdateringar

Det är viktigt att notera att UPDATE() funktionen indikerar bara om en INSERT eller UPDATE försök gjordes på en specificerad kolumn i en tabell eller vy. Det kommer fortfarande att returneras sant om försöket misslyckades.

COLUMNS_UPDATED-funktionen

Ett annat sätt att söka efter uppdateringar i flera kolumner är att använda COLUMNS_UPDATED funktion.

Denna funktion returnerar en variant bitmönster som anger de infogade eller uppdaterade kolumnerna i en tabell eller vy.

Mer information finns i Microsofts dokumentation för COLUMNS_UPDATED .


  1. Trigger med dynamiskt fältnamn

  2. 3 sätt att ta bort dubbletter av rader i SQL Server medan du ignorerar den primära nyckeln

  3. Felaktig neutralisering av specialelement som används i ett SQL-kommando

  4. Hur tvingar jag Postgres att använda ett visst index?