Как мне указать "закрыть существующие подключения" в сценарии SQL - PullRequest
141 голосов
/ 11 ноября 2009

Я активно занимаюсь разработкой своей схемы в 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.

Если щелкнуть правой кнопкой мыши базу данных на панели проводника объектов и выбрать задачу «Удалить» из контекстного меню, появится флажок для «закрытия существующих подключений»

Есть ли способ указать эту опцию в моем скрипте?

Ответы [ 6 ]

226 голосов
/ 11 ноября 2009

Вы можете отключить всех и откатить свои транзакции с помощью:

alter database [MyDatbase] set single_user with rollback immediate

После этого вы можете безопасно удалить базу данных:)

35 голосов
/ 11 ноября 2009

Зайдите в Management Studio и сделайте все, что вы описываете, только вместо того, чтобы нажимать OK, нажмите Script. Он покажет код, который он будет запускать, который вы затем сможете включить в свои скрипты.

В этом случае вы хотите:

ALTER DATABASE [MyDatabase] SET SINGLE_USER WITH ROLLBACK IMMEDIATE
GO
15 голосов
/ 06 мая 2013

Согласно документации 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 голосов
/ 03 июня 2017

Я знаю, что уже слишком поздно, но, может быть, кому-то это поможет. при использовании этого переведите вашу базу данных в автономный режим

ALTER DATABASE dbname SET OFFLINE
2 голосов
/ 09 сентября 2014

Я попробовал то, что сказал hgmnz на SQL Server 2012.

Управление создано для меня:

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
0 голосов
/ 07 марта 2019

попробуйте этот код C # для удаления вашей базы данных

публичная статическая пустота DropDatabase (строка 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();
            }
        }
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...