有没有办法防止从 SSMS GUI 中删除数据库?

Ran*_*dle 5 sql-server ssms sql-server-2014

使用 SQL Server Management Studio,可以在对象资源管理器中右键单击数据库并将其删除。(您也可以使用 T-SQL 删除数据库,此处未演示。)我不小心删除了错误的数据库(谢天谢地,我能够从最近的备份中恢复)。

尽管如此,它让我思考。有没有办法配置数据库以防意外删除——通过 GUI 或 T-SQL 脚本?如果我真的需要删除特定的数据库,那么我应该采取一些深思熟虑的步骤来启用数据库删除。否则无法删除数据库。

我搜索了“防止数据库删除”,我找到的所有内容都是关于如何防止表行数据被删除的操作方法文章——而不是整个数据库的意外删除。

SSMS 对象资源管理器,即将删除数据库

Phi*_*rtz 8

据我所知,您不能直接从 GUI 阻止它。您可以创建一个服务器范围的触发器来监视DROP_DATABASE事件并在调用时向用户抛出错误。

USE [master]
GO
CREATE DATABASE [CannotDropMe];
GO

CREATE TRIGGER TRG_PreventDropDB ON ALL SERVER
FOR DROP_DATABASE
AS
BEGIN
    RAISERROR('You cannot drop databases on this server.', 16,1);
    ROLLBACK;
END
GO

-- ERROR
DROP DATABASE [CannotDropMe];
GO

-- DB still exists
SELECT * FROM sys.databases WHERE name = 'CannotDropMe';
GO
Run Code Online (Sandbox Code Playgroud)

此外,如果您想记录语句 (attempted DROP DATABASE) 以及您想要的任何其他信息,您可以将触发器更改为这样的内容。

/* If logging we need a log table */
CREATE TABLE [SomeDB].dbo.[DropDatabaseLog] (Command VARCHAR(100), DBUser NVARCHAR(100), ServerName NVARCHAR(100), EventTime DATETIME DEFAULT(GETDATE()));
GO

CREATE TRIGGER TRG_PreventDropDB ON ALL SERVER
FOR DROP_DATABASE
AS
BEGIN
    DECLARE @CommandText NVARCHAR(MAX);
    SELECT @CommandText = EVENTDATA().value('(/EVENT_INSTANCE/TSQLCommand/CommandText)[1]', 'nvarchar(max)');
    ROLLBACK;

    SET NOCOUNT ON;
    INSERT INTO [SomeDB].dbo.[DropDatabaseLog] (Command, DBUser, ServerName)
    SELECT @CommandText,
        CURRENT_USER,
        @@SERVERNAME
    RAISERROR('You cannot drop databases on this server.', 16,1);
END
GO

-- ERROR
DROP DATABASE [CannotDropMe];
GO


SELECT * FROM [DropDatabaseLog];
Run Code Online (Sandbox Code Playgroud)

数据库仍然存在,你会得到一些关于可能对谁大喊大叫的信息:)

编辑:我在没有看到 Shaulinator 的回答和链接的情况下盲目地回答了这个问题。查看两个链接,第一个显示如何过滤特定数据库,这可能很有用。


cco*_*nho 5

Phil 给出的建议是防止服务器中的所有数据库被删除。如果只需要保护服务器上的一个数据库不被意外删除怎么办?

让我们假设这个数据库名为ProductionDatabase. 我设法通过以下代码实现了这一点:

CREATE OR ALTER TRIGGER TRG_PreventDropProductionDB ON ALL SERVER
FOR DROP_DATABASE
AS
BEGIN
    IF DB_NAME() = 'ProductionDatabase'
        BEGIN
            RAISERROR('You cannot drop the production database.', 16,1);
            ROLLBACK;
        END
END
GO
Run Code Online (Sandbox Code Playgroud)