2016-03-25 11 views
0

他のDB管理者が作成したSQL Serverインスタンスの変更を確認するにはSQLスクリプトがありますか?その変更が電子メールで通知されます。はいの場合は、スクリプトとそれを適用するためのすべての手順を教えてください。私はSQL Server 2012を使用しています。SQL Serverインスタンスの変更を確認するスクリプト?

答えて

1

すべてのスキーマの変更(プロシージャ、関数、テーブル定義など)をキャッチするには、DDL triggerを使用します。これは暗号化されていないすべてのオブジェクトで有効ですが、他の管理者は無効にしてはいけません。

このようなトリガを書き、変更を永続化する方法の詳細は、hereを参照してください。

[後の編集]

私は、開発環境で、このような監査を作成した覚えて、私は指示された記事に基づいてカスタムバージョンを提供することができます。通常の情報の他に、私はまた、古いオブジェクトテキストと新しいオブジェクトテキストとの間に「距離」を入れて、変化の大きさについての基本的な考え方を持っています。

1)テーブル定義:

IF NOT EXISTS(SELECT * FROM dbo.DDLEvents) 
BEGIN 
    INSERT INTO dbo.DDLEvents 
    (EventType, DatabaseName, SchemaName, ObjectName, LoginName, ObjectDefinition) 
    SELECT 'CREATE_PROCEDURE', DB_NAME(), OBJECT_SCHEMA_NAME([object_id]), OBJECT_NAME([object_id]), 'SYSTEM', OBJECT_DEFINITION([object_id]) 
    FROM sys.procedures; 

    INSERT INTO dbo.DDLEvents 
    (EventType, DatabaseName, SchemaName, ObjectName, LoginName, ObjectDefinition) 
    SELECT 'CREATE_VIEW', DB_NAME(), OBJECT_SCHEMA_NAME([object_id]), OBJECT_NAME([object_id]), 'SYSTEM', OBJECT_DEFINITION([object_id]) 
    FROM sys.views; 

    INSERT INTO dbo.DDLEvents 
    (EventType, DatabaseName, SchemaName, ObjectName, LoginName, ObjectDefinition) 
    SELECT 'CREATE_FUNCTION', DB_NAME(), OBJECT_SCHEMA_NAME([object_id]), OBJECT_NAME([object_id]), 'SYSTEM', OBJECT_DEFINITION([object_id]) 
    FROM sys.objects 
    -- scalar, inline table-valued, table-valued 
    WHERE type IN ('FN', 'IF', 'TF') 
END 
go 

3)距離関数(CLR):既存のオブジェクトの

IF OBJECT_ID('dbo.DDLEvents', 'U') IS NULL BEGIN CREATE TABLE dbo.DDLEvents ( EventId INT IDENTITY(1, 1) NOT NULL, EventDate DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, EventType NVARCHAR(64), EventXML XML, DatabaseName NVARCHAR(255), SchemaName NVARCHAR(255), ObjectName NVARCHAR(255), HostName VARCHAR(128), IPAddress VARCHAR(32), ProgramName NVARCHAR(255), LoginName NVARCHAR(255), ObjectDefinition NVARCHAR(MAX), LastObjDefinition NVARCHAR(MAX), Diff INT -- edit distance between last and current object version (gives an idea of how much was changed in the object) ); create index IDX_DDLEvents_Object ON DDLEvents (SchemaName, ObjectName) END go 

2)初期テキスト

[Microsoft.SqlServer.Server.SqlFunction(IsDeterministic = true, IsPrecise = false)] 
public static int Levenshtein(SqlString S1, SqlString S2) 
{ 
    if (S1.IsNull) 
     S1 = new SqlString(""); 

    if (S2.IsNull) 
     S2 = new SqlString(""); 

    int maxLen = 4096; 

    // keeping only the first part of the string (performance reasons) 
    String SC1 = S1.Value.ToUpper(); 
    String SC2 = S2.Value.ToUpper(); 

    if (SC1.Length > maxLen) 
     SC1 = SC1.Remove(maxLen); 
    if (SC2.Length > maxLen) 
     SC2 = SC2.Remove(maxLen); 

    int n = SC1.Length; 
    int m = SC2.Length; 

    short[,] d = new short[n + 1, m + 1]; 
    int cost = 0; 

    if (n + m == 0) 
    { 
     return 0; 
    } 
    else if (n == 0) 
    { 
     return 0; 
    } 
    else if (m == 0) 
    { 
     return 0; 
    } 

    for (short i = 0; i <= n; i++) 
     d[i, 0] = i; 

    for (short j = 0; j <= m; j++) 
     d[0, j] = j; 

    for (int i = 1; i <= n; i++) 
    { 
     for (int j = 1; j <= m; j++) 
     { 
      if (SC1[i - 1] == SC2[j - 1]) 
       cost = 0; 
      else 
       cost = 1; 

      d[i, j] = (short) System.Math.Min(System.Math.Min(d[i - 1, j] + 1, d[i, j - 1] + 1), d[i - 1, j - 1] + cost); 
     } 
    } 

    // double percentage = System.Math.Round((1.0 - ((double)d[n, m]/(double)System.Math.Max(n, m))) * 100.0, 2); 
    // return percentage; 
    return d[n, m]; 
} 

4)DDLトリガの定義

if not exists (select * from sys.triggers where name = 'DDL_Audit_Trigger') 
    exec ('create trigger DDL_Audit_Trigger ON DATABASE FOR CREATE_PROCEDURE AS BEGIN PRINT 1; END') 
GO 

ALTER TRIGGER [DDL_Audit_Trigger] 
ON DATABASE 
FOR 
    CREATE_ASSEMBLY, ALTER_ASSEMBLY, DROP_ASSEMBLY, 
    CREATE_PROCEDURE, ALTER_PROCEDURE, DROP_PROCEDURE, 
    CREATE_FUNCTION, ALTER_FUNCTION, DROP_FUNCTION, 
    CREATE_INDEX, ALTER_INDEX, DROP_INDEX, 
    CREATE_VIEW, ALTER_VIEW, DROP_VIEW, 
    CREATE_ROLE, ALTER_ROLE, DROP_ROLE, 
    CREATE_SCHEMA, ALTER_SCHEMA, DROP_SCHEMA, 
    CREATE_TABLE, ALTER_TABLE, DROP_TABLE, 
    CREATE_TYPE, DROP_TYPE, 
    CREATE_USER, ALTER_USER, DROP_USER, 
    CREATE_TRIGGER, ALTER_TRIGGER, DROP_TRIGGER, 
    RENAME 
AS 
BEGIN 
    SET NOCOUNT ON; 

    BEGIN TRY 
     DECLARE @EventData XML = EVENTDATA(); 
     DECLARE @ip VARCHAR(32) = (SELECT client_net_address FROM sys.dm_exec_connections WHERE session_id = @@SPID); 
     DECLARE @ObjectSchema NVARCHAR(255) = @EventData.value('(/EVENT_INSTANCE/SchemaName)[1]', 'NVARCHAR(255)') 
     DECLARE @ObjectName NVARCHAR(255) = @EventData.value('(/EVENT_INSTANCE/ObjectName)[1]', 'NVARCHAR(255)') 
     -- DECLARE @ObjectFullName NVARCHAR(255) = @ObjectSchema + '.' + @ObjectName 
     DECLARE @CommandText NVARCHAR(MAX) = @EventData.value('(/EVENT_INSTANCE/TSQLCommand/CommandText)[1]', 'NVARCHAR(MAX)') 

     DECLARE @LastObjectChange DATETIME = (SELECT TOP 1 EventDate FROM dbo.DDLEvents where SchemaName = @ObjectSchema and ObjectName = @ObjectName ORDER BY EventDate DESC) 
     DECLARE @LastObjectDefinition NVARCHAR(MAX) = (SELECT TOP 1 ObjectDefinition FROM dbo.DDLEvents where SchemaName = @ObjectSchema and ObjectName = @ObjectName and EventDate = @LastObjectChange ORDER BY EventDate DESC) 

     INSERT INTO dbo.DDLEvents 
     (EventType, 
      EventXML, DatabaseName, 
      SchemaName, ObjectName, 
      HostName, IPAddress, ProgramName, LoginName, 
      ObjectDefinition, LastObjDefinition, Diff 
     ) 
     SELECT @EventData.value('(/EVENT_INSTANCE/EventType)[1]', 'NVARCHAR(100)'), 
      @EventData, DB_NAME(), 
      @ObjectSchema, @ObjectName, 
      HOST_NAME(), @ip, PROGRAM_NAME(), SUSER_SNAME(), 
      @CommandText, @LastObjectDefinition, dbo.Levenshtein(@CommandText, @LastObjectDefinition); 
    END TRY 
    BEGIN CATCH 
     INSERT INTO dbo.DDLEventsLog (Error) 
     SELECT ERROR_MESSAGE() 
    END CATCH 
END 
GO 
関連する問題