Pergunta

Estou trabalhando em um projeto em que preciso sincronizar dados do nosso sistema com um sistema externo. O que eu quero alcançar é enviar periodicamente apenas itens alterados (linhas) de uma consulta personalizada. Esta consulta se parece com isso (mas com muitas outras colunas):

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

Quero evitar comparar todos os campos um a um entre sincronizações. Eu tive a ideia de que eu poderia gerar um hash para cada linha a partir da minha consulta e comparar isso com o hash da sincronização anterior, que retornará apenas as linhas alteradas. Estou ciente do Soma de verificação Função, mas é muito propensa a colisões e às vezes pode perder as mudanças. No entanto, eu gosto da maneira como eu poderia simplesmente fazer uma mesa temporária e usar CHECKSUM(*), o que facilita a manutenção (não precisando adicionar campos na consulta e na soma de cheque):

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;

Estou ciente Hashbytes Função (que suporta SHA1, MD5, que é menos propensa a colisões), mas aceita apenas Varchar ou varbinária, não uma lista de colunas ou * a maneira como a soma de verificação. Ter que lançar/converter todas as colunas da consulta é uma dor no ... e abre a porta para erros (esqueça de incluir um novo campo, por exemplo)

Eu também notei Alterar captura de dados e alteração de rastreamento Recursos do SQL Server, mas todos parecem complicados e exagerados pelo que estou fazendo.

Então, minha pergunta: existe outro método para gerar um hash a partir de uma consulta ou uma tabela de temperatura que atenda aos meus critérios?

Caso contrário, existe outra maneira de alcançar esse tipo de trabalho (para sincronizar as diferenças de uma consulta)

Foi útil?

Solução

Encontrei uma maneira de fazer exatamente o que eu queria, graças ao 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 em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top