Question

Je travaille sur un projet où je dois synchroniser les données de notre système à un système externe. Ce que je veux réaliser, c'est d'envoyer périodiquement les éléments (lignes) modifiés à partir d'une requête personnalisée. Cette requête ressemble à ceci (mais avec de nombreuses autres colonnes):

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

Je veux éviter de comparer chaque champ à un entre les synchronisations. Je suis venu avec l'idée que je pouvais générer un hachage pour chaque ligne à partir de ma requête, et comparer cela avec le hachage de la synchronisation précédente, qui ne renverra que les lignes modifiées. Je suis conscient du Somme de contrôle Fonction, mais il est très sujet à la collision et peut parfois manquer des changements. Cependant, j'aime la façon dont je pouvais faire une table temporaire et utiliser CHECKSUM(*), ce qui facilite la maintenance (sans avoir à ajouter des champs dans la requête et à la somme de contrôle):

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;

je suis conscient de Hashbytes Fonction (qui prend en charge SHA1, MD5, qui sont moins sujettes aux collisions), mais il accepte uniquement Varchar ou Varbinary, pas une liste de colonnes ou * comme le sommet de contrôle. Devoir lancer / convertir chaque colonne de la requête est une douleur dans le ... et ouvre la porte aux erreurs (oubliez d'inclure un nouveau champ par exemple)

J'ai aussi remarqué Modifier la capture des données et changer de suivi Caractéristiques de SQL Server, mais elles semblent toutes compliquées et exagérées pour ce que je fais.

Donc ma question: existe-t-il une autre méthode pour générer un hachage à partir d'une requête ou d'une table temporaire qui répond à mes critères?

Sinon, y a-t-il un autre moyen d'atteindre ce type de travail (pour synchroniser les différences d'une requête)

Était-ce utile?

La solution

J'ai trouvé un moyen de faire exactement ce que je voulais, grâce au FOR XML Clause:

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;
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top