Attention à la fonction UPDATE() utilisée dans les déclencheures (triggers).
Ne pensez pas que cela vous indique que la valeur de la colonne a changé, mais simplement
que la colonne a été mentionnée dans l’instruction. Un exemple :
GO
CREATE TABLE dbo.Contact (Id INT, Name VARCHAR(50))
GO
INSERT INTO dbo.Contact
VALUES (1, 'Fillon'), (2, 'Copé');
CREATE TRIGGER atr_u_Contact
ON dbo.Contact
AFTER UPDATE
AS BEGIN
IF UPDATE(Name)
PRINT 'ok'
ELSE
PRINT 'non'
END
UPDATE dbo.Contact
SET Name = Name
WHERE Id = 2;
-- affiche oui
UPDATE dbo.Contact
SET Id = Id
WHERE Id = 2;
-- affiche non
Donc il vaut mieux tester s’il y a eu réellement une modification avant d’exécuter tout le reste. Par exemple, à la place de ceci :
ON dbo.Contact
AFTER UPDATE
AS BEGIN
IF UPDATE(Name)
INSERT INTO ContactHistory (Id, Name)
SELECT Id, Name
FROM deleted;
END
ceci :
ON dbo.Contact
AFTER UPDATE
AS BEGIN
IF @@ROWCOUNT = 0 RETURN
IF UPDATE(Name)
INSERT INTO ContactHistory (Id, Name)
SELECT d.Id, d.Name
FROM deleted d
JOIN inserted i ON d.Id = i.Id
WHERE d.Name i.Name;
END
Ici nous ajoutons aussi, en toute première ligne (c’est important), l’instruction
pour tester si le déclencheur est appelé pour une bonne raison. En effet, une instruction comme celle-ci:
SET Name = UPPER(Name)
WHERE 1 = 0;
n’affecterait aucune ligne, mais appellerait pourtant le déclencheur, qui lancerait des requêtes pour rien. Le test sur @@ROWCOUNT permet de sortir immédiatement du trigger si aucune ligne n’a été affectée.