Pregunta

Estoy trabajando en un proyecto donde necesito sincronizar los datos de nuestro sistema a un sistema externo. Lo que quiero lograr es enviar periódicamente los elementos cambiados (filas) desde una consulta personalizada. Esta consulta se ve así (pero con muchas más columnas):

SELECT T1.field1,
    T1.field2,
    T1.field2,
    T1.field3,
    CASE WHEN T1.field4 = 'some-value' THEN 1 ELSE 0 END,
    T2.field1,
    T3.field1,
    T4.field1
FROM T1
INNER JOIN T2 ON T2.pk = T2.fk
INNER JOIN T3 ON T3.pk = T2.fk
INNER JOIN T4 ON T4.pk = T2.fk

Quiero evitar tener que comparar cada campo uno a uno entre sincronizaciones. Vine con la idea de que podría generar un hash para cada fila de mi consulta, y comparar esto con el hash de la sincronización anterior, que solo devolverá las filas cambiadas. Soy consciente del Suma de verificación función, pero es muy propensa a colisiones y a veces puede perder los cambios. Sin embargo, me gusta la forma en que podría hacer una mesa de temperatura y usar CHECKSUM(*), lo que facilita el mantenimiento (no tener que agregar campos en la consulta y en la suma de verificación):

SELECT T1.field1,
    T1.field2,
    T1.field2,
    T1.field3,
    CASE WHEN T1.field4 = 'some-value' THEN 1 ELSE 0 END,
    T2.field1,
    T3.field1,
    T4.field1
INTO #tmp
FROM T1
INNER JOIN T2 ON T2.pk = T2.fk
INNER JOIN T3 ON T3.pk = T2.fk
INNER JOIN T4 ON T4.pk = T2.fk;

-- get all columns from the query, plus a hash of the row
SELECT *, CHECKSUM(*)
FROM #tmp;

Estoy consciente de Hashbytes función (que admite Sha1, MD5, que son menos propensas a las colisiones), pero solo acepta Varchar o Varbinary, no una lista de columnas o * la forma en que la suma de verificación lo hace. Tener que lanzar/convertir cada columna de la consulta es un dolor en ... y abre la puerta a los errores (olvídate de incluir un nuevo campo, por ejemplo)

Yo también noté Cambiar la captura de datos y el seguimiento de cambios Características de SQL Server, pero todos parecen complicados y exagerados por lo que estoy haciendo.

Entonces mi pregunta: ¿hay otro método para generar un hash a partir de una consulta o una mesa de temperatura que cumpla con mis criterios?

Si no, ¿hay una otra forma de lograr este tipo de trabajo (sincronizar las diferencias de una consulta)

¿Fue útil?

Solución

Encontré una manera de hacer exactamente lo que quería, gracias a la FOR XML Cláusula:

SELECT T1.field1,
    T1.field2,
    T1.field2,
    T1.field3,
    CASE WHEN T1.field4 = 'some-value' THEN 1 ELSE 0 END,
    T2.field1,
    T3.field1,
    T4.field1
INTO #tmp
FROM T1
INNER JOIN T2 ON T2.pk = T2.fk
INNER JOIN T3 ON T3.pk = T2.fk
INNER JOIN T4 ON T4.pk = T2.fk;

-- get all columns from the query, plus a hash of the row (converted in an hex string)
SELECT T.*, CONVERT(VARCHAR(100), HASHBYTES('sha1', (SELECT T.* FOR XML RAW)), 2) AS sHash
FROM #tmp AS T;
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top