Reputation: 11
I want to prevent dropping table if there are rows in it.
I wrote:
create trigger prevDrop on database for drop_table
as
begin
if exists (select * from dropped_table)
raiserror('cant do',25,1)
end
But I am getting a syntax error with the dropped table
.
How can I trace which table is about to be deleted?
Upvotes: 1
Views: 1253
Reputation:
I don't think you can do this with a DDL trigger, since in this case it is an after trigger - so the table no longer exists, and there is no trace of it in the system metadata. Why not just prevent dropping ALL tables, not just non-empty ones?
CREATE TRIGGER prevDrop ON DATABASE
FOR DROP_TABLE
AS
BEGIN
ROLLBACK;
RAISERROR('Disable the trigger prevDrop to drop tables!',11,1);
END
GO
What they should implement is INSTEAD OF DDL triggers
- please vote for it here:
http://connect.microsoft.com/SQLServer/feedback/details/243986
I also had them change the documentation, which originally was misleading people into believing that DDL triggers prevented actions, when really it rolls them back:
http://connect.microsoft.com/SQLServer/feedback/details/752210
The reason I am telling you all of this is because you state:
How can I trace which table is about to be deleted?
However this implies that you think the table hasn't been deleted yet. It has. You can certainly get the table name within the DDL trigger:
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);
But this doesn't help you. You can't check the contents of the table because it no longer exists. You can try in vain to do something clever, like:
DECLARE @sql NVARCHAR(MAX) = N'SELECT COUNT(*) FROM ' + @t;
EXEC sp_executesql @sql;
But this will just yield:
Msg 208, Level 16, State 1, Line 1
Invalid object name 'dbo.tablename'.
Even though, if you rollback in the trigger, or the transaction is otherwise aborted, the table exists again right afterward. As far as the trigger itself is concerned, it doesn't exist.
Upvotes: 2