2

我不希望防止表删除,但是当某些表被删除到数据库中时,我想备份整个表或查询行并在删除之前将特定行选择到另一个表中。

使用表上的正常触发器,如果​​删除了一行,您可以访问“已删除”表并访问那些已删除的行。

删除表后触发 DROP_TABLE 触发器。

DROP_TABLE 触发器是否有与 Deleted 表等效的表?我可以使用其他方法吗?或者我是否必须在创建和删除这些表的 Windows 服务中重新编码业务逻辑?

(我真的不想编写一个触发器来回滚删除,访问和复制数据,然后在不递归触发触发器的情况下重新删除表。我喜欢创造性,但这对于解决方案来说太糟糕了我)

我在 Microsoft SQL Server Enterprise Edition(64 位)和 Microsoft SQL Server Developer Edition(64 位)上运行它

4

2 回答 2

1

感谢您的帮助,但要直接回答我自己的问题:

  1. 对于 DDL 触发器(为 DROP TABLE 触发),没有等效于 DELETE/UPDATE 触发器中的 Deleted 表

  2. 如果不回滚 drop、复制数据并重新发出 drop,则没有等效的解决方案

  3. 唯一合适且正确的方法是在创建和删除这些表的 Windows 服务中重新编码业务逻辑 - 以便在需要时允许软删除/移动/重命名

于 2013-01-09T16:24:09.850 回答
0

如果是触发器的递归触发让您感到困扰,则可以进行检查。这只会对初始的 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
于 2013-01-09T13:57:21.133 回答