Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

Automatische Datenerfassung von Datenbankschemaänderungen in MS SQL Server

Einführung

Sind Sie schon einmal in eine Situation geraten, in der Sie sehr schnell Änderungen an einer gespeicherten Prozedur oder einer Ansicht vornehmen mussten? Das habe ich sehr oft, besonders in der Umsetzungsphase. Ein Versionskontrollsystem kann hier leider nicht helfen. Wie kann ich trotzdem verstehen, dass etwas geändert wurde und wann?

Dieser Artikel beschreibt eine mögliche Lösung für die automatische Datenerfassung über Datenbankschemaänderungen in MS SQL Server. Wie üblich freue ich mich über alternative Lösungen.

Lösung

  1. Erstellen Sie zwei Tabellen:die erste für jede Datenbank, die zweite für alle Datenbanken:
    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
  2. Erstellen Sie einen DDL-Trigger für eine Datenbank, die Schemaänderungen sammelt:
    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

Ich empfehle, einen Filter einzustellen und keinen DDL-Trigger für den gesamten Server zu machen. Es ist nutzlos, da Sie viele unnötige Informationen erhalten. In diesem Fall ist es besser, für jede Datenbank einen Trigger zu erstellen.
Bei komplizierten Vorgängen, z. B. Replikation, müssen Sie diesen Trigger jedoch deaktivieren. Aber später können Sie es wieder einschalten.

  1. Sie müssen Informationen in einer einzigen Tabelle sammeln. Beispielsweise können Sie dies einmal pro Woche mit einer Aufgabe im SQL Server Agent tun.
  2. Es ist möglich, alles auf eine andere Art und Weise, die Sie bevorzugen, in einer Tabelle zu sammeln.

Außerdem empfehle ich, alte Daten zu löschen.

Ergebnis

In diesem Artikel habe ich ein Beispiel für die Implementierung einer automatischen Datenerfassung über Änderungen von Datenbankschemata in MS SQL Server analysiert. Es ermöglicht uns, herauszufinden, was und wann geändert wurde, und sie bei Bedarf rückgängig zu machen. Im Allgemeinen kann diese Lösung in der Implementierungsphase hilfreich sein, wenn es viele Fehler gibt und wenn wir verschiedene Versionen von Datenbankkopien haben, die analysiert werden müssen. Wenn Sie den Grund für Änderungen herausfinden möchten, können Sie dies tun, indem Sie eine Änderungshistorie abrufen.

Lesen Sie auch:

Automatische Datenerfassung über abgeschlossene Aufgaben in MS SQL Server