Anche se sono pienamente d'accordo sul fatto che il controllo del codice sorgente sia il modo giusto per farlo, capisco anche che non tutti gli ambienti sono abbastanza disciplinati da fare affidamento solo su questo (se non del tutto) e che a volte le modifiche devono essere apportate direttamente per mantenere l'app correre, salvare un cliente, cosa hai.
È possibile utilizzare un trigger DDL per conservare tutte le revisioni in una tabella in un database separato (e ovviamente eseguire il backup di quel database frequentemente). Supponendo di avere un database di utilità:
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)
);
Ora nel tuo database, prima prendiamo quello che chiameremo "controllo iniziale" - la versione corrente delle procedure memorizzate:
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;
Ora per acquisire le modifiche successive, aggiungi un trigger DDL al database:
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 il passare del tempo diventerà facile vedere e confrontare le modifiche alle procedure, guardare le nuove procedure aggiunte al sistema, vedere le procedure cadere e avere una buona idea di chi parlare di uno di questi eventi.
Maggiori informazioni qui:
http://www.mssqltips.com/sqlservertip/2085/sql-server-ddl-triggers-to-track-all-database-changes/