Sqlserver
 sql >> Baza danych >  >> RDS >> Sqlserver

Jak przechowywać rekordy historyczne w tabeli historii w SQL Server

Zasadniczo chcesz śledzić/kontrolować zmiany w tabeli, zachowując mały rozmiar tabeli głównej.

Istnieje kilka sposobów rozwiązania tego problemu. Wady i zalety każdego sposobu omówiono poniżej.

1 - Kontrola tabeli z wyzwalaczami.

Jeśli chcesz przeprowadzić audyt tabeli (wstawienia, aktualizacje, usunięcia), spójrz na mój sposób na odzyskanie niechcianych transakcji - SQL Saturday slide deck z kodem - http://craftydba.com/?page_id=880. Wyzwalacz, który wypełnia tabelę inspekcji, może przechowywać informacje z wielu tabel, jeśli wybierzesz, ponieważ dane są zapisywane w formacie XML. Dlatego w razie potrzeby można cofnąć usunięcie akcji, analizując kod XML. Śledzi, kto i co wprowadził zmianę.

Opcjonalnie możesz mieć tabelę audytu we własnej grupie plików.

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 - Skuteczne datowanie rekordów

Jeśli nigdy nie zamierzasz usuwać danych z tabeli audytu, dlaczego nie oznaczyć wiersza jako usunięty, ale zachować go na zawsze? Wiele systemów, takich jak ludzie, używa skutecznych randek, aby pokazać, czy rekord nie jest już aktywny. W świecie BI nazywa się to tabelą wymiarową typu 2 (wymiary powoli zmieniające się). Zobacz artykuł o instytucie hurtowni danych. http://www.bidw.org/datawarehousing/scd-type-2/ Każdy rekord ma datę rozpoczęcia i zakończenia.

Wszystkie aktywne rekordy mają datę zakończenia równą 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 - Zmień przechwytywanie danych (funkcja Enterprise).

Micorsoft SQL Server 2008 wprowadził funkcję przechwytywania danych zmian. Chociaż śledzi zmiany danych (CDC) za pomocą czytnika LOG po fakcie, brakuje w nim takich rzeczy, jak kto i co dokonał zmiany. Szczegóły MSDN — http://technet.microsoft.com/en-us/library/bb522489(v=sql.105).aspx

To rozwiązanie zależy od uruchomionych zadań CDC. Wszelkie problemy z agentem sql spowodują opóźnienia w wyświetlaniu danych.

Zobacz zmiany w tabelach przechwytywania danych.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 — Funkcja śledzenia zmian (wszystkie wersje).

Micorsoft SQL Server 2008 wprowadził funkcję śledzenia zmian. W przeciwieństwie do CDC, jest dostarczany ze wszystkimi wersjami; Jednak zawiera kilka funkcji TSQL, które musisz wywołać, aby dowiedzieć się, co się stało.

Został zaprojektowany w celu synchronizacji jednego źródła danych z serwerem SQL za pośrednictwem aplikacji. W TechNet działa cała rama synchronizacji.

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

W przeciwieństwie do CDC, określasz, jak długo trwają zmiany w bazie danych, zanim zostaną usunięte. Ponadto wstawienia i usunięcia nie rejestrują danych. Aktualizacje rejestrują tylko to, które pole uległo zmianie.

Ponieważ synchronizujesz źródło serwera SQL z innym celem, działa to dobrze. Nie jest to dobre do audytu, chyba że piszesz okresowe zadanie w celu ustalenia zmian.

Nadal będziesz musiał gdzieś przechowywać te informacje.

Description:
    Enable change tracking

Cons:
    Not a good auditing solution

Pierwsze trzy rozwiązania sprawdzą się podczas audytu. Podoba mi się pierwsze rozwiązanie, ponieważ intensywnie korzystam z niego w swoim środowisku.

Z poważaniem

Jan

Fragment kodu z prezentacji (baza danych 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];

** Wygląd i styl tabeli audytu **



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Konwertuj „datetime” na „datetimeoffset” w SQL Server (przykłady T-SQL)

  2. DATEDIFF() zwraca nieprawidłowe wyniki w programie SQL Server? Przeczytaj to.

  3. Znak ucieczki w SQL Server

  4. Jak wykonać procedurę składowaną MS SQL Server w java/jsp, zwracając dane tabeli?

  5. Jak używać OBJECT_ID() na obiektach między bazami danych w SQL Server