我想提出一个服务器级触发器,以防止这不是一个数据库快照任何数据库的下落。乍一看,下面看起来好像它应该工作,但它从来没有。我尝试了扭转逻辑,并没有帮助。有谁知道我做错了什么?SQL Server触发器,以防止数据库中删除
DECLARE @DBName NVARCHAR(100),
@eventData XML;
SET @eventData = EVENTDATA();
SELECT @DBName = @eventData.value('data(/EVENT_INSTANCE/DatabaseName)[1]', 'SYSNAME');
RAISERROR('Attempting delete of %s.', 10, 1, @DBName);
IF @DBName IN (SELECT name
FROM sys.databases
WHERE source_database_id IS NOT NULL)
BEGIN
RAISERROR('[%s] was successfully dropped.', 10, 1, @DBname) WITH LOG;
END;
ELSE
BEGIN
RAISERROR('[%s] cannot be deleted without first disabling the server trigger "tgr_prevent_db_drop".', 10, 1, @DBname) WITH LOG;
ROLLBACK;
END;
顶部的RAISERROR总是确认正确的数据库(例如,一个被删除),当我从sys.databases中运行SELECT手动它总是返回相应的数据。不幸的是,无论我做什么,它总是落入“真正的数据库及其数据库快照”的“..was successfully dropped”部分。
嗨@TheGameIswar,我没跟踪。如果数据库快照,它会在source_database_id列中的值,并出现在SELECT这样的条件应该永远是真的,那么。如果它不是一个快照,source_database_id必须为NULL,所以我期望它评估为false。如果我在DDL触发器之外运行它,它按预期工作。它只在DDL触发器内失败。最终,我想允许快照删除,但防止父数据库删除。 – PseudoToad
@PseudoToad的sys.databases中具有基于用户的权限返回值的问题。如果触发器没有在sys.databases中看到快照数据库,那么触发器将作为无权访问的用户执行。 –