sql >> Database >  >> RDS >> Sqlserver

Historische records opslaan in een geschiedenistabel in SQL Server

In principe wil je wijzigingen aan een tafel bijhouden/controleren terwijl je de primaire tafel klein houdt.

Er zijn verschillende manieren om dit probleem op te lossen. De voor- en nadelen van elke manier worden hieronder besproken.

1 - Controle van de tabel met triggers.

Als u de tabel wilt controleren (invoegingen, updates, verwijderingen), kijk dan naar mijn hoe u ongewenste transacties kunt voorkomen - SQL Saturday-diadeck met code - http://craftydba.com/?page_id=880. De trigger die de controletabel vult, kan desgewenst informatie uit meerdere tabellen bevatten, aangezien de gegevens worden opgeslagen als XML. Daarom kunt u de verwijdering van een actie indien nodig ongedaan maken door de XML te ontleden. Het houdt bij wie en wat de wijziging heeft aangebracht.

Optioneel kunt u de controletabel op zijn eigen bestandsgroep hebben.

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 - Effectieve datering van de records

Als u de gegevens nooit uit de controletabel gaat wissen, waarom markeert u de rij dan niet als verwijderd, maar bewaart u deze voor altijd? Veel systemen zoals people soft gebruiken effectieve dating om te laten zien of een record niet langer actief is. In de BI-wereld wordt dit een type 2 dimensionale tabel genoemd (langzaam veranderende dimensies). Zie het artikel van het datawarehouseinstituut. http://www.bidw.org/datawarehousing/scd-type-2/ Elk record heeft een begin- en einddatum.

Alle actieve records hebben een einddatum van null.

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 - Gegevens vastleggen wijzigen (bedrijfsfunctie).

Micorsoft SQL Server 2008 introduceerde de functie voor het vastleggen van wijzigingsgegevens. Hoewel dit achteraf gegevensverandering (CDC) volgt met behulp van een LOG-lezer, ontbreekt het aan zaken als wie en wat de wijziging heeft aangebracht. MSDN-details - http://technet.microsoft.com/en-us/library/bb522489(v=sql.105).aspx

Deze oplossing is afhankelijk van de uitgevoerde CDC-taken. Eventuele problemen met sql-agent veroorzaken vertragingen bij het verschijnen van gegevens.

Zie tabellen voor het vastleggen van gegevens wijzigen.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 - Traceerfunctie wijzigen (alle versies).

Micorsoft SQL Server 2008 introduceerde de functie voor het bijhouden van wijzigingen. In tegenstelling tot CDC wordt het geleverd met alle versies; Het wordt echter geleverd met een aantal TSQL-functies die u moet aanroepen om erachter te komen wat er is gebeurd.

Het is ontworpen om één gegevensbron via een applicatie te synchroniseren met SQL-server. Er is een heel synchronisatieframewerk op 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

In tegenstelling tot CDC specificeert u hoe lang wijzigingen in de database blijven voordat ze worden verwijderd. Invoegingen en verwijderingen registreren ook geen gegevens. Updates registreren alleen welk veld is gewijzigd.

Aangezien u de SQL-serverbron synchroniseert met een ander doel, werkt dit prima. Het is niet goed voor controle, tenzij u een periodieke taak schrijft om wijzigingen te achterhalen.

Je zult die informatie nog wel ergens moeten opslaan.

Description:
    Enable change tracking

Cons:
    Not a good auditing solution

De eerste drie oplossingen zullen werken voor uw auditing. Ik hou van de eerste oplossing omdat ik deze veel in mijn omgeving gebruik.

Met vriendelijke groet

Jan

Codefragment uit presentatie (Autos-database)

-- 
-- 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 van audittafel **



  1. Interessante dingen over IN PLAATS VAN triggers

  2. Oracle's containers voor J2EE (OC4J) in R12

  3. android.database.sqlite.SQLiteException:in de buurt van s:syntaxisfout (code 1):,

  4. Bindende parameters voor Oracle Dynamic SQL