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?

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 :)


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

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]


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

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();
            }
        }
    }
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.