Introducción
¿Alguna vez se ha enfrentado a una situación en la que necesita realizar cambios en un procedimiento almacenado o en una vista muy rápidamente? Tengo, muy a menudo, especialmente en la etapa de implementación. Desafortunadamente, un sistema de control de versiones no puede ayudar en este caso. Aún así, ¿cómo podría entender que algo ha sido modificado y cuándo?
Este artículo describe una posible solución para la recopilación automática de datos sobre los cambios en el esquema de la base de datos en MS SQL Server. Como de costumbre, estaré encantado de escuchar cualquier solución alternativa.
Solución
- Cree dos tablas:la primera será para cada base de datos, la segunda, para todas las bases de datos:
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
- Cree un activador DDL para una base de datos que recopile los cambios de esquema:
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
Recomiendo ajustar un filtro y no hacer un disparador DDL para todo el servidor. Es inútil, ya que obtendrá mucha información innecesaria. En este caso, es mejor crear un activador para cada base de datos.
Sin embargo, deberá desactivar este activador durante operaciones complicadas, por ejemplo, la replicación. Pero más tarde, podrá volver a encenderlo.
- Deberá recopilar información en una sola tabla. Por ejemplo, puede hacerlo con una tarea en el Agente SQL Server una vez a la semana.
- Es posible reunir todo en una mesa de otra manera que prefiera.
Además, recomiendo eliminar los datos antiguos.
Resultado
En este artículo, analicé un ejemplo de implementación de una recopilación automática de datos sobre cambios de esquemas de bases de datos en MS SQL Server. Nos permite saber qué y cuándo se han modificado y, en caso necesario, revertirlas. En general, esta solución puede ser útil en la etapa de implementación donde hay muchos errores y cuando tenemos diferentes versiones de copias de bases de datos para analizar. Si desea averiguar el motivo de los cambios, puede hacerlo recuperando un historial de revisiones.
Lea también:
Recopilación automática de datos sobre tareas completadas en MS SQL Server