En un desencadenante, ¿cómo verificar si no han cambiado los campos?
-
16-10-2019 - |
Pregunta
Si recibimos una declaración de actualización que no verifica si el valor ha cambiado en la cláusula WHERE, ¿cuáles son las diferentes formas de ignorar esa actualización dentro de un desencadenante?
Sé que podemos hacer una comparación de cada campo individual (manejando el lado de Isnull también), pero donde es una tabla que tiene más de 50 campos, ¿hay una forma más rápida/más fácil de hacerlo?
Nota: Esto podría usarse para reducir IO/ruido en los registros de auditoría, etc.
EJEMPLO
Para una tabla de:
CREATE TABLE myTest
(ID int NOT NULL IDENTITY(1,1),
Field1 varchar(10) NULL,
Field2 varchar(20) NULL)
con un disparador de actualización posterior que contiene:
INSERT INTO myTestAudit (ID, Field1, Field2, DateTimeUpdate)
SELECT ID, Field1, Field2, getDate()
FROM inserted
con valores iniciales:
INSERT INTO myTest (Field1, Field2)
SELECT 'a', 'b' UNION ALL
SELECT 'a', 'c'
Ahora ejecute una actualización:
UPDATE myTest set Field2 = 'b' WHERE Field1 = 'a'
Solución
Para traer filas donde al menos un valor ha cambiado, puede usar
SELECT /*TODO: Column List*/
FROM INSERTED I
JOIN DELETED D
ON I.ID = D.ID
AND EXISTS (SELECT I.*
EXCEPT
SELECT D.*)
Otros consejos
Pon esto como la primera línea en tu gatillo:
-- Exit trigger if no data was actually modified
IF (@@ROWCOUNT = 0) return
Hago esto en todos mis desencadenantes de auditoría. Es corto y al grano, definitivamente reduce la E/S desperdiciada.
Actualización: Lo siento, leí mal tu pregunta. Pensé que había preguntado cómo salir del desencadenante si no han cambiado datos.