SQL Server не отслеживает конкретные изменения таблиц. Если вам нужен или нужен этот уровень детализации, вам необходимо создать триггер DDL (введенный в SQL Server 2005), который может захватывать определенные события или даже классы событий и записывать эти изменения в созданную таблицу истории.
DDL Триггеры являются «после» триггерами; нет опции «вместо». Однако, если вы хотите запретить действие, вы можете просто выдать ROLLBACK
и отменить то, что произошло.
страницы MSDN для DDL Triggers имеет много полезной информацию о том, как ловушке либо конкретные события (т.е. ALTER TABLE
) и с помощью функции EVENTDATA
, которая возвращает XML, чтобы получить особенности, какие события произвели на спусковой крючок, в том числе точного SQL-запрос, который был выполнен. Фактически, на странице MSDN для Use the EVENTDATA Function даже есть простые примеры создания триггера DDL для записи операторов ALTER TABLE
(в разделе « ALTER TABLE и ALTER DATABASE Events») и создания триггера DDL для захвата событий в таблицу журналов (в раздел «Пример»). Поскольку все команды ALTER TABLE
будут запускать этот триггер, вам необходимо проанализировать, какие из них относятся к тому, что вы ищете. И, возможно, теперь, когда вы знаете, что это вариант, требуется больше, чем просто добавлять столбцы (например, удаление столбцов, изменение типа данных и/или NULLability и т. Д.).
Следует отметить, что вы можете создать триггер DLL ON ALL SERVER
для событий с областью базы данных, таких как ALTER_TABLE
.
Если вы хотите увидеть структуру XML для любого события или класса событий, перейдите к:
http://schemas.microsoft.com/sqlserver/2006/11/eventdata/
и нажмите на кнопку «Текущая версия:» ссылку. Если вы хотите увидеть конкретное событие или класс событий, просто выполните поиск (обычно Control-F в браузере) имени события, которое будет использоваться в предложении триггера «FOR» (включая подчеркивание). Ниже приводится схема для ALTER_TABLE
события:
<xs:complexType name="EVENT_INSTANCE_ALTER_TABLE">
<xs:sequence>
<!-- Basic Envelope -->
<xs:element name="EventType" type="SSWNAMEType"/>
<xs:element name="PostTime" type="xs:string"/>
<xs:element name="SPID" type="xs:int"/>
<!-- Server Scoped DDL -->
<xs:element name="ServerName" type="PathType"/>
<xs:element name="LoginName" type="SSWNAMEType"/>
<!-- DB Scoped DDL -->
<xs:element name="UserName" type="SSWNAMEType"/>
<!-- Main Body -->
<xs:element name="DatabaseName" type="SSWNAMEType"/>
<xs:element name="SchemaName" type="SSWNAMEType"/>
<xs:element name="ObjectName" type="SSWNAMEType"/>
<xs:element name="ObjectType" type="SSWNAMEType"/>
<xs:element name="Parameters" type="EventTag_Parameters" minOccurs="0"/>
<xs:element name="AlterTableActionList" type="AlterTableActionListType" minOccurs="0"/>
<xs:element name="TSQLCommand" type="EventTag_TSQLCommand"/>
</xs:sequence>
</xs:complexType>
Вот очень простой тест, чтобы увидеть, как это работает, и что в результате EventData XML выглядит следующим образом:
IF (EXISTS(
SELECT *
FROM sys.server_triggers sst
WHERE sst.name = N'CaptureAlterTable'
))
BEGIN
DROP TRIGGER CaptureAlterTable ON ALL SERVER;
END;
GO
CREATE TRIGGER CaptureAlterTable
ON ALL SERVER -- capture events for all databases
FOR ALTER_TABLE -- only capture ALTER TABLE events
AS
PRINT CONVERT(NVARCHAR(MAX), EVENTDATA()); -- Display in "Messages" tab in SSMS
GO
Сначала мы создаем простой, реальная таблица в tempdb (эти события не фиксируются для временных таблиц):
USE [tempdb];
CREATE TABLE dbo.MyAlterTest (Col2 INT NULL);
Затем мы добавим столбец. Мы делаем это из другой базы данных, чтобы убедиться, что XML захватывает базу данных, где объект существует, а не текущая база данных. Обратите внимание на обложку слов alTeR Table tempDB.dbo.MyALTERTest ... DATEcreated
для сравнения с тем, что есть в XML.
USE [master];
alTeR Table tempDB.dbo.MyALTERTest ADD DATEcreated DATETIME NOT NULL;
Вы должны увидеть следующее на вкладке «Сообщения» (комментарии, добавленные мной):
<EVENT_INSTANCE>
<EventType>ALTER_TABLE</EventType>
<PostTime>2014-12-15T10:53:04.523</PostTime>
<SPID>55</SPID>
<ServerName>_{server_name}_</ServerName>
<LoginName>_{login_name}_</LoginName>
<UserName>dbo</UserName>
<DatabaseName>tempdb</DatabaseName> <!-- casing is based on database definition -->
<SchemaName>dbo</SchemaName>
<ObjectName>MyAlterTest</ObjectName> <!-- casing is based on object definition -->
<ObjectType>TABLE</ObjectType>
<AlterTableActionList>
<Create>
<Columns>
<Name>DATEcreated</Name> <!-- casing is taken from executed query -->
</Columns>
</Create>
</AlterTableActionList>
<TSQLCommand>
<SetOptions ANSI_NULLS="ON" ANSI_NULL_DEFAULT="ON" ANSI_PADDING="ON" QUOTED_IDENTIFIER="ON" ENCRYPTED="FALSE"/>
<CommandText>alTeR Table tempDB.dbo.MyALTERTest ADD DATEcreated DATETIME NOT NULL;
</CommandText>
</TSQLCommand>
</EVENT_INSTANCE>
Было бы хорошо, если за колонкой детали (т.е. NULL/NOT NULL, тип данных и т. д.), а не только имя, но при необходимости они могут быть проанализированы из элемента CommandText
.
Вам нужно будет посмотреть SYS.OBJECTS, подключенный к SYS.COLUMNS. SYS.OBJECTS имеет поле create_date: http://technet.microsoft.com/en-us/library/ms190324.aspx –