Tengo una tabla con 42 columnas y un disparador que debería hacer algunas cosas cuando se actualizan 38 de estas columnas. Entonces, necesito omitir la lógica si se cambian las 4 columnas restantes.
Puedo usar la función UPDATE () y crear una gran IF
condición, pero prefiero hacer algo más corto. Con COLUMNS_UPDATED, ¿puedo verificar si se actualizan todas las columnas?
Por ejemplo, verificar si las columnas 3, 5 y 9 están actualizadas:
IF
(
(SUBSTRING(COLUMNS_UPDATED(),1,1) & 20 = 20)
AND
(SUBSTRING(COLUMNS_UPDATED(),2,1) & 1 = 1)
)
PRINT 'Columns 3, 5 and 9 updated';
Entonces, valor 20
para columna 3
y 5
, y valor 1
para columna 9
porque se establece en el primer bit del segundo byte. Si cambio la declaración OR
, ¿verificará si las columnas 3
y / 5
o columna 9
se actualizan?
¿Cómo se puede aplicar la OR
lógica en el contexto de un byte?
sql-server
t-sql
trigger
gotqn
fuente
fuente
SET
lista o si los valores realmente cambiaron? AmbosUPDATE
yCOLUMNS_UPDATED()
solo te digo lo primero. Si desea saber si los valores realmente cambiaron, deberá hacer una comparación adecuada deinserted
ydeleted
.SUBSTRING
para dividir el valor del formulario devueltoCOLUMNS_UPDATED()
, debe usar una comparación bit a bit, como se muestra en la documentación . Tenga en cuenta que si cambia la tabla de alguna manera, cambiará el orden de los valores devueltos porCOLUMNS_UPDATED()
.SET
oUPDATE
, es posible que desee ver el uso deCHECKSUM()
oBINARY_CHECKSUM()
, o inclusoHASHBYTES()
sobre las columnas en cuestión.Respuestas:
Puede utilizar
CHECKSUM()
una metodología bastante simple para comparar valores reales para ver si se modificaron.CHECKSUM()
generará una suma de comprobación en una lista de valores pasados, de los cuales el número y el tipo son indeterminados. Cuidado, hay una pequeña posibilidad de comparar sumas de comprobación como esta que dará como resultado falsos negativos. Si no puede hacer frente a eso, se puede utilizarHASHBYTES
en lugar de 1 .El siguiente ejemplo utiliza un
AFTER UPDATE
activador para retener un historial de modificaciones realizadas en laTriggerTest
tabla solo si alguno de los valores en las columnasData1
oData2
cambia. SiData3
cambia, no se toman medidas.Si insiste en usar la función COLUMNS_UPDATED () , no debe codificar el valor ordinal de las columnas en cuestión, ya que la definición de la tabla puede cambiar, lo que puede invalidar los valores codificados. Puede calcular cuál debería ser el valor en tiempo de ejecución utilizando las tablas del sistema. Tenga en cuenta que la
COLUMNS_UPDATED()
función devuelve verdadero para el bit de columna dado si la columna se modifica en CUALQUIER fila afectada por laUPDATE TABLE
instrucción.Esta demostración inserta filas en la tabla de historial que quizás no deberían insertarse. Las filas han tenido su
Data1
columna actualizada para algunas filas, y laData3
columna ha sido actualizada para algunas filas. Como se trata de una declaración única, todas las filas se procesan con una sola pasada a través del desencadenador. Como algunas filas se hanData1
actualizado, lo que forma parte de laCOLUMNS_UPDATED()
comparación, todas las filas vistas por el desencadenador se insertan en laTriggerHistory
tabla. Si esto es "incorrecto" para su escenario, es posible que deba manejar cada fila por separado, utilizando un cursor.La
TriggerResult
tabla ahora tiene algunas filas potencialmente engañosas que parecen no pertenecer, ya que no muestran absolutamente ningún cambio (en las dos columnas de esa tabla). En el segundo conjunto de filas en la imagen a continuación, TriggerTestID 7 es el único que parece haber sido modificado. Las otras filas solo tenían laData3
columna actualizada; sin embargo, desde la una fila en el lote habíaData1
actualizado, todas las filas se insertan en laTriggerResult
tabla.Alternativamente, como @AaronBertrand y @srutzky señalaron, se puede realizar una comparación de los datos reales de los
inserted
ydeleted
virtuales tablas. Dado que la estructura de ambas tablas es idéntica, puede usar unaEXCEPT
cláusula en el disparador para capturar filas donde las columnas precisas que le interesan han cambiado:1: consulte /programming/297960/hash-collision-what-are-the-chances para ver una discusión sobre la pequeña posibilidad de que el cálculo HASHBYTES también pueda provocar colisiones. Preshing también tiene un análisis decente de este problema.
fuente
HASHBYTES
en su lugar". es engañosa. Es cierto queHASHBYTES
es menos probable que tenga falsos negativos queCHECKSUM
(la probabilidad varía según el tamaño del algoritmo utilizado), pero no se puede descartar. Cualquier función de hashing siempre tendrá el potencial de tener colisiones, ya que es muy probable que se reduzca la información. La única manera de estar seguro de no hay cambios es comparar lasINSERTED
yDELETED
mesas, y usando un_BIN2
cotejo si se trata de datos de cadena. Comparar hashes solo da certeza para las diferencias.