SQLスクリプトで「既存の接続を閉じる」を指定する方法


153

SQL Server 2008で自分のスキーマに対して積極的な開発を行っており、ドロップ/データベース作成スクリプトを頻繁に再実行したいと考えています。私が走るとき

USE [master]
GO

IF  EXISTS (SELECT name FROM sys.databases WHERE name = N'MyDatabase')
DROP DATABASE [MyDatabase]
GO

このエラーがよく発生します

Msg 3702, Level 16, State 4, Line 3
Cannot drop database "MyDatabase" because it is currently in use.

オブジェクトエクスプローラーペインでデータベースを右クリックし、コンテキストメニューから[削除]タスクを選択すると、「既存の接続を閉じる」ためのチェックボックスがあります

スクリプトでこのオプションを指定する方法はありますか?

回答:


247

次の方法で、全員を切断してトランザクションをロールバックできます。

alter database [MyDatbase] set single_user with rollback immediate

その後、データベースを安全に削除できます:)


8
私はこれを使用しましたが、別のユーザーが「シングルユーザー」として参加する機会があるかどうか疑問に思いました-それは可能ですか?代替案は、A​​LTER DATABASE [MyDatabaseName] SET OFFLINE WITH ROLLBACK IMMEDIATE
Kristen

9
single_userのユーザーはあなたです。シングルユーザーモードの設定後に切断しない限り。その後、他の1人のユーザーがログオンできます。
Andomar

データベースを削除したら、同じ名前で新しいデータベースを作成すると、multi_userモードになると思いますか?したがって、実行する必要はありません。alterdatabase [MyDatbase] set multi_user
AndyM

@AndyM:ええ、おそらくmulti_userがデフォルトです
Andomar

2
@クリステンあなたのアプローチを使用して私はsqlサーバーがmdfとldfファイルを削除しないことを発見しました。set single_userは私には問題なく動作します(常にdbを再作成する必要があります)。
2xMax

36

Management Studioに移動して、説明するすべてを実行します。[OK]をクリックする代わりに、[スクリプト]をクリックします。実行するコードが表示され、スクリプトに組み込むことができます。

この場合、以下が必要です。

ALTER DATABASE [MyDatabase] SET SINGLE_USER WITH ROLLBACK IMMEDIATE
GO

1
私はあなたが説明したとおりに(「データベースの削除」ダイアログをスクリプト化して)この質問に答えようとしましたが、「既存の接続を閉じる」チェックボックスをオンにしても、ALTER DATABASE行がスクリプトに追加されません
マットハミルトン

ウィザードから生成されたスクリプトには、「alter database」行が含まれていました。
ニック

変だ。Management Studioのどのバージョンですか?2008 x64を使用しています。
マットハミルトン

私も:Microsoft SQL Server Management Studio 10.0.1600.22オペレーティングシステム6.0.6001
ニック

8
スクリプトに追加されていないALTER DATABASEと同じ問題がありました。スクリプトに追加するために、スクリプトが生成されたときに、そのデータベースに対して実行中のプロセス(アクティブな接続)があることを確認する必要がありました。
Gilbert

16

ALTER DATABASE SETのドキュメントによると、データベースをSINGLE_USERモードに設定した後、そのデータベースにアクセスできない可能性があります。

データベースをSINGLE_USERに設定する前に、AUTO_UPDATE_STATISTICS_ASYNCオプションがOFFに設定されていることを確認してください。ONに設定すると、統計の更新に使用されるバックグラウンドスレッドがデータベースへの接続を取得し、シングルユーザーモードでデータベースにアクセスできなくなります。

したがって、既存の接続でデータベースを削除する完全なスクリプトは次のようになります。

DECLARE @dbId int
DECLARE @isStatAsyncOn bit
DECLARE @jobId int
DECLARE @sqlString nvarchar(500)

SELECT @dbId = database_id,
       @isStatAsyncOn = is_auto_update_stats_async_on
FROM sys.databases
WHERE name = 'db_name'

IF @isStatAsyncOn = 1
BEGIN
    ALTER DATABASE [db_name] SET  AUTO_UPDATE_STATISTICS_ASYNC OFF

    -- kill running jobs
    DECLARE jobsCursor CURSOR FOR
    SELECT job_id
    FROM sys.dm_exec_background_job_queue
    WHERE database_id = @dbId

    OPEN jobsCursor

    FETCH NEXT FROM jobsCursor INTO @jobId
    WHILE @@FETCH_STATUS = 0
    BEGIN
        set @sqlString = 'KILL STATS JOB ' + STR(@jobId)
        EXECUTE sp_executesql @sqlString
        FETCH NEXT FROM jobsCursor INTO @jobId
    END

    CLOSE jobsCursor
    DEALLOCATE jobsCursor
END

ALTER DATABASE [db_name] SET  SINGLE_USER WITH ROLLBACK IMMEDIATE

DROP DATABASE [db_name]


2

SQL Server 2012でhgmnzの発言を試しました。

私に作成された管理:

EXEC msdb.dbo.sp_delete_database_backuphistory @database_name = N'MyDataBase'
GO
USE [master]
GO
/****** Object:  Database [MyDataBase]    Script Date: 09/09/2014 15:58:46 ******/
DROP DATABASE [MyDataBase]
GO

4
これはアクティブな接続を閉じません。
イェンス

「既存の接続を閉じる」をオンにしたことを確認してください。あなたがそうしないならば、ROLLBACK IMMEDIATE声明は含まれます。これsp_delete_database_backuphistoryは、「データベースのバックアップの削除と履歴情報の復元」をチェックした結果です。
Christian.K

[既存の接続を閉じる]をオンALTER DATABASE SET SINGLE_USER ...にしても、現在閉じる接続がない場合は生成されません。
-ahwm

-1

このC#コードを試してデータベースを削除してください

public static void DropDatabases(string dataBase){

        string sql =  "ALTER DATABASE "  + dataBase + "SET SINGLE_USER WITH ROLLBACK IMMEDIATE" ;

        using (System.Data.SqlClient.SqlConnection connection = new System.Data.SqlClient.SqlConnection(ConfigurationManager.ConnectionStrings["DBRestore"].ConnectionString))
        {
            connection.Open();
            using (System.Data.SqlClient.SqlCommand command = new System.Data.SqlClient.SqlCommand(sql, connection))
            {
                command.CommandType = CommandType.Text;
                command.CommandTimeout = 7200;
                command.ExecuteNonQuery();
            }
            sql = "DROP DATABASE " + dataBase;
            using (System.Data.SqlClient.SqlCommand command = new System.Data.SqlClient.SqlCommand(sql, connection))
            {
                command.CommandType = CommandType.Text;
                command.CommandTimeout = 7200;
                command.ExecuteNonQuery();
            }
        }
    }
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.