1

如果其中有行,我想防止删除表。

我写:

create trigger prevDrop on database for drop_table
as
begin
   if exists (select * from dropped_table)
    raiserror('cant do',25,1)
end

但是我收到了一个语法错误dropped table

如何跟踪即将删除的表?

4

1 回答 1

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;

但这只会产生:

消息 208,级别 16,状态 1,第 1 行
无效的对象名称“dbo.tablename”。

即使,如果您在触发器中回滚,或者事务以其他方式中止,则该表随后会再次存在。就触发器本身而言,它不存在。

于 2013-02-06T23:48:51.820 回答