Introduktion
Har du någonsin ställts inför en situation där du behöver göra ändringar i en lagrad procedur eller en vy mycket snabbt? Jag har, väldigt ofta, särskilt på genomförandestadiet. Tyvärr kan ett versionskontrollsystem inte hjälpa i detta fall. Ändå, hur kunde jag förstå att något har ändrats, och när?
Den här artikeln beskriver en möjlig lösning för automatisk datainsamling om databasschemaändringar i MS SQL Server. Som vanligt kommer jag gärna höra eventuella alternativa lösningar.
Lösning
- Skapa två tabeller:den första kommer att vara för varje databas, den andra – för alla databaser:
USE [DATABASE_NAME] GO SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO CREATE TABLE [srv].[ddl_log]( [DDL_Log_GUID] [uniqueidentifier] NOT NULL, [PostTime] [datetime] NOT NULL, [DB_Login] [nvarchar](255) NULL, [DB_User] [nvarchar](255) NULL, [Event] [nvarchar](255) NULL, [TSQL] [nvarchar](max) NULL, CONSTRAINT [PK_ddl_log] PRIMARY KEY CLUSTERED ( [DDL_Log_GUID] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] GO ALTER TABLE [srv].[ddl_log] ADD CONSTRAINT [DF_ddl_log_DDL_Log_GUID] DEFAULT (newid()) FOR [DDL_Log_GUID] GO USE [DATABASE_NAME] GO SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO CREATE TABLE [srv].[ddl_log_all]( [DDL_Log_GUID] [uniqueidentifier] NOT NULL, [Server_Name] [nvarchar](255) NOT NULL, [DB_Name] [nvarchar](255) NOT NULL, [PostTime] [datetime] NOT NULL, [DB_Login] [nvarchar](255) NULL, [DB_User] [nvarchar](255) NULL, [Event] [nvarchar](255) NULL, [TSQL] [nvarchar](max) NULL, [InsertUTCDate] [datetime] NOT NULL, CONSTRAINT [PK_ddl_log_all] PRIMARY KEY CLUSTERED ( [DDL_Log_GUID] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] GO ALTER TABLE [srv].[ddl_log_all] ADD CONSTRAINT [DF_ddl_log_all_DDL_Log_GUID] DEFAULT (newid()) FOR [DDL_Log_GUID] GO ALTER TABLE [srv].[ddl_log_all] ADD CONSTRAINT [DF_ddl_log_all_InsertUTCDate] DEFAULT (getutcdate()) FOR [InsertUTCDate] GO
- Skapa en DDL-utlösare för en databas som samlar in schemaändringar:
USE [DATABASE_NAME] GO SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO CREATE TRIGGER [SchemaLog] ON DATABASE --ALL SERVER FOR DDL_DATABASE_LEVEL_EVENTS AS SET NOCOUNT ON; SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; DECLARE @data XML begin try if(CURRENT_USER<>'NT AUTHORITY\NETWORK SERVICE' and SYSTEM_USER<>'NT AUTHORITY\NETWORK SERVICE') begin SET @data = EVENTDATA(); INSERT srv.ddl_log( PostTime, DB_Login, DB_User, Event, TSQL ) select GETUTCDATE(), CONVERT(nvarchar(255), SYSTEM_USER), CONVERT(nvarchar(255), CURRENT_USER), @data.value('(/EVENT_INSTANCE/EventType)[1]', 'nvarchar(255)'), @data.value('(/EVENT_INSTANCE/TSQLCommand)[1]', 'nvarchar(max)') where @data.value('(/EVENT_INSTANCE/EventType)[1]', 'nvarchar(255)') not in('UPDATE_STATISTICS', 'ALTER_INDEX') and @data.value('(/EVENT_INSTANCE/TSQLCommand)[1]', 'nvarchar(max)') not like '%Msmerge%'; --there is no need in tracking changes of replication objects end end try begin catch end catch GO SET ANSI_NULLS OFF GO SET QUOTED_IDENTIFIER OFF GO ENABLE TRIGGER [SchemaLog] ON DATABASE GO
Jag rekommenderar att du justerar ett filter och inte gör en DDL-trigger för hela servern. Det är värdelöst, eftersom du kommer att få mycket onödig information. I det här fallet är det bättre att skapa en trigger för varje databas.
Du måste dock stänga av denna trigger under komplicerade operationer, till exempel replikering. Men senare kommer du att kunna slå på den igen.
- Du måste samla information i en enda tabell. Du kan till exempel göra det med en uppgift i SQL Server Agent en gång i veckan.
- Det är möjligt att samla allt i en tabell på ett annat sätt som du föredrar.
Dessutom rekommenderar jag att du tar bort gamla data.
Resultat
I den här artikeln har jag analyserat ett exempel på att implementera en automatisk datainsamling om förändringar av databasscheman i MS SQL Server. Det låter oss ta reda på vad och när som har ändrats, och, om nödvändigt, att återställa dem. I allmänhet kan den här lösningen vara till hjälp vid implementeringsstadiet där det finns många misstag och när vi har olika versioner av databaser kopior som ska analyseras. Om du vill ta reda på en anledning till ändringar kan du göra det genom att hämta en revisionshistorik.
Läs även:
Automatisk datainsamling om slutförda uppgifter i MS SQL Server