Sqlserver
 sql >> Database >  >> RDS >> Sqlserver

Come archiviare i record cronologici in una tabella cronologica in SQL Server

Fondamentalmente stai cercando di tracciare/controllare le modifiche a una tabella mantenendo le dimensioni della tabella principale di piccole dimensioni.

Esistono diversi modi per risolvere questo problema. I contro e i pro di ogni modo sono discussi di seguito.

1 - Auditing della tabella con trigger.

Se stai cercando di controllare la tabella (inserimenti, aggiornamenti, eliminazioni), guarda il mio come annullare le transazioni indesiderate - SQL Saturday slide deck w/code - http://craftydba.com/?page_id=880. Il trigger che riempie la tabella di controllo può contenere informazioni da più tabelle, se lo desideri, poiché i dati vengono salvati come XML. Pertanto, è possibile annullare l'eliminazione di un'azione, se necessario, analizzando l'XML. Tiene traccia di chi e cosa ha apportato la modifica.

Facoltativamente, puoi avere la tabella di controllo nel proprio gruppo di file.

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 - Datazione efficace dei record

Se non hai mai intenzione di eliminare i dati dalla tabella di controllo, perché non contrassegnare la riga come eliminata ma conservarla per sempre? Molti sistemi come le persone usano la datazione efficace per mostrare se un record non è più attivo. Nel mondo BI questo è chiamato tabella dimensionale di tipo 2 (dimensioni che cambiano lentamente). Vedi l'articolo dell'istituto di data warehouse. http://www.bidw.org/datawarehousing/scd-type-2/ Ogni record ha una data di inizio e di fine.

Tutti i record attivi hanno una data di fine nulla.

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 - Modifica acquisizione dati (funzione aziendale).

Micorsoft SQL Server 2008 ha introdotto la funzionalità di acquisizione dei dati di modifica. Sebbene questo tenga traccia della modifica dei dati (CDC) utilizzando un lettore di LOG dopo il fatto, mancano cose come chi e cosa ha apportato la modifica. Dettagli MSDN - http://technet.microsoft.com/en-us/library/bb522489(v=sql.105).aspx

Questa soluzione dipende dai lavori CDC in esecuzione. Eventuali problemi con l'agente sql causeranno ritardi nella visualizzazione dei dati.

Vedere modifiche alle tabelle di acquisizione dei dati.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 - Funzione di monitoraggio delle modifiche (tutte le versioni).

Micorsoft SQL Server 2008 ha introdotto la funzionalità di rilevamento delle modifiche. A differenza di CDC, viene fornito con tutte le versioni; Tuttavia, viene fornito con un sacco di funzioni TSQL che devi chiamare per capire cosa è successo.

È stato progettato allo scopo di sincronizzare un'origine dati con il server SQL tramite un'applicazione. C'è un intero frame di sincronizzazione su TechNet.

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

A differenza di CDC, si specifica la durata delle modifiche nel database prima di essere eliminate. Inoltre, gli inserimenti e le eliminazioni non registrano i dati. Gli aggiornamenti registrano solo il campo modificato.

Dal momento che stai sincronizzando l'origine del server SQL con un'altra destinazione, funziona correttamente. Non è utile per il controllo a meno che tu non scriva un lavoro periodico per capire le modifiche.

Dovrai comunque memorizzare queste informazioni da qualche parte.

Description:
    Enable change tracking

Cons:
    Not a good auditing solution

Le prime tre soluzioni funzioneranno per il tuo auditing. Mi piace la prima soluzione poiché la uso ampiamente nel mio ambiente.

Cordiali saluti

Giovanni

Snippet di codice dalla presentazione (database di auto)

-- 
-- 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 della tabella di audit **