Si bien estoy totalmente de acuerdo en que el control de fuente es la forma correcta de hacer esto, también entiendo que no todos los entornos son lo suficientemente disciplinados como para depender solo de eso (si es que lo hacen), y que a veces los cambios deben realizarse directamente para mantener la aplicación corriendo, guardar un cliente, ¿qué tienes?
Puede usar un desencadenador DDL para mantener todas las revisiones en una tabla en una base de datos separada (y, por supuesto, hacer una copia de seguridad de esa base de datos con frecuencia). Suponiendo que tiene una base de datos de utilidades:
USE Utility;
GO
CREATE TABLE dbo.ProcedureChanges
(
EventDate DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
EventType NVARCHAR(100),
EventDDL NVARCHAR(MAX),
DatabaseName NVARCHAR(255),
SchemaName NVARCHAR(255),
ObjectName NVARCHAR(255),
HostName NVARCHAR(255),
IPAddress VARCHAR(32),
ProgramName NVARCHAR(255),
LoginName NVARCHAR(255)
);
Ahora en su base de datos, primero tomemos lo que llamaremos "control inicial": la versión actual de los procedimientos almacenados:
USE YourDB;
GO
INSERT Utility.dbo.ProcedureChanges
(
EventType,
EventDDL,
DatabaseName,
SchemaName,
ObjectName
)
SELECT
N'Initial control',
OBJECT_DEFINITION([object_id]),
DB_NAME(),
OBJECT_SCHEMA_NAME([object_id]),
OBJECT_NAME([object_id])
FROM
sys.procedures;
Ahora para capturar los cambios posteriores, agregue un desencadenador DDL a la base de datos:
USE YourDB;
GO
CREATE TRIGGER CaptureStoredProcedureChanges
ON DATABASE
FOR CREATE_PROCEDURE, ALTER_PROCEDURE, DROP_PROCEDURE
AS
BEGIN
SET NOCOUNT ON;
DECLARE @EventData XML = EVENTDATA(), @ip VARCHAR(32);
SELECT @ip = client_net_address
FROM sys.dm_exec_connections
WHERE session_id = @@SPID;
INSERT Utility.dbo.ProcedureChanges
(
EventType,
EventDDL,
SchemaName,
ObjectName,
DatabaseName,
HostName,
IPAddress,
ProgramName,
LoginName
)
SELECT
@EventData.value('(/EVENT_INSTANCE/EventType)[1]', 'NVARCHAR(100)'),
@EventData.value('(/EVENT_INSTANCE/TSQLCommand)[1]', 'NVARCHAR(MAX)'),
@EventData.value('(/EVENT_INSTANCE/SchemaName)[1]', 'NVARCHAR(255)'),
@EventData.value('(/EVENT_INSTANCE/ObjectName)[1]', 'NVARCHAR(255)'),
DB_NAME(), HOST_NAME(), @ip, PROGRAM_NAME(), SUSER_SNAME();
END
GO
Con el tiempo, será fácil ver y comparar los cambios en los procedimientos, ver cómo se agregan nuevos procedimientos al sistema, ver cómo se eliminan los procedimientos y tener una buena idea de con quién hablar sobre cualquiera de estos eventos.
Más información aquí:
http://www.mssqltips.com/sqlservertip/2085/sql-server-ddl-triggers-to-track-all-database-changes/