Der SQL Server verfolgt keine spezifischen Änderungen an Tabellen. Wenn Sie diese Detaillierungsstufe benötigen oder benötigen, müssen Sie einen DDL-Trigger (eingeführt in SQL Server 2005) erstellen, der bestimmte Ereignisse oder sogar Ereignisklassen auffängt und diese Änderungen in einer von Ihnen erstellten Protokolltabelle protokolliert.
DDL-Trigger sind "nach" Trigger; Es gibt keine "statt" -Option. Wenn Sie jedoch eine Aktion ablehnen möchten, können Sie einfach ROLLBACK
ausgeben und das wird abgebrochen.
Die MSDN-Seite für DDL Triggers hat viele gute Informationen darüber, wie zu stoppen entweder bestimmte Ereignisse (dh ALTER TABLE
) und mit Hilfe der EVENTDATA
Funktion, die XML zurückgibt, die Besonderheiten von dem, was Ereignis ausgelöst, den Abzug zu erhalten, einschließlich der genauen SQL-Abfrage, die ausgeführt wurde. Die MSDN-Seite für Use the EVENTDATA Function enthält sogar einfache Beispiele zum Erstellen eines DDL-Triggers zum Erfassen von ALTER TABLE
Anweisungen (im Abschnitt " ALTER TABLE- und ALTER DATABASE-Ereignisse") und Erstellen eines DDL-Triggers zum Erfassen der Ereignisse in einer Protokolltabelle (in der Abschnitt "Beispiel"). Da alle ALTER TABLE
Befehle diesen Trigger auslöst, müssen Sie analysieren, welche spezifisch für was Sie suchen. Und vielleicht wissen Sie jetzt, dass dies eine Option ist, das Erfassen von mehr als nur das Hinzufügen von Spalten ist erwünscht (d. H. Löschen von Spalten, Ändern des Datentyps und/oder der NULL-Fähigkeit usw.).
Es sollte beachtet werden, dass Sie einen DLL-Trigger ON ALL SERVER
für datenbankspezifische Ereignisse wie ALTER_TABLE
erstellen können.
Wenn Sie die Struktur des XML für jede Veranstaltung oder Ereignisklasse sehen möchten, gehen Sie zu:
http://schemas.microsoft.com/sqlserver/2006/11/eventdata/
und klicken Sie auf „Aktuelle Version:“ -Link. Wenn Sie eine bestimmte Ereignis- oder Ereignisklasse sehen möchten, führen Sie einfach eine Suche (normalerweise Control-F im Browser) nach dem Ereignisnamen durch, der in der FOR-Klausel des Triggers (einschließlich des Unterstrichs) verwendet wird. Hier finden Sie das Schema für die ALTER_TABLE
Ereignis:
<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>
Hier ist ein sehr einfacher Test, um zu sehen, wie das funktioniert und was die resultierende Eventdata XML wie folgt aussieht:
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
Zuerst erstellen wir eine einfache, reale Tabelle in tempdb (diese Ereignisse werden nicht für temporäre Tabellen erfasst):
USE [tempdb];
CREATE TABLE dbo.MyAlterTest (Col2 INT NULL);
Als nächstes fügen wir eine Spalte hinzu. Wir tun dies aus einer anderen Datenbank, um sicherzustellen, dass die XML-Datei die Datenbank, in der das Objekt vorhanden ist, anstelle der aktuellen Datenbank erfasst. Bitte beachten Sie das Gehäuse der Wörter alTeR Table tempDB.dbo.MyALTERTest ... DATEcreated
, um mit dem, was in der XML ist, zu vergleichen.
USE [master];
alTeR Table tempDB.dbo.MyALTERTest ADD DATEcreated DATETIME NOT NULL;
Folgendes sollten Sie im Register "Nachrichten" (von mir Kommentare hinzugefügt) sehen:
<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>
Es würde, wenn die Details pro-Säule schön gewesen (dh NULL/NOT NULL, Datentyp, usw.) wurden nicht nur als Name, sondern bei Bedarf auch aus dem CommandText
Element geparst.
Sie müssten sich SYS.OBJECTS ansehen, die mit SYS.COLUMNS verbunden sind. SYS.OBJECTS hat das create_date-Feld: http://technet.microsoft.com/en-us/library/ms190324.aspx –