181

I'm doing active development on my schema in SQL Server 2008 and frequently want to rerun my drop/create database script. When I run

USE [master]
GO

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

I often get this error

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

If you right click on the database in the object explorer pane and select the Delete task from the context menu, there is a checkbox which to "close existing connections"

Is there a way to specify this option in my script?

nick
  • 3,368
  • 5
  • 23
  • 26

8 Answers8

289

You can disconnect everyone and roll back their transactions with:

alter database [MyDatbase] set single_user with rollback immediate

After that, you can safely drop the database :)

Andomar
  • 232,371
  • 49
  • 380
  • 404
  • 11
    I've used this but often wondered if there was a window of opportunity for another user to get in as the "single user" - is that possible? Possible alternative is ALTER DATABASE [MyDatabaseName] SET OFFLINE WITH ROLLBACK IMMEDIATE – Kristen Nov 10 '09 at 23:04
  • 10
    The user in single_user is you; unless you disconnect after setting single user mode. Then one (1) other user can log on. – Andomar Nov 10 '09 at 23:08
  • Once you've dropped the database, if you create a new one with the same name I presume it will be in multi_user mode? So you don't have to run: alter database [MyDatbase] set multi_user – AndyM May 07 '10 at 09:30
  • @AndyM: Yeah, multi_user is probably the default – Andomar May 07 '10 at 11:35
  • 2
    @Kristen Using your approach I found the sql server doesn't remove the mdf and ldf files. Set single_user works fine to me (I need to constantly recreate the db). – 2xMax Mar 15 '13 at 13:48
  • @2xMax: Setting database to OFFLINE isn't intended to remove the files as you could subsequently set it to ONLINE to reinstate the database. OFFLINE allows you to, for example, make a physical file copy. DROP the database if you don't want it anymore, or just RESTORE with same filenames as the original when you are having to "recreate the db" (which will be faster on the restore, especially for large files, as the existing files will be re-used without having to pre-create a new file – Kristen Mar 22 '13 at 07:20
  • 1
    @AndyM: database, after restore, will be in the same state as the database that the backup was made from; e.g. backup a database which is in Single User mode: that's what the restored database will be too. The state of the database being restored over has no effect. (Old comment I know, just wanted to clarify for others who may read this in the future) – Kristen Mar 22 '13 at 07:26
  • Using this example, I couldn't get in the database myself anymore. I fixed that by setting it back to MULTI_USER in the end of my script. – Jowen Oct 30 '13 at 13:47
  • Doesn't work -- says there are still connections to the database, had to go with @Kristen's approach. – BrainSlugs83 Jul 10 '15 at 01:18
44

Go to management studio and do everything you describe, only instead of clicking OK, click on Script. It will show the code it will run which you can then incorporate in your scripts.

In this case, you want:

ALTER DATABASE [MyDatabase] SET SINGLE_USER WITH ROLLBACK IMMEDIATE
GO
hgmnz
  • 13,208
  • 4
  • 37
  • 41
  • 1
    I was going to try to answer this question by doing exactly what you describe (scripting the "delete database" dialog) but it **doesn't** add the ALTER DATABASE line to the script if you check the "close existing connections" checkbox. – Matt Hamilton Nov 10 '09 at 23:03
  • The script generating from the wizard included the 'alter database' line for me. – nick Nov 10 '09 at 23:56
  • Weird. Which Management Studio version? I'm on 2008 x64. – Matt Hamilton Nov 11 '09 at 00:25
  • Me too: Microsoft SQL Server Management Studio 10.0.1600.22 Operating System 6.0.6001 – nick Nov 11 '09 at 01:27
  • 8
    Had the same problem with ALTER DATABASE not being added to the script. In order for me to get it added to the script I had to make sure I had a process running (active connection) against that database when the script was generated. – Gilbert Sep 05 '13 at 14:36
17

According to the ALTER DATABASE SET documentation, there is still a possibility that after setting a database to SINGLE_USER mode you won't be able to access that database:

Before you set the database to SINGLE_USER, verify the AUTO_UPDATE_STATISTICS_ASYNC option is set to OFF. When set to ON, the background thread used to update statistics takes a connection against the database, and you will be unable to access the database in single-user mode.

So, a complete script to drop the database with existing connections may look like this:

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
  • 5,011
  • 2
  • 23
  • 34
10

I know it's too late but may be its helps some one. on using this take your database offline

ALTER DATABASE dbname SET OFFLINE
  • remark: after "drop offline database", file Mdf not dropped! https://stackoverflow.com/questions/33154141/drop-db-but-dont-delete-mdf-ldf – bob217 Mar 27 '20 at 12:45
  • Run `ALTER DATABASE dbname SET ONLINE` just after running the OFFLINE command of this answer. SQL server will only delete the associated files (mdf, ldf) for online databases. By running the offline and online statement consecutively, all existing connections will be dropped, and SQL will delete all db files correctly. – Chris Feb 18 '23 at 12:13
1

I tryed what hgmnz saids on SQL Server 2012.

Management created to me:

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
  • 243
  • 1
  • 5
  • 15
  • 4
    This will not close the active connections. – Jens Aug 11 '16 at 14:06
  • Make sure you checked "Close existing connections"; If you don the `ROLLBACK IMMEDIATE` statement will be included. The `sp_delete_database_backuphistory` comes from checking the "Delete backup and restore history information for databases". – Christian.K Jan 30 '17 at 05:58
  • Checking "Close existing connections" doesn't generate the `ALTER DATABASE SET SINGLE_USER ...` if there are no current connections to close. – ahwm Feb 23 '18 at 17:34
0

if you are trying to drop it from you application, your connection string's initial catalog must be "master"

  • 1
    Please add further details to expand on your answer, such as working code or documentation citations. – Community Sep 09 '21 at 18:08
0

See below. Do not click OK, but Ctrl + Shift + N, and a new window with the script will be ready for you.

Drop Database Dialog for script generation

VivekDev
  • 20,868
  • 27
  • 132
  • 202
-2

try this C# code to drop your database

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();
            }
        }
    }
Shailesh Tiwari
  • 295
  • 4
  • 4