回答:
削除するデータベースにデータベーススナップショットなどの依存関係がないことを確認してください。ただし、エラーメッセージは別の方法で表示されます。データベースに接続している隠しプロセスがないことを確認しますか?良い方法は、すべてのセッションを強制終了し、データベースの名前を別の名前に変更した直後にデータベースを削除するスクリプトを実行することです。
この選択に基づいてカーソルを作成します。
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は1つのデータベースのみを表示します。また、SSMSで開かれたオブジェクトエクスプローラーまたはオブジェクトエクスプローラーの詳細のような単純なものでもかまいません。この場合も、sp_who2には1つのデータベースしか表示されません。
責任のあるセッションを見つけようとして気にしないでください。1つのステートメントでそれらをすべて強制終了します(接続されているSSMSのコピーではないことを確認します。たとえば、別のクエリウィンドウ、オブジェクトエクスプローラなど)。
USE master;
GO
ALTER DATABASE dbname SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
GO
これでドロップできるようになり、UIではなくDDLを使用して削除できます。
DROP DATABASE dbname;
USE master
、その時だけDROP DATABASE dbname
でした。どうやら必要なのは、dbを解放するために、他の何かを「使用」することだけです。
DROP
コマンドを発行したときの現在のデータベースは何ですか?これを試して:
use master
go
drop database mydb
go
また、ドロップするデータベースに接続するのsa
ではなくdbo
、接続していることを確認してください。
UIを使用し、アクションのスクリプトを発行するように指示したときにSSMSが何をするのか見てみませんか?DBを右クリックして[削除]を選択し、チェックボックスをオンにして既存の接続を閉じると、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)