Inleiding
Heeft u wel eens te maken gehad met een situatie waarin u zeer snel wijzigingen moet aanbrengen in een opgeslagen procedure of een weergave? Ik heb dat heel vaak, vooral in de implementatiefase. Helaas kan een versiebeheersysteem in dit geval niet helpen. Maar hoe kan ik begrijpen dat er iets is gewijzigd, en wanneer?
Dit artikel beschrijft een mogelijke oplossing voor het automatisch verzamelen van gegevens over wijzigingen in het databaseschema in MS SQL Server. Zoals gewoonlijk hoor ik graag alternatieve oplossingen.
Oplossing
- Maak twee tabellen:de eerste is voor elke database, de tweede - voor alle databases:
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
- Maak een DDL-trigger voor een database die schemawijzigingen verzamelt:
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
Ik raad aan om een filter aan te passen en geen DDL-trigger voor de hele server te maken. Het is nutteloos, omdat je veel onnodige informatie krijgt. In dit geval is het beter om voor elke database een trigger aan te maken.
U zult deze trigger echter moeten uitschakelen tijdens gecompliceerde bewerkingen, bijvoorbeeld replicatie. Maar later kunt u het weer aanzetten.
- U moet informatie in één tabel verzamelen. U kunt het bijvoorbeeld één keer per week doen met een taak in de SQL Server Agent.
- Het is mogelijk om alles in één tabel te verzamelen op een andere manier die u verkiest.
Daarnaast raad ik aan om oude gegevens te verwijderen.
Resultaat
In dit artikel heb ik een voorbeeld geanalyseerd van het implementeren van een automatische gegevensverzameling over wijzigingen van databaseschema's in MS SQL Server. Het stelt ons in staat om te achterhalen wat en wanneer is gewijzigd en, indien nodig, terug te draaien. Over het algemeen kan deze oplossing nuttig zijn in de implementatiefase waar er veel fouten zijn en wanneer we verschillende versies van databasekopieën moeten analyseren. Als u een reden voor wijzigingen wilt achterhalen, kunt u dit doen door een revisiegeschiedenis op te halen.
Lees ook:
Automatische gegevensverzameling over voltooide taken in MS SQL Server