Nogle databasetabeller indeholder en "sidst ændret" kolonne, som gemmer datoen og klokkeslættet, hvor rækken sidst blev opdateret. Hver gang rækken opdateres, opdateres datoen for at afspejle datoen og klokkeslættet for den pågældende opdatering.
I SQL Server kan du bruge en trigger til at udføre denne opdatering.
En trigger er en speciel type lagret procedure, der automatisk kører, når en hændelse opstår på databaseserveren.
Du kan bruge CREATE TRIGGER
sætning for at oprette en trigger, når du bruger T-SQL. Denne erklæring kan bruges til at oprette en DML-, DDL- eller logontrigger.
Eksempel
Følgende kode opretter en tabel samt en trigger, der opdaterer ModifiedDate
kolonne, når der er en opdatering.
CREATE TABLE dbo.Books (
BookId int IDENTITY(1,1) NOT NULL PRIMARY KEY,
BookName nvarchar(1000) NOT NULL,
CreateDate datetime DEFAULT CURRENT_TIMESTAMP,
ModifiedDate datetime DEFAULT CURRENT_TIMESTAMP
);
CREATE TRIGGER trg_Books_UpdateModifiedDate
ON dbo.Books
AFTER UPDATE
AS
UPDATE dbo.Books
SET ModifiedDate = CURRENT_TIMESTAMP
WHERE BookId IN (SELECT DISTINCT BookId FROM inserted);
Indsæt en række
Lad os indsætte en række og vælge den for at se resultatet af DEFAULT
begrænsning:
INSERT INTO Books (BookName)
VALUES ('Trigger Happy');
SELECT * FROM Books;
Resultat (ved hjælp af lodret output):
-[ RECORD 1 ]------------------------- BookId | 1 BookName | Trigger Happy CreateDate | 2020-08-17 23:33:15.230 ModifiedDate | 2020-08-17 23:33:15.230
Dette vises ved hjælp af lodret output for at gøre det lettere at læse (så du ikke behøver at rulle sidelæns for at læse alle kolonner).
I dette tilfælde er både CreatedDate
og ModifiedDate
kolonner indeholder den samme værdi. Men hvis rækken er opdateret, vises ModifiedDate
's værdi burde ændre sig. Det er derfor, vi skabte udløseren.
Opdater rækken
Lad os nu opdatere rækken og vælge resultaterne.
UPDATE Books
SET BookName = 'Trigger Hippy'
WHERE BookId = 1;
SELECT * FROM Books;
Resultat (ved hjælp af lodret output):
-[ RECORD 1 ]------------------------- BookId | 1 BookName | Trigger Hippy CreateDate | 2020-08-17 23:33:15.230 ModifiedDate | 2020-08-18 00:07:39.680
Som forventet er ModifiedDate
kolonnen er opdateret, men CreateDate
kolonne forbliver den samme.
Yderligere forklaring af koden
Nedenfor er en mere detaljeret forklaring af den kode, der blev brugt til at oprette tabellen og dens tilhørende trigger.
Bordet
Følgende kode opretter tabellen:
CREATE TABLE dbo.Books (
BookId int IDENTITY(1,1) NOT NULL PRIMARY KEY,
BookName nvarchar(1000) NOT NULL,
CreateDate datetime DEFAULT CURRENT_TIMESTAMP,
ModifiedDate datetime DEFAULT CURRENT_TIMESTAMP
);
ModifiedDate
kolonne har en DEFAULT
begrænsning, som sætter standardværdien til CURRENT_TIMESTAMP
(det samme gør CreateDate
kolonne).
Det betyder, at når rækken indsættes første gang, vises CURRENT_TIMESTAMP
er indsat i disse kolonner.
Dette er fint til den første indsættelse, men det tager ikke højde for eventuelle efterfølgende opdateringer. Det er her, triggeren kommer ind.
Udløseren
Følgende kode opretter triggeren:
CREATE TRIGGER trg_Books_UpdateModifiedDate
ON dbo.Books
AFTER UPDATE
AS
UPDATE dbo.Books
SET ModifiedDate = CURRENT_TIMESTAMP
WHERE BookId IN (SELECT DISTINCT BookId FROM inserted);
I dette tilfælde kaldte jeg triggeren trg_Books_UpdateModifiedDate
.
Jeg oprettede den på dbo.Books
database, og den kører efter hver UPDATE
.
Når den kører, opdaterer den ModifiedDate
kolonne til CURRENT_TIMESTAMP
(men kun på den række, der blev opdateret, selvfølgelig).
Jeg er i stand til at bestemme, hvilken række der blev opdateret ved at kontrollere den inserted
bord. Den inserted
table er en midlertidig, hukommelsesresident tabel, som SQL Server opretter og vedligeholder.
Den inserted
tabel gemmer kopier af de berørte rækker under INSERT
og UPDATE
udsagn. Under en indsættelses- eller opdateringstransaktion tilføjes nye rækker til både de inserted
bordet og triggerbordet. Rækkerne i den inserted
tabel er kopier af de nye rækker i triggertabellen.
Ud over den inserted
tabel, opretter og vedligeholder SQL Server også en deleted
bord. En opdateringstransaktion ligner en sletningsoperation efterfulgt af en indsættelseshandling; de gamle rækker kopieres til den deleted
tabel først, og derefter kopieres de nye rækker til triggertabellen og til den inserted
tabel.
En trigger for kolonnen "Oprettet dato"
Brug af en DEFAULT
begrænsning er en praktisk måde at skabe den oprindelige værdi på, men du risikerer, at nogen direkte kan opdatere værdien senere.
Hvis du ser dette som et problem, kan du ændre triggeren til at inkludere kolonnen "Oprettet dato", så den nulstiller den til sin oprindelige værdi, hver gang der er en opdatering af rækken.
Du kan få den oprindelige værdi fra den deleted
tabel, da de gamle rækker kopieres til denne tabel først, før der finder nogen opdateringer sted.