我认为您不能使用 DDL 触发器来执行此操作,因为在这种情况下,它是一个 after 触发器 - 因此该表不再存在,并且在系统元数据。为什么不只是防止删除所有表,而不仅仅是非空表?
CREATE TRIGGER prevDrop ON DATABASE
FOR DROP_TABLE
AS
BEGIN
ROLLBACK;
RAISERROR('Disable the trigger prevDrop to drop tables!',11,1);
END
GO
他们应该实现的是INSTEAD OF DDL triggers - 请在这里投票:
http://connect.microsoft.com/SQLServer/feedback/details/243986
我还让他们更改了文档,这原本误导人们相信 DDL 触发器阻止了操作,而实际上它会将它们回滚:
http://connect.microsoft.com/SQLServer/feedback/details/752210
我之所以告诉你这一切,是因为你说:
如何追踪即将删除的表?
但这意味着您认为该表尚未被删除。它有。您当然可以在 DDL 触发器中获取表名:
DECLARE @e XML = EVENTDATA(), @t NVARCHAR(513);
SET @t = @e.value('(/EVENT_INSTANCE/SchemaName)[1]', 'nvarchar(255)');
+ '.' + @e.value('(/EVENT_INSTANCE/ObjectName)[1]', 'nvarchar(255)');
RAISERROR('%s has been dropped.', 11, 1, @t);
但这对你没有帮助。您无法检查表的内容,因为它不再存在。你可以徒劳地尝试做一些聪明的事情,比如:
DECLARE @sql NVARCHAR(MAX) = N'SELECT COUNT(*) FROM ' + @t;
EXEC sp_executesql @sql;
但这只会产生:
消息 208,第 16 级,状态 1,第 1 行
无效的对象名称“dbo.tablename”。
尽管如此,如果您在触发器中回滚,或者事务以其他方式中止,则该表随后会再次存在。就触发器本身而言,它并不存在。