Zasadniczo użytkownik chce śledzić/kontrolować zmiany w tabeli, zachowując niewielki rozmiar podstawowej tabeli.
Istnieje kilka sposobów rozwiązania tego problemu. Wady i zalety każdego sposobu omówiono poniżej.
1 - Audyt tabeli z wyzwalaczami.
Jeśli szukasz audytu tabeli (wstawia, aktualizuje, usuwa), spójrz na mój sposób na odzyskanie niechcianych transakcji - SQL Sobota slajdów w/kod - http://craftydba.com/?page_id=880. Spust, który wypełnia tabelę kontroli, może przechowywać informacje z wielu tabel, jeśli tak zdecydujesz, ponieważ dane są zapisywane jako XML. W związku z tym można usunąć działanie, jeśli to konieczne, analizując plik XML. Śledzi, kto i co spowodowało zmianę.
Opcjonalnie można mieć tabelę kontroli w jej 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 randki ewidencji
Jeśli nie zamierzamy oczyścić dane z tabeli audytu, dlaczego nie zaznaczyć wiersz jako usunięte, ale zachować ją na zawsze? Wiele systemów, takich jak ludzie miękcy, używa efektywnych randek, aby pokazać, czy rekord nie jest już aktywny. W świecie BI nazywa się to tabelą wymiarową typu 2 (wolno zmieniające się wymiary). Zobacz artykuł instytutu 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ę końcową równą zero.
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 - przechwytywania zmian danych (Feature Enterprise).
Micorsoft SQL Server 2008 wprowadził funkcję przechwytywania zmian. Podczas śledzenia zmian danych (CDC) za pomocą czytnika LOG po tym fakcie, , brakuje informacji o tym, 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 tabele przechwytywania danych zmian. 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 - Change Tracking Feature (wszystkie wersje).
Micorsoft SQL Server 2008 wprowadził funkcję śledzenia zmian. W przeciwieństwie do CDC, ma wszystkie wersje; Jednak zawiera szereg 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 ramka synchronizacji.
http://msdn.microsoft.com/en-us/library/bb933874.aspx http://msdn.microsoft.com/en-us/library/bb933994.aspx http://technet.microsoft.com/en-us/library/bb934145(v=sql.105).aspx
przeciwieństwie do CDC, można określić, jak długo ostatnie zmiany w bazie danych przed usunięte. Ponadto, wstawienia i usunięcia nie rejestrują danych. Aktualizacje rejestrują tylko to, które pole zostało zmienione.
Ponieważ synchronizujesz źródło serwera SQL z innym obiektem docelowym, działa to dobrze. Nie nadaje się do audytu, jeśli nie piszesz okresowej pracy, aby dowiedzieć się o zmianach.
Wciąż będziesz musiał przechowywać te informacje gdzieś.
Description:
Enable change tracking
Cons:
Not a good auditing solution
Pierwsze trzy rozwiązania będą służyć do kontroli. Podoba mi się pierwsze rozwiązanie, ponieważ używam go w dużym stopniu w moim środowisku.
poważaniem
John
Code Snippet od prezentacji (Database 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];
** Spójrz & dotyk tabeli audytu **
Czy rozważałeś użycie wyzwalaczy w 'Tabela-A', aby utworzyć dla ciebie wiersze' Tabela-A-Historia'? Upewnij się, że ustawiono je jako ostatnie ([sp_settriggerorder] (http://msdn.microsoft.com/en-us/library/ms186762.aspx)). – HABO
Nie, nie mam. Przyjrzę się wyzwalaczom. Dzięki. – Mausimo