如果有行,我想阻止丢弃表。
我写道:
create trigger prevDrop on database for drop_table
as
begin
if exists (select * from dropped_table)
raiserror('cant do',25,1)
end
但我的dropped table
语法错误。
如何跟踪要删除哪个表?
答案 0 :(得分:2)
我认为你不能用DDL触发器来做这件事,因为在这种情况下它是之后的触发器 - 所以表不再存在,并且在它中没有它的痕迹系统元数据。为什么不阻止丢弃所有表,而不仅仅是非空表?
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;
但这只会产生:
Msg 208,Level 16,State 1,Line 1
无效的对象名称'dbo.tablename'。
即使如果您在触发器中回滚,或者事务以其他方式中止,该表也会在之后再次存在。就触发器本身而言,它不存在。