Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

Comment stocker des enregistrements historiques dans une table d'historique dans SQL Server

Fondamentalement, vous cherchez à suivre/vérifier les modifications apportées à une table tout en gardant la table principale de petite taille.

Il existe plusieurs façons de résoudre ce problème. Les inconvénients et les avantages de chaque méthode sont discutés ci-dessous.

1 - Audit de la table avec déclencheurs.

Si vous cherchez à auditer la table (insertions, mises à jour, suppressions), regardez comment éviter les transactions indésirables - Diaporama SQL Saturday w/code - http://craftydba.com/?page_id=880. Le déclencheur qui remplit la table d'audit peut contenir des informations provenant de plusieurs tables, si vous le souhaitez, car les données sont enregistrées au format XML. Par conséquent, vous pouvez annuler la suppression d'une action si nécessaire en analysant le XML. Il suit qui et ce qui a fait le changement.

En option, vous pouvez avoir la table d'audit sur son propre groupe de fichiers.

Description:
    Table Triggers For (Insert, Update, Delete)
    Active table has current records.
    Audit (history) table for non-active records.

Pros:
    Active table has smaller # of records.
    Index in active table is small.
    Change is quickly reported in audit table.
    Tells you what change was made (ins, del, upd)

Cons:
    Have to join two tables to do historical reporting.
    Does not track schema changes.

2 - Dating efficace des enregistrements

Si vous n'allez jamais purger les données de la table d'audit, pourquoi ne pas marquer la ligne comme supprimée mais la conserver pour toujours ? De nombreux systèmes tels que People Soft utilisent une datation efficace pour indiquer si un enregistrement n'est plus actif. Dans le monde de la BI, cela s'appelle un tableau dimensionnel de type 2 (dimensions à évolution lente). Voir l'article de l'institut des entrepôts de données. http://www.bidw.org/datawarehousing/scd-type-2/ Chaque enregistrement a une date de début et de fin.

Tous les enregistrements actifs ont une date de fin nulle.

Description:
    Table Triggers For (Insert, Update, Delete)
    Main table has both active and historical records.

Pros:
    Historical reporting is easy.
    Change is quickly shown in main table.

Cons:
    Main table has a large # of records.
    Index of main table is large.
    Both active & history records in same filegroup.
    Does not tell you what change was made (ins, del, upd)
    Does not track schema changes.

3 - Modifier la capture de données (fonctionnalité d'entreprise).

Micorsoft SQL Server 2008 a introduit la fonctionnalité de capture de données modifiées. Bien que cela suive le changement de données (CDC) à l'aide d'un lecteur LOG après coup, il manque des choses comme qui et quoi a fait le changement. Détails MSDN - http://technet.microsoft.com/en-us/library/bb522489(v=sql.105).aspx

Cette solution dépend des travaux CDC en cours d'exécution. Tout problème avec l'agent sql entraînera des retards dans l'affichage des données.

Voir modifier les tables de capture de données.http://technet.microsoft.com/en-us/library/bb500353(v=sql.105).aspx

Description:
    Enable change data capture

Pros:
    Do not need to add triggers or tables to capture data.
    Tells you what change was made (ins, del, upd) the _$operation field in 
    <user_defined_table_CT>
    Tracks schema changes.    

Cons:
    Only available in enterprise version.
    Since it reads the log after the fact, time delay in data showing up.
    The CDC tables do not track who or what made the change.
    Disabling CDC removes the tables (not nice)!
    Need to decode and use the _$update_mask to figure out what columns changed.

4 - Fonctionnalité de suivi des modifications (toutes les versions).

Micorsoft SQL Server 2008 a introduit la fonctionnalité de suivi des modifications. Contrairement à CDC, il est livré avec toutes les versions; Cependant, il est livré avec un tas de fonctions TSQL que vous devez appeler pour comprendre ce qui s'est passé.

Il a été conçu dans le but de synchroniser une source de données avec SQL Server via une application. Il existe tout un cadre de travail de synchronisation sur TechNet.

http://msdn.microsoft.com/en-us/library/bb933874.aspxhttp://msdn.microsoft.com/en-us/library/bb933994.aspxhttp://technet.microsoft.com/en-us/ bibliothèque/bb934145(v=sql.105).aspx

Contrairement à CDC, vous spécifiez combien de temps les modifications durent dans la base de données avant d'être purgées. De plus, les insertions et les suppressions n'enregistrent pas de données. Les mises à jour enregistrent uniquement les champs modifiés.

Puisque vous synchronisez la source du serveur SQL avec une autre cible, cela fonctionne bien. Ce n'est pas bon pour l'audit, sauf si vous écrivez un travail périodique pour comprendre les changements.

Vous devrez toujours stocker ces informations quelque part.

Description:
    Enable change tracking

Cons:
    Not a good auditing solution

Les trois premières solutions fonctionneront pour votre audit. J'aime la première solution car je l'utilise beaucoup dans mon environnement.

Cordialement

Jean

Extrait de code de la présentation (base de données Autos)

-- 
-- 7 - Auditing data changes (table for DML trigger)
-- 


-- Delete existing table
IF OBJECT_ID('[AUDIT].[LOG_TABLE_CHANGES]') IS NOT NULL 
  DROP TABLE [AUDIT].[LOG_TABLE_CHANGES]
GO


-- Add the table
CREATE TABLE [AUDIT].[LOG_TABLE_CHANGES]
(
  [CHG_ID] [numeric](18, 0) IDENTITY(1,1) NOT NULL,
  [CHG_DATE] [datetime] NOT NULL,
  [CHG_TYPE] [varchar](20) NOT NULL,
  [CHG_BY] [nvarchar](256) NOT NULL,
  [APP_NAME] [nvarchar](128) NOT NULL,
  [HOST_NAME] [nvarchar](128) NOT NULL,
  [SCHEMA_NAME] [sysname] NOT NULL,
  [OBJECT_NAME] [sysname] NOT NULL,
  [XML_RECSET] [xml] NULL,
 CONSTRAINT [PK_LTC_CHG_ID] PRIMARY KEY CLUSTERED ([CHG_ID] ASC)
) ON [PRIMARY]
GO

-- Add defaults for key information
ALTER TABLE [AUDIT].[LOG_TABLE_CHANGES] ADD CONSTRAINT [DF_LTC_CHG_DATE] DEFAULT (getdate()) FOR [CHG_DATE];
ALTER TABLE [AUDIT].[LOG_TABLE_CHANGES] ADD CONSTRAINT [DF_LTC_CHG_TYPE] DEFAULT ('') FOR [CHG_TYPE];
ALTER TABLE [AUDIT].[LOG_TABLE_CHANGES] ADD CONSTRAINT [DF_LTC_CHG_BY] DEFAULT (coalesce(suser_sname(),'?')) FOR [CHG_BY];
ALTER TABLE [AUDIT].[LOG_TABLE_CHANGES] ADD CONSTRAINT [DF_LTC_APP_NAME] DEFAULT (coalesce(app_name(),'?')) FOR [APP_NAME];
ALTER TABLE [AUDIT].[LOG_TABLE_CHANGES] ADD CONSTRAINT [DF_LTC_HOST_NAME] DEFAULT (coalesce(host_name(),'?')) FOR [HOST_NAME];
GO



--
--  8 - Make DML trigger to capture changes
--


-- Delete existing trigger
IF OBJECT_ID('[ACTIVE].[TRG_FLUID_DATA]') IS NOT NULL 
  DROP TRIGGER [ACTIVE].[TRG_FLUID_DATA]
GO

-- Add trigger to log all changes
CREATE TRIGGER [ACTIVE].[TRG_FLUID_DATA] ON [ACTIVE].[CARS_BY_COUNTRY]
  FOR INSERT, UPDATE, DELETE AS
BEGIN

  -- Detect inserts
  IF EXISTS (select * from inserted) AND NOT EXISTS (select * from deleted)
  BEGIN
    INSERT [AUDIT].[LOG_TABLE_CHANGES] ([CHG_TYPE], [SCHEMA_NAME], [OBJECT_NAME], [XML_RECSET])
    SELECT 'INSERT', '[ACTIVE]', '[CARS_BY_COUNTRY]', (SELECT * FROM inserted as Record for xml auto, elements , root('RecordSet'), type)
    RETURN;
  END

  -- Detect deletes
  IF EXISTS (select * from deleted) AND NOT EXISTS (select * from inserted)
  BEGIN
    INSERT [AUDIT].[LOG_TABLE_CHANGES] ([CHG_TYPE], [SCHEMA_NAME], [OBJECT_NAME], [XML_RECSET])
    SELECT 'DELETE', '[ACTIVE]', '[CARS_BY_COUNTRY]', (SELECT * FROM deleted as Record for xml auto, elements , root('RecordSet'), type)
    RETURN;
  END

  -- Update inserts
  IF EXISTS (select * from inserted) AND EXISTS (select * from deleted)
  BEGIN
    INSERT [AUDIT].[LOG_TABLE_CHANGES] ([CHG_TYPE], [SCHEMA_NAME], [OBJECT_NAME], [XML_RECSET])
    SELECT 'UPDATE', '[ACTIVE]', '[CARS_BY_COUNTRY]', (SELECT * FROM deleted as Record for xml auto, elements , root('RecordSet'), type)
    RETURN;
  END

END;
GO



--
--  9 - Test DML trigger by updating, deleting and inserting data
--

-- Execute an update
UPDATE [ACTIVE].[CARS_BY_COUNTRY]
SET COUNTRY_NAME = 'Czech Republic'
WHERE COUNTRY_ID = 8
GO

-- Remove all data
DELETE FROM [ACTIVE].[CARS_BY_COUNTRY];
GO

-- Execute the load
EXECUTE [ACTIVE].[USP_LOAD_CARS_BY_COUNTRY];
GO 

-- Show the audit trail
SELECT * FROM [AUDIT].[LOG_TABLE_CHANGES]
GO

-- Disable the trigger
ALTER TABLE [ACTIVE].[CARS_BY_COUNTRY] DISABLE TRIGGER [TRG_FLUID_DATA];

** Look &Feel du tableau d'audit **