fonction UPDATE() dans un déclencheur

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 :

USE tempdb;
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 :

CREATE TRIGGER atr_u_Contact
ON dbo.Contact
AFTER UPDATE
AS BEGIN
    IF UPDATE(Name)
        INSERT INTO ContactHistory (Id, Name)
        SELECT Id, Name
        FROM deleted;
END

ceci :

CREATE TRIGGER atr_u_Contact
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

IF @@ROWCOUNT = 0 RETURN

pour tester si le déclencheur est appelé pour une bonne raison. En effet, une instruction comme celle-ci:

UPDATE dbo.Contact
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.

Laisser un commentaire