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 IFcondició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 20para columna 3y 5, y valor 1para columna 9porque se establece en el primer bit del segundo byte. Si cambio la declaración OR, ¿verificará si las columnas 3y / 5o columna 9se actualizan?
¿Cómo se puede aplicar la ORlógica en el contexto de un byte?
sql-server
t-sql
trigger
gotqn
fuente
fuente


SETlista o si los valores realmente cambiaron? AmbosUPDATEyCOLUMNS_UPDATED()solo te digo lo primero. Si desea saber si los valores realmente cambiaron, deberá hacer una comparación adecuada deinsertedydeleted.SUBSTRINGpara 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().SEToUPDATE, 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 utilizarHASHBYTESen lugar de 1 .El siguiente ejemplo utiliza un
AFTER UPDATEactivador para retener un historial de modificaciones realizadas en laTriggerTesttabla solo si alguno de los valores en las columnasData1oData2cambia. SiData3cambia, 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 TABLEinstrucción.Esta demostración inserta filas en la tabla de historial que quizás no deberían insertarse. Las filas han tenido su
Data1columna actualizada para algunas filas, y laData3columna 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 hanData1actualizado, lo que forma parte de laCOLUMNS_UPDATED()comparación, todas las filas vistas por el desencadenador se insertan en laTriggerHistorytabla. Si esto es "incorrecto" para su escenario, es posible que deba manejar cada fila por separado, utilizando un cursor.La
TriggerResulttabla 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 laData3columna actualizada; sin embargo, desde la una fila en el lote habíaData1actualizado, todas las filas se insertan en laTriggerResulttabla.Alternativamente, como @AaronBertrand y @srutzky señalaron, se puede realizar una comparación de los datos reales de los
insertedydeletedvirtuales tablas. Dado que la estructura de ambas tablas es idéntica, puede usar unaEXCEPTclá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
HASHBYTESen su lugar". es engañosa. Es cierto queHASHBYTESes 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 lasINSERTEDyDELETEDmesas, y usando un_BIN2cotejo si se trata de datos de cadena. Comparar hashes solo da certeza para las diferencias.