¿Cómo especifico "cerrar conexiones existentes" en el script sql

153

Estoy haciendo un desarrollo activo en mi esquema en SQL Server 2008 y con frecuencia quiero volver a ejecutar mi script de base de datos drop / create. Cuando corro

USE [master]
GO

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

A menudo me sale este error

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

Si hace clic con el botón derecho en la base de datos en el panel del explorador de objetos y selecciona la tarea Eliminar en el menú contextual, hay una casilla de verificación para "cerrar las conexiones existentes"

¿Hay alguna manera de especificar esta opción en mi script?

mella
fuente

Respuestas:

247

Puede desconectar a todos y revertir sus transacciones con:

alter database [MyDatbase] set single_user with rollback immediate

Después de eso, puede soltar la base de datos de forma segura :)

Andomar
fuente
8
He usado esto, pero a menudo me preguntaba si había una ventana de oportunidad para que otro usuario entrara como "usuario único". ¿Es eso posible? La alternativa posible es ALTER DATABASE [MyDatabaseName] SET OFFLINE WITH ROLLBACK INMEDIATE
Kristen
9
El usuario en single_user eres tú; a menos que se desconecte después de configurar el modo de usuario único. Luego, un (1) otro usuario puede iniciar sesión.
Andomar
Una vez que haya eliminado la base de datos, si crea una nueva con el mismo nombre, ¿supongo que estará en modo multiusuario? Para que no tenga que ejecutar: alter database [MyDatbase] set multi_user
AndyM
@AndyM: Sí, multi_user es probablemente el predeterminado
Andomar
2
@Kristen Usando su enfoque, descubrí que el servidor SQL no elimina los archivos mdf y ldf. Establecer single_user funciona bien para mí (necesito recrear constantemente el db).
2xMax
36

Vaya al estudio de administración y haga todo lo que describa, solo que en lugar de hacer clic en Aceptar, haga clic en Script. Mostrará el código que ejecutará y luego podrá incorporarlo a sus scripts.

En este caso, quieres:

ALTER DATABASE [MyDatabase] SET SINGLE_USER WITH ROLLBACK IMMEDIATE
GO
hgmnz
fuente
1
Intentaría responder a esta pregunta haciendo exactamente lo que usted describe (escribir el cuadro de diálogo "eliminar base de datos") pero no agrega la línea ALTER DATABASE al script si marca la casilla de verificación "cerrar conexiones existentes".
Matt Hamilton
El script que generó desde el asistente incluyó la línea 'alter database' para mí.
nick
Extraño. ¿Qué versión de Management Studio? Estoy en 2008 x64.
Matt Hamilton el
Yo también: Microsoft SQL Server Management Studio 10.0.1600.22 Sistema operativo 6.0.6001
nick
8
Tuve el mismo problema con ALTER DATABASE que no se agregó al script. Para poder agregarlo al script, tuve que asegurarme de tener un proceso en ejecución (conexión activa) en esa base de datos cuando se generó el script.
Gilbert
16

De acuerdo con la documentación de ALTER DATABASE SET , todavía existe la posibilidad de que después de configurar una base de datos en modo SINGLE_USER no pueda acceder a esa base de datos:

Antes de establecer la base de datos en SINGLE_USER, verifique que la opción AUTO_UPDATE_STATISTICS_ASYNC esté establecida en OFF. Cuando se establece en ON, el subproceso en segundo plano utilizado para actualizar las estadísticas se conecta a la base de datos, y no podrá acceder a la base de datos en modo de usuario único.

Por lo tanto, un script completo para descartar la base de datos con conexiones existentes puede verse así:

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]
AlexD
fuente
3

Sé que es demasiado tarde, pero puede ser útil para alguien. al usar esto, desconecte su base de datos

ALTER DATABASE dbname SET OFFLINE
Abhishek Upadhyay
fuente
comentario: después de "soltar la base de datos fuera de línea", ¡el archivo Mdf no se descartó! stackoverflow.com/questions/33154141/…
bob217
2

Probé lo que dice hgmnz en SQL Server 2012.

Gestión creada para mí:

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
Deiwys
fuente
44
Esto no cerrará las conexiones activas.
Jens
Asegúrese de marcar "Cerrar conexiones existentes"; Si lo hace ROLLBACK IMMEDIATE, se incluirá la declaración. Esto sp_delete_database_backuphistoryviene de marcar la opción "Eliminar copia de seguridad y restaurar la información del historial de las bases de datos".
Christian.K
Marcar "Cerrar conexiones existentes" no genera ALTER DATABASE SET SINGLE_USER ...si no hay conexiones actuales para cerrar.
ahwm
-1

pruebe este código C # para descartar su base de datos

público estático vacío 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();
            }
        }
    }
Shailesh Tiwari
fuente