Въведение
Случвало ли ви се е да се сблъскате със ситуация, когато трябва да направите промени в съхранена процедура или изглед много бързо? Имам, много често, особено на етапа на изпълнение. За съжаление, системата за контрол на версиите не може да помогне в този случай. И все пак, как мога да разбера, че нещо е променено и кога?
Тази статия описва възможно решение за автоматично събиране на данни за промени в схемата на базата данни в MS SQL Server. Както обикновено, ще се радвам да чуя всякакви алтернативни решения.
Решение
- Създайте две таблици:първата ще бъде за всяка база данни, втората – за всички бази данни:
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
- Създайте DDL-тригер за база данни, която събира промени в схемата:
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
Препоръчвам да коригирате филтър и да не правите DDL-тригер за целия сървър. Безполезно е, тъй като ще получите много ненужна информация. В този случай е по-добре да създадете тригер за всяка база данни.
Въпреки това, ще трябва да изключите този тригер по време на сложни операции, например репликация. Но по-късно ще можете да го включите отново.
- Ще трябва да съберете информация в една таблица. Например, можете да го направите със задача в SQL Server Agent веднъж седмично.
- Възможно е да съберете всичко в една таблица по друг начин, който предпочитате.
Освен това препоръчвам да изтриете стари данни.
Резултат
В тази статия анализирах пример за внедряване на автоматично събиране на данни за промени в схемите на бази данни в MS SQL Server. Позволява ни да разберем какво и кога е променено и, ако е необходимо, да ги върнем. Като цяло, това решение може да бъде полезно на етапа на внедряване, където има много грешки и когато имаме различни версии на бази данни, копия за анализиране. Ако искате да разберете причината за промените, можете да го направите, като извлечете хронология на ревизиите.
Прочетете също:
Автоматично събиране на данни за изпълнени задачи в MS SQL Server