Joh*_*ner 13
如果从实例中分离数据库,则需要对文件执行操作系统级别的删除。更安全的方法是删除数据库。
我的建议是在将数据库置于只读模式后对其进行最终备份(因为这将确保备份期间没有活动发生),然后通过Drop Database命令将其从系统中删除。
完整的命令集将类似于以下内容:
-- Use master db to ensure you don't have an active connection to the db you wish to affect
USE [master]
GO
-- This will kill any active transactions, but will force the database into a Read-Only state
ALTER DATABASE [db_name] SET READ_ONLY WITH ROLLBACK IMMEDIATE
GO
BACKUP DATABASE [db_name] -- Fill in more options here or use the UI to take a backup if you chooose
GO
-- This will kick out all connections from the database allowing you to drop it.
ALTER DATABASE [db_name] SET SINGLE_USER WITH ROLLBACK IMMEDIATE
GO
-- Drop the database (which automatically removes the files from the OS)
DROP DATABASE [db_name]
GO
Run Code Online (Sandbox Code Playgroud)
在此之后,您将需要查找针对数据库运行脚本的任何作业。我建议您等待看看什么失败了(之后您可以编写脚本/删除作业),因为作业可以通过多种方式引用数据库(并非所有这些方式都很容易识别)。
最后,您需要从实例中删除所有只能访问该数据库的用户。这个脚本应该识别那些用户是谁,尽管 Max 的版本更清晰(我没有意识到他发布了一种方法,直到我编辑了我的答案以包含这个):
DECLARE @ExecString NVARCHAR (4000)
-- Create Empty Table in a very lazy manner
SELECT name, principal_id, CAST('' AS NVARCHAR(128)) as database_name
INTO ##tmp_AllDBUsers
FROM sys.server_principals
WHERE 1 = 2
-- Declare Cursor to iterate through all DBs on the instance
DECLARE dbCursor CURSOR
FOR
SELECT name
FROM sys .databases
DECLARE @name NVARCHAR (128)
OPEN dbCursor
FETCH NEXT FROM dbCursor
INTO @name
WHILE @@FETCH_STATUS = 0
BEGIN
SET @ExecString =
'USE [' + @name + '];
INSERT INTO ##tmp_AllDBUsers
SELECT sp.name, sp.principal_id, DB_NAME()
FROM sys.server_principals sp INNER JOIN sys.database_principals dp
ON sp.sid = dp.sid'
EXEC(@ExecString)
FETCH NEXT FROM dbCursor
INTO @name
END
-- Close and deallocate the cursor because you've finished traversing all it's data
CLOSE dbCursor
DEALLOCATE dbCursor
-- Show all logins that do not belong to a server-level role nor have access to any databases
SELECT sp.*
FROM sys.server_principals sp LEFT JOIN ##tmp_AllDBUsers adu
ON sp.principal_id = adu.principal_id
WHERE adu.principal_id IS NULL
AND sp.principal_id NOT IN (SELECT member_principal_id
FROM sys.server_role_members)
AND TYPE IN ('S', 'U', 'G')
-- cleanup
DROP TABLE ##tmp_AllDBUsers
Run Code Online (Sandbox Code Playgroud)
Han*_*non 13
我赞成约翰的回答;我只想添加一些有关您可能想要清理的其他项目的详细信息。
SQL Server 代理作业和警报可能会引用数据库。清理它们将防止报告不必要的错误。
删除任何专门为数据库创建的登录名。以下 T-SQL 将识别可能的候选登录名,您可能会调查这些登录名以查看它们是否正在被使用。该代码标识未被任何数据库引用的登录。
DECLARE @cmd nvarchar(max);
SET @cmd = ' SELECT sp.sid
FROM master.sys.server_principals sp
';
SELECT @cmd = @cmd + ' EXCEPT
SELECT dp.sid
FROM ' + QUOTENAME(d.name) + '.sys.database_principals dp
'
FROM sys.databases d
WHERE d.[state] <> 6; --ignore offline DBs
SET @cmd = 'SELECT spr.*
FROM (
' + @cmd + '
) src
INNER JOIN master.sys.server_principals spr
ON src.sid = spr.sid
WHERE spr.type <> ''R''
AND spr.name NOT LIKE ''%##MS_%''
AND spr.name NOT LIKE ''NT %''
AND NOT EXISTS (
SELECT 1
FROM sys.server_role_members srm
WHERE srm.member_principal_id = spr.principal_id
)
ORDER BY spr.name;
';
EXEC sys.sp_executesql @cmd;
Run Code Online (Sandbox Code Playgroud)该数据库可能存在备份设备。虽然删除它们不是绝对必要的,但如果它们没有被使用,它们应该去消除潜在的未来混淆。
服务器级触发器可以引用数据库。
查找引用数据库的维护计划 - 如果没有更新它们以删除丢失的数据库,这些维护计划将失败。
| 归档时间: |
|
| 查看次数: |
1470 次 |
| 最近记录: |