SQL Server 无法删除数据库 <dbname>,因为它当前正在使用...但没有显示会话

tus*_*eau 88 sql-server-2005 sql-server

当我尝试删除数据库时,出现错误“无法删除数据库“dbname”,因为它当前正在使用中”。但是,当我运行时sp_who2,肯定没有连接到该数据库的会话。我还将数据库设置为single_user mode with rollback immediate.

为什么会这样?

Aar*_*and 103

连接到另一个数据库的会话可能有一个打开的事务,它也会影响您的数据库 - sp_who2 将只显示一个数据库。它也可以像在 SSMS 中打开的对象资源管理器或对象资源管理器详细信息一样简单,这同样只会在 sp_who2 中显示一个数据库。

不要费心去寻找负责的会话;只需用一个语句将它们全部杀死(并确保它不是您连接的 SSMS 副本,例如另一个查询窗口、对象资源管理器等):

USE master;
GO
ALTER DATABASE dbname SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
GO
Run Code Online (Sandbox Code Playgroud)

现在您将能够删除它,并使用 DDL 而不是 UI 来做到这一点:

DROP DATABASE dbname;
Run Code Online (Sandbox Code Playgroud)

  • 实际上,我所要做的就是“USE master”,然后是“DROP DATABASE dbname”。显然,所需要的只是“使用”其他东西,以释放数据库。 (2认同)
  • @vapcguy 只有当您当前的查询窗口是唯一的连接时,这才是正确的。通常情况并非如此(这就是为什么我的回答指出“并确保连接的不是您的 SSMS 副本”)。 (2认同)

yru*_*hka 24

确保在要删除的数据库上没有诸如数据库快照之类的依赖项。但是,错误消息看起来会不同。您确定没有隐藏的进程连接到您的数据库吗?一个好的方法是运行一个脚本来终止所有会话,并在将数据库重命名为另一个名称后立即删除数据库。

基于此选择创建一个游标:

  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')
Run Code Online (Sandbox Code Playgroud)

光标内的问题:

SET @kill_process =  'KILL ' + @spid      
            EXEC master.dbo.sp_executesql @kill_process
                   PRINT 'killed spid : '+ @spid
Run Code Online (Sandbox Code Playgroud)

在游标关闭并释放后:

sp_dboption 'my_db', 'single user', 'TRUE'

go

sp_renamedb 'my_db', 'my_db_old'

go

DROP DATABASE MY_DB_OLD 
Run Code Online (Sandbox Code Playgroud)


Gai*_*ius 20

当您发出DROP命令时,您当前的数据库是什么?尝试这个:

use master
go
drop database mydb
go
Run Code Online (Sandbox Code Playgroud)

还要确保您连接的是sa而不是dbo要删除的任何数据库。

  • 我刚刚发现了这个问题 - 尝试从 sqlcmd 提示符运行 drop 脚本,并将上下文设置为数据库!都 (3认同)

小智 19

当您使用 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
Run Code Online (Sandbox Code Playgroud)


Kin*_*hah 5

我多次遇到这种情况,以下是我所做的:

当明显的方法不起作用时......(就像你的情况一样):

从 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
Run Code Online (Sandbox Code Playgroud)