sql server 本身不记录 ddl 语句执行历史,但可通过 database 级 ddl 触发器实时捕获 create table 等操作;它是唯一开箱即用、语句级精确、同步生效的方案,无需依赖已弃用的默认跟踪、难配置的扩展事件或不可读的事务日志。

SQL Server 本身不记录 DDL 语句执行历史,但可以通过 DATABASE 级别 DDL 触发器捕获 CREATE TABLE 等操作 —— 这是最轻量、无需额外服务或权限的实时监控方式。
为什么不用 SQL Server 默认日志查 CREATE TABLE
系统默认不保留 DDL 执行记录。sys.fn_dblog 和事务日志仅面向恢复,不提供可读的语句文本;扩展事件(XEvents)虽能捕获,但需手动配置会话、目标和过滤,且日志默认不持久化;默认跟踪(Default Trace)在 SQL Server 2016+ 已弃用,且只保留有限时间窗口内的事件,不可靠。
DDL 触发器是唯一开箱即用、语句级精确、同步生效的方案。
创建 DATABASE 级 DDL 触发器捕获 CREATE TABLE
触发器必须建在目标数据库内(不是 master),且需 CREATE DATABASE DDL TRIGGER 权限(通常由 db_owner 或 sysadmin 授予)。
- 触发器作用域是当前数据库,对其他库的
CREATE TABLE不响应 - 必须使用
AFTER CREATE_TABLE(不能用INSTEAD OF,否则会阻止建表) - 事件数据通过
EVENTDATA()函数获取,返回 XML,需用.value()提取字段 - 建议将日志写入本地表而非外部系统,避免触发器执行失败导致建表失败
示例:
CREATE TABLE dbo.DDL_Log (
LogID INT IDENTITY(1,1) PRIMARY KEY,
EventTime DATETIME2 DEFAULT GETDATE(),
EventType NVARCHAR(100),
ObjectName NVARCHAR(256),
SchemaName NVARCHAR(128),
TSQLCommand NVARCHAR(MAX),
LoginName NVARCHAR(128)
);
CREATE OR ALTER TRIGGER tr_CaptureCreateTable
ON DATABASE
AFTER CREATE_TABLE
AS
BEGIN
SET NOCOUNT ON;
DECLARE @EventData XML = EVENTDATA();
INSERT INTO dbo.DDL_Log (
EventType,
ObjectName,
SchemaName,
TSQLCommand,
LoginName
)
SELECT
@EventData.value('(/EVENT_INSTANCE/EventType)[1]', 'NVARCHAR(100)'),
@EventData.value('(/EVENT_INSTANCE/ObjectName)[1]', 'NVARCHAR(256)'),
@EventData.value('(/EVENT_INSTANCE/SchemaName)[1]', 'NVARCHAR(128)'),
@EventData.value('(/EVENT_INSTANCE/TSQLCommand/CommandText)[1]', 'NVARCHAR(MAX)'),
@EventData.value('(/EVENT_INSTANCE/LoginName)[1]', 'NVARCHAR(128)');
END;
常见错误:触发器没生效或报错
典型现象包括:建表后 DDL_Log 表无记录;执行 CREATE TABLE 报错 “The current transaction cannot be committed”;或触发器被意外禁用。
- 检查触发器状态:
SELECT name, is_disabled FROM sys.triggers WHERE parent_class_desc = 'DATABASE' -
EVENTDATA()只在触发器内部有效,不能在 SSMS 查询窗口中单独调用 - 如果触发器内发生未捕获异常(如插入日志表时违反约束),整个 DDL 事务会回滚 → 建表失败。务必用
TRY...CATCH包裹日志写入逻辑 - 日志表若建在
tempdb或远程服务器上,可能因权限、连接或事务隔离问题失败 - 注意:触发器对
CREATE TABLE #t(临时表)不响应,只捕获永久对象
DDL 触发器 vs 更重的 CDC / 审计功能
DDL 触发器适合“知道谁、什么时候、建了什么表”这类轻量审计。它不替代 CDC(变更数据捕获),因为 CDC 针对 DML(INSERT/UPDATE/DELETE),且依赖 service broker 和额外架构;也不等价于 SQL Server Audit,后者需启用服务器审计规范、写入文件或 Windows 日志,配置复杂、有性能开销。
真正容易被忽略的一点是:DDL 触发器不会捕获通过 SSMS 图形界面“生成脚本并执行”的操作 —— 因为那本质仍是 CREATE TABLE 语句,所以它会捕获;但它**无法区分**是人工执行还是应用代码自动执行。如果你需要绑定应用上下文(比如哪个服务 IP、哪个 AppName),得在触发器里解析 HOST_NAME() 或 APP_NAME(),而这些值极易被伪造或为空。











