Reputation: 514
I do not wish to prevent table drops, but when certain tables are dropped in a database I would like to back up either the entire table or query the rows and select specific rows into another table before the drop.
With a normal trigger on a table, if a row was deleted you could access the 'Deleted' table and access those deleted rows.
The DROP_TABLE trigger fires after the table is dropped.
Is there an equivalent to the Deleted table for a DROP_TABLE trigger? Is there a different approach I could use? Or am I going to have to re-code the business logic in the windows service which creates and drops these tables?
(I REALLY don't want to write a trigger which rolls-back the drop, accesses and copies-out the data, then re-drops the table without firing the trigger recursively. I like inventiveness, but this is too mucky a solution for me)
I am running this on Microsoft SQL Server Enterprise Edition (64-bit) and Microsoft SQL Server Developer Edition (64-bit)
Upvotes: 2
Views: 1198
Reputation: 514
Thanks for the help guys, but to directly answer my own questions:
For DDL triggers (which fire for DROP TABLE), there is no equivalent to the Deleted table within DELETE/UPDATE triggers
There is no equivalent solution without rolling-back the drop, copying-out the data and re-issuing the drop
The only appropriate and correct approach is to re-code the business logic in the windows service which creates and drops these tables - to permit a soft-delete/move/rename when required
Upvotes: 1
Reputation: 8808
If it's the recursive firing of the trigger that bothers you, that can be checked for. This will only run for the initial DROP TABLE.
alter Trigger ddlt_ProcessDropTable
on all server for drop_table
AS
begin
if( trigger_nestlevel() = 1 ) -- only run if top level drop table
begin
declare @data XML
set @data = EVENTDATA()
-- rollback the drop
rollback;
-- get table name
declare @TableName sysname, @SchemaName sysname, @DataBaseName sysname, @Sql nvarchar(1000);
select
@TableName = @data.value('(/EVENT_INSTANCE/ObjectName)[1]', 'nvarchar(2000)'),
@SchemaName = @data.value('(/EVENT_INSTANCE/SchemaName)[1]', 'nvarchar(2000)'),
@DataBaseName = @data.value('(/EVENT_INSTANCE/DatabaseName)[1]', 'nvarchar(2000)')
/****
Do stuff with the dropped table...
****/
-- re-drop the table
set @sql = 'Drop Table ' +
QuoteName(@DataBaseName) + '.' + QuoteName(@SchemaName) + '.' + QuoteName(@TableName)
exec(@sql)
end
end
GO
Upvotes: 0