Answers:
确保您没有要删除的数据库上的数据库快照之类的依赖项。虽然,错误消息将看起来相反。您确定没有隐藏的进程正在连接到数据库吗?一个好的方法是运行一个脚本,该脚本杀死所有会话,并在将数据库重命名为另一个名称后立即删除数据库。
根据此选择创建一个游标:
select d.name , convert (smallint, req_spid) As spid
from master.dbo.syslockinfo l,
master.dbo.spt_values v,
master.dbo.spt_values x,
master.dbo.spt_values u,
master.dbo.sysdatabases d
where l.rsc_type = v.number
and v.type = 'LR'
and l.req_status = x.number
and x.type = 'LS'
and l.req_mode + 1 = u.number
and u.type = 'L'
and l.rsc_dbid = d.dbid
and rsc_dbid = (select top 1 dbid from
master..sysdatabases
where name like 'my_db')
游标内的问题:
SET @kill_process = 'KILL ' + @spid
EXEC master.dbo.sp_executesql @kill_process
PRINT 'killed spid : '+ @spid
在关闭并释放游标之后:
sp_dboption 'my_db', 'single user', 'TRUE'
go
sp_renamedb 'my_db', 'my_db_old'
go
DROP DATABASE MY_DB_OLD
连接到另一个数据库的会话可能具有打开的事务,该事务也会影响您的数据库-sp_who2仅显示一个数据库。它也可以像在SSMS中打开“对象资源管理器”或“对象资源管理器详细信息”一样简单,它们再次仅在sp_who2中显示一个数据库。
不要费力去寻找负责的会话。只需使用一条语句将它们全部杀死(并确保所连接的不是您的SSMS副本,例如另一个查询窗口,对象资源管理器等):
USE master;
GO
ALTER DATABASE dbname SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
GO
现在,您将能够删除它,并使用DDL而不是UI进行删除:
DROP DATABASE dbname;
USE master
,那么DROP DATABASE dbname
。显然,所需要做的就是仅“使用”其他东西来释放数据库。
发出DROP
命令时,当前的数据库是什么?尝试这个:
use master
go
drop database mydb
go
另外,请确保您已连接,sa
而不要连接dbo
到您要删除的任何数据库。
仅在使用UI时看到SSMS的功能,然后告诉它发出操作脚本,该怎么办?右键单击数据库并选择“删除”,然后选中此框以关闭现有连接,SSMS会执行以下操作:
EXEC msdb.dbo.sp_delete_database_backuphistory @database_name = N'yourdbname'
GO
USE [master]
GO
ALTER DATABASE [yourdbname] SET SINGLE_USER WITH ROLLBACK IMMEDIATE
GO
USE [master]
GO
DROP DATABASE [yourdbname]
GO
我已经多次遇到这种情况,下面是我的工作:
当明显的方法不起作用时(就像您所处的情况一样):
从sysdatabases中找到数据库ID。
然后执行- sp_lock
将显示实例上的所有锁以及spid和dbid。
使用试图脱机或掉线的Dbid杀死spid。
虽然,该过程有点手动,但可以如下自动进行:
IF OBJECT_ID('tempdb.dbo.#temp', 'U') IS NOT NULL
DROP TABLE #temp;
create table #temp (spid int
, dbid int
,ObjId bigint
, IndId bigint
,Type varchar(5)
,resource varchar(max)
,Mode varchar(5)
,status varchar(10));
declare @dbid int
select @dbid =DB_ID(db_name())
insert into #temp
exec sp_lock
select * from #temp
where dbid = @dbid
在StackOverflow上找到了一个非常简单的答案,该答案首次对我有用:
https://stackoverflow.com/a/7469167/261405
这是该答案中的SQL:
DECLARE @DatabaseName nvarchar(50)
SET @DatabaseName = N'YOUR_DABASE_NAME'
DECLARE @SQL varchar(max)
SELECT @SQL = COALESCE(@SQL,'') + 'Kill ' + Convert(varchar, SPId) + ';'
FROM MASTER..SysProcesses
WHERE DBId = DB_ID(@DatabaseName) AND SPId <> @@SPId
--Use this to see results
SELECT @SQL
--Uncomment this to run it
--EXEC(@SQL)