Conseils et formations : vos deux atouts pour réussir !
Accueil > DBA > Messages > Suivi des modifications avec SQLServer2008
Suivi des modifications avec SQLServer2008

Introduction :

Il s'agit de surveiller une ou des tables d'une base de données, et de garder la trace des différentes évolutions des données.

Mise en œuvre :

Il faut d'abord activer la surveillance au niveau de la base de données :

 

    -- Mise en oeuvre du suivi des modifications

    ALTER DATABASE DemoSuiviModifications

    SET CHANGE_TRACKING = ON

    (CHANGE_RETENTION = 2 DAYS, AUTO_CLEANUP = ON)

Ensuite, pour chacune des tables à surveiller, on fait aussi une activation :

    -- Création d'une table à suivre

    create table Personnel (IdPersonnel int identity (1,1) not null primary key,

    Nom nvarchar(50) not null,

    Salaire money not null)

    go

 
    -- Quelques lignes

    insert into Personnel (Nom,Salaire) values ('Dominique',50000),('Isabelle',40000),('David',30000)

    go

 

    -- Et allons y pour le suivi :

    ALTER TABLE Personnel ENABLE CHANGE_TRACKING WITH (TRACK_COLUMNS_UPDATED = ON)

    go

 


Vous noterez que j'ai utilisé l'insert multiple de 2008.

 

Quelles sont les tables ainsi surveillées ?

 

    -- Qui est surveillé ?

    select OBJECT_NAME(object_id) as TableSurveillée from sys.change_tracking_tables

    go

   

La fonction indispensable pour cette surveillance s'appelle CHANGETABLE, en voici la syntaxe :

 

--CHANGETABLE
--  ( {
--       NomTableEspionnee , DepuisNoVersion
--        | VERSION table , { ( NomColonnePk [ , ...n ] ) , ( ValeurColonnePk [ , ...n ] ) }
--  --} )
--        --[ AS ] AliasDeTable [ ( AliasDeColonne [ ,...n ] ) ]
--
--

 

Il y a donc deux modes d'exécution :

  • Récupérer les modifications depuis une version donnée
  • Récupérer les valeurs actuelles des versions de lignes


Voici ce que donne la 1ère :

 

    select * from CHANGETABLE (CHANGES Personnel,0) as Ev


Normal : je n'ai fait aucune mise à jour sur la table, un petit update va arranger cela :

 

    update Personnel set salaire = 35000 where IdPersonnel = 3

    go

 

 

 

Bon on apprend que l'on a modifié une ligne : elle a le NoPersonnel = 3, et les colonnes 0x0000000003000000 ont été modifiées.

On peut heureusement décrypter ce masque par :

 

    -- Obtenir l'ID unique de la table

    select OBJECT_ID('Personnel')

 

 

    -- puis l'ID d'une colonne

    select COLUMNPROPERTY(OBJECT_ID('Personnel'), 'Salaire', 'ColumnId')

   

 

    -- Et un masque des colonnes modifiées

    select CHANGE_TRACKING_IS_COLUMN_IN_MASK ( COLUMNPROPERTY(OBJECT_ID('Personnel'), 'Salaire', 'ColumnId') ,SYS_CHANGE_COLUMNS ),*

    from CHANGETABLE (CHANGES Personnel,1) as Ev

 

    -- A-t-on modifié les salaires ?

    select * from CHANGETABLE (CHANGES Personnel,NULL) as Ev

    where CHANGE_TRACKING_IS_COLUMN_IN_MASK ( COLUMNPROPERTY(OBJECT_ID('Personnel'), 'Salaire', 'ColumnId') ,SYS_CHANGE_COLUMNS ) = 1

 



Ce qui nous permet de chercher si on a modifié les salaires depuis la version la plus petite (null = en fait celle disponible dans la durée de rétention paramétrée au début de ce post).

Bon, mais où sont les valeurs des colonnes modifiées ?
Hélas ! 3 fois hélas ! Elles ne sont stockées nulle part, et la seule chose que l'on puisse savoir est que cette ligne a été insérée, supprimée ou mise à jour....

Ce choix a très certainement été fait pour des raisons de performances, ce qui part d'un bon sentiment, mais ne permettra que d'envoyer ce qui a été modifié depuis (avec la dernière version) , par exemple pour faire une interface d'export.


Où sont stockées les évolutions ?

Dans la même base de données, ainsi que le montre :

    -- Où sont les données de suivi ?

    select OBJECT_NAME(parent_object_id),* from sys.internal_tables

    where internal_type = 209




C'est dans une table interne (donc non visible) que cela se passe.


Voici la deuxième écriture de la fonction :

 

    -- Lignes avec leur version

    SELECT Personnel.IdPersonnel, Personnel.Nom, Personnel.Salaire,

        Evolutions.SYS_CHANGE_VERSION, Evolutions.SYS_CHANGE_CONTEXT

    FROM Personnel

    CROSS APPLY CHANGETABLE

        (VERSION Personnel, (IdPersonnel), (Personnel.IdPersonnel)) AS Evolutions;



Mais, comme dit plus haut, on sait que cela a bougé, qu'est-ce qui a bougé, mais pas la valeur qui a bougé.



Enfin, une autre fonction qui peut être utile :

    -- La dernière version utilisée

    select CHANGE_TRACKING_CURRENT_VERSION();

 

   

    -- Ce numéro est-il global à la base ?

    create table Tva (IdTva int primary key not null,Taux decimal(6,3))

    go

    insert into Tva (IdTva,Taux) values (1,18.6),(2,33.3),(3,0)

    go

    ALTER TABLE Tva ENABLE CHANGE_TRACKING WITH (TRACK_COLUMNS_UPDATED = ON)

    go

 

    update Tva set Taux = 22.6 where IdTva = 1;

    select CHANGE_TRACKING_CURRENT_VERSION();



Effectivement, le tracking est global à la base de données.



Enfin, il est facile de le désactiver par :

    -- On peut désactiver le suivi

    ALTER TABLE Personnel DISABLE CHANGE_TRACKING;

 

Conclusion :

Cette fonctionnalité peut être utile dans le cas d'un progiciel, où je me vois assez mal ajouter des colonnes d'estampillage, style rowversion.

Mais, dans le cas d'un développement spécifique, l'apport est trop faible pour justifier son emploi...

Mais ma boule de cristal me dit que Microsoft ne s'arrêtera pas là.... à suivre donc.....

Commentaires

Aucun commentaire sur ce message.