Wie gebe ich im SQL-Skript "Vorhandene Verbindungen schließen" an?

153

Ich entwickle mein Schema in SQL Server 2008 aktiv und möchte mein Drop / Create-Datenbankskript häufig erneut ausführen. Wenn ich renne

USE [master]
GO

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

Ich bekomme oft diesen Fehler

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

Wenn Sie im Objekt-Explorer-Bereich mit der rechten Maustaste auf die Datenbank klicken und im Kontextmenü die Aufgabe Löschen auswählen, gibt es ein Kontrollkästchen, mit dem Sie "vorhandene Verbindungen schließen" können.

Gibt es eine Möglichkeit, diese Option in meinem Skript anzugeben?

Nick
quelle

Antworten:

247

Sie können alle trennen und ihre Transaktionen zurücksetzen mit:

alter database [MyDatbase] set single_user with rollback immediate

Danach können Sie die Datenbank sicher löschen :)

Andomar
quelle
8
Ich habe dies verwendet, mich aber oft gefragt, ob es ein Zeitfenster für einen anderen Benutzer gibt, um als "Einzelbenutzer" einzusteigen - ist das möglich? Mögliche Alternative ist ALTER DATABASE [MyDatabaseName] SET OFFLINE MIT ROLLBACK IMMEDIATE
Kristen
9
Der Benutzer in single_user sind Sie; es sei denn, Sie trennen die Verbindung nach dem Einstellen des Einzelbenutzermodus. Dann kann sich ein (1) anderer Benutzer anmelden.
Andomar
Wenn Sie die Datenbank gelöscht haben und eine neue mit demselben Namen erstellen, wird sie vermutlich im Multi_user-Modus sein? Sie müssen also nicht ausführen: alter database [MyDatbase] set multi_user
AndyM
@ AndyM: Ja, Multi_Benutzer ist wahrscheinlich die Standardeinstellung
Andomar
2
@Kristen Mit Ihrem Ansatz habe ich festgestellt, dass der SQL Server die MDF- und LDF-Dateien nicht entfernt. Set single_user funktioniert gut für mich (ich muss die Datenbank ständig neu erstellen).
2xMax
36

Gehen Sie zu Management Studio und führen Sie alles aus, was Sie beschreiben. Klicken Sie statt auf OK auf Skript. Es wird der Code angezeigt, der ausgeführt wird und den Sie dann in Ihre Skripte integrieren können.

In diesem Fall möchten Sie:

ALTER DATABASE [MyDatabase] SET SINGLE_USER WITH ROLLBACK IMMEDIATE
GO
hgmnz
quelle
1
Ich wollte versuchen, diese Frage zu beantworten, indem ich genau das tat, was Sie beschrieben haben (Skripterstellung im Dialogfeld "Datenbank löschen"), aber die Zeile ALTER DATABASE wird dem Skript nicht hinzugefügt, wenn Sie das Kontrollkästchen "Vorhandene Verbindungen schließen" aktivieren.
Matt Hamilton
Das vom Assistenten generierte Skript enthielt für mich die Zeile "Datenbank ändern".
Nick
Seltsam. Welche Management Studio-Version? Ich bin auf 2008 x64.
Matt Hamilton
Ich auch: Microsoft SQL Server Management Studio 10.0.1600.22 Betriebssystem 6.0.6001
Nick
8
Hatte das gleiche Problem mit ALTER DATABASE nicht zum Skript hinzugefügt. Damit ich es dem Skript hinzufügen konnte, musste ich sicherstellen, dass bei der Erstellung des Skripts ein Prozess für diese Datenbank ausgeführt wurde (aktive Verbindung).
Gilbert
16

Gemäß der Dokumentation zu ALTER DATABASE SET besteht weiterhin die Möglichkeit, dass Sie nach dem Einstellen einer Datenbank in den SINGLE_USER-Modus nicht auf diese Datenbank zugreifen können:

Bevor Sie die Datenbank auf SINGLE_USER setzen, überprüfen Sie, ob die Option AUTO_UPDATE_STATISTICS_ASYNC auf OFF gesetzt ist. Wenn diese Option auf ON gesetzt ist, stellt der zum Aktualisieren von Statistiken verwendete Hintergrundthread eine Verbindung zur Datenbank her, und Sie können im Einzelbenutzermodus nicht auf die Datenbank zugreifen.

Ein vollständiges Skript zum Löschen der Datenbank mit vorhandenen Verbindungen kann also folgendermaßen aussehen:

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
quelle
3

Ich weiß, dass es zu spät ist, aber vielleicht hilft es jemandem. Wenn Sie dies verwenden, schalten Sie Ihre Datenbank offline

ALTER DATABASE dbname SET OFFLINE
Abhishek Upadhyay
quelle
Bemerkung: Nach "Offline-Datenbank löschen" wird Datei Mdf nicht gelöscht! stackoverflow.com/questions/33154141/…
bob217
2

Ich habe versucht, was hgmnz auf SQL Server 2012 sagt.

Management für mich geschaffen:

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
quelle
4
Dadurch werden die aktiven Verbindungen nicht geschlossen.
Jens
Stellen Sie sicher, dass Sie "Vorhandene Verbindungen schließen" aktiviert haben. Wenn Sie nicht anziehen, wird die ROLLBACK IMMEDIATEErklärung beigefügt. Das sp_delete_database_backuphistorykommt von dem „Delete Backup und Verlaufsinformationen für Datenbanken wiederherstellen“ zu überprüfen.
Christian.K
ALTER DATABASE SET SINGLE_USER ...Wenn Sie "Vorhandene Verbindungen schließen" aktivieren, wird dies nicht generiert, wenn keine aktuellen Verbindungen zum Schließen vorhanden sind.
Ahwm
-1

Versuchen Sie diesen C # -Code, um Ihre Datenbank zu löschen

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
quelle