使用 EVENTDATA 函数捕获触发 DDL 触发器的事件的相关信息。 此函数返回一个 xml
值。 XML 架构包括有关以下内容的信息:
事件时间。
执行触发器时连接的系统进程 ID (SPID)。
触发触发器的事件的类型。
根据事件类型,架构随后包括其他信息,例如发生事件的数据库、发生事件的对象以及事件的 Transact-SQL 语句。 有关详细信息,请参阅 DDL 触发器。
例如,在 AdventureWorks2012 示例数据库中创建以下 DDL 触发器:
CREATE TRIGGER safety
ON DATABASE
FOR CREATE_TABLE
AS
PRINT 'CREATE TABLE Issued.'
SELECT EVENTDATA().value('(/EVENT_INSTANCE/TSQLCommand/CommandText)[1]','nvarchar(max)')
RAISERROR ('New tables cannot be created in this database.', 16, 1)
ROLLBACK
;
然后运行以下 CREATE TABLE
语句:
CREATE TABLE NewTable (Column1 int);
DDL 触发器中的EVENTDATA()
语句捕获不允许的CREATE TABLE
语句的文本。 这可以通过对 EVENTDATA 生成的数据使用 XQuery 语句,并检索出<CommandText>元素来实现。 有关详细信息,请参阅 XQuery 语言参考(SQL Server)。
谨慎
EVENTDATA 捕获 CREATE_SCHEMA 事件的数据,以及相应 CREATE SCHEMA 定义的 <schema_element>(如果有的话)。 此外,EVENTDATA 将 <schema_element> 定义识别为单独的事件。 因此,在 CREATE_SCHEMA 事件和由 CREATE SCHEMA 定义中的 <schema_element> 表示的事件上创建的 DDL 触发器,可能会返回相同的事件数据两次,例如 TSQLCommand
数据。 例如,请考虑在CREATE_SCHEMA和CREATE_TABLE事件上创建的 DDL 触发器,并运行以下批处理:
CREATE SCHEMA s
CREATE TABLE t1 (col1 int)
如果应用程序检索到 TSQLCommand
CREATE_TABLE 事件的数据,请注意,此数据可能会出现两次:一次是在 CREATE_SCHEMA 事件发生时,另一次是在 CREATE_TABLE 事件发生时。 避免在 CREATE_SCHEMA 事件和任何对应的 CREATE SCHEMA 定义的 <schema_element> 文本上创建 DDL 触发器,或者在应用程序中构建逻辑,以免同一事件被处理两次。
ALTER TABLE 和 ALTER DATABASE 事件
ALTER_TABLE和ALTER_DATABASE事件的事件数据还包括受 DDL 语句影响的其他对象的名称和类型,以及对这些对象执行的作。 ALTER_TABLE事件数据包括受 ALTER TABLE 语句影响的列、约束或触发器的名称,以及对受影响的对象执行的作(创建、更改、删除、启用或禁用)。 ALTER_DATABASE事件数据包括受 ALTER DATABASE 语句影响的任何文件或文件组的名称,以及对受影响的对象执行的作(创建、更改或删除)。
例如,在 AdventureWorks 示例数据库中创建以下 DDL 触发器:
CREATE TRIGGER ColumnChanges
ON DATABASE
FOR ALTER_TABLE
AS
-- Detect whether a column was created/altered/dropped.
SELECT EVENTDATA().value('(/EVENT_INSTANCE/TSQLCommand/CommandText)[1]', 'nvarchar(max)')
RAISERROR ('Table schema cannot be modified in this database.', 16, 1);
ROLLBACK;
然后执行以下违反约束的 ALTER TABLE 语句:
ALTER TABLE Person.Address ALTER COLUMN ModifiedDate date;
DDL 触发器中的 EVENTDATA() 语句捕获不允许的 ALTER TABLE
语句的文本。
示例:
可以使用 EVENTDATA 函数创建事件日志。 在以下示例中,将创建一个表来存储事件信息。 然后,在当前数据库上创建一个 DDL 触发器,每当发生任何数据库级 DDL 事件时,就会使用以下信息填充表:
事件的时间(使用 GETDATE 函数)。
发生事件的会话的数据库用户(使用 CURRENT_USER 函数)。
事件类型。
构成事件的 Transact-SQL 语句。
同样,使用 XQuery 查询 EVENTDATA 生成的 xml
数据来捕获最后两个项。
USE AdventureWorks2012;
GO
CREATE TABLE ddl_log (PostTime datetime, DB_User nvarchar(100), Event nvarchar(100), TSQL nvarchar(2000));
GO
CREATE TRIGGER log
ON DATABASE
FOR DDL_DATABASE_LEVEL_EVENTS
AS
DECLARE @data XML
SET @data = EVENTDATA()
INSERT ddl_log
(PostTime, DB_User, Event, TSQL)
VALUES
(GETDATE(),
CONVERT(nvarchar(100), CURRENT_USER),
@data.value('(/EVENT_INSTANCE/EventType)[1]', 'nvarchar(100)'),
@data.value('(/EVENT_INSTANCE/TSQLCommand)[1]', 'nvarchar(2000)') ) ;
GO
--Test the trigger
CREATE TABLE TestTable (a int)
DROP TABLE TestTable ;
GO
SELECT * FROM ddl_log ;
GO
注释
若要返回事件数据,建议使用 XQuery value()
方法而不是 query()
方法。
query()
方法返回的输出中包含了 XML 格式,并将回车换行符(CRLF)实例转义,而 value()
方法使输出中的 CRLF 实例不可见。
AdventureWorks2012 示例数据库提供了类似的 DDL 触发器示例。 若要获取示例,请使用 SQL Server Management Studio 找到数据库触发器文件夹。 此文件夹位于 AdventureWorks2012 数据库的 可编程性 文件夹下。 右键单击 ddlDatabaseTriggerLog 并选择脚本 数据库触发器作为。 默认情况下,禁用 DDL 触发器 ddlDatabaseTriggerLog 。