Comment spécifier «fermer les connexions existantes» dans le script SQL

153

Je fais du développement actif sur mon schéma dans SQL Server 2008 et je souhaite fréquemment réexécuter mon script de suppression / création de base de données. Quand je cours

USE [master]
GO

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

J'ai souvent cette erreur

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

Si vous cliquez avec le bouton droit de la souris sur la base de données dans le volet de l'explorateur d'objets et sélectionnez la tâche Supprimer dans le menu contextuel, il y a une case à cocher pour "fermer les connexions existantes"

Existe-t-il un moyen de spécifier cette option dans mon script?

pseudo
la source

Réponses:

247

Vous pouvez déconnecter tout le monde et annuler leurs transactions avec:

alter database [MyDatbase] set single_user with rollback immediate

Après cela, vous pouvez supprimer la base de données en toute sécurité :)

Andomar
la source
8
Je l'ai utilisé mais je me suis souvent demandé s'il y avait une fenêtre d'opportunité pour un autre utilisateur d'entrer en tant qu '"utilisateur unique" - est-ce possible? L'alternative possible est ALTER DATABASE [MyDatabaseName] OFFLINE WITH ROLLBACK IMMEDIATE
Kristen
9
L'utilisateur dans single_user est vous; sauf si vous vous déconnectez après avoir défini le mode mono-utilisateur. Ensuite, un (1) autre utilisateur peut se connecter.
Andomar
Une fois que vous avez supprimé la base de données, si vous en créez une nouvelle avec le même nom, je suppose qu'elle sera en mode multi_utilisateur? Vous n'avez donc pas besoin d'exécuter: alter database [MyDatbase] set multi_user
AndyM
@AndyM: Ouais, multi_user est probablement la valeur par défaut
Andomar
2
@Kristen En utilisant votre approche, j'ai trouvé que le serveur sql ne supprime pas les fichiers mdf et ldf. Set single_user fonctionne bien pour moi (je dois constamment recréer la base de données).
2xMax
36

Accédez au studio de gestion et faites tout ce que vous décrivez, mais au lieu de cliquer sur OK, cliquez sur Script. Il montrera le code qu'il exécutera que vous pourrez ensuite incorporer dans vos scripts.

Dans ce cas, vous souhaitez:

ALTER DATABASE [MyDatabase] SET SINGLE_USER WITH ROLLBACK IMMEDIATE
GO
hgmnz
la source
1
J'allais essayer de répondre à cette question en faisant exactement ce que vous décrivez (script de la boîte de dialogue "supprimer la base de données") mais cela n'ajoute pas la ligne ALTER DATABASE au script si vous cochez la case "fermer les connexions existantes".
Matt Hamilton
Le script généré à partir de l'assistant incluait pour moi la ligne «alter database».
nick
Bizarre. Quelle version de Management Studio? Je suis sur 2008 x64.
Matt Hamilton
Moi aussi: Microsoft SQL Server Management Studio 10.0.1600.22 Système d'exploitation 6.0.6001
nick
8
Avait le même problème avec ALTER DATABASE ne pas être ajouté au script. Pour que je l'ajoute au script, je devais m'assurer qu'un processus était en cours d'exécution (connexion active) sur cette base de données lorsque le script était généré.
Gilbert
16

Selon la documentation ALTER DATABASE SET , il est toujours possible qu'après avoir défini une base de données en mode SINGLE_USER, vous ne puissiez pas accéder à cette base de données:

Avant de définir la base de données sur SINGLE_USER, vérifiez que l'option AUTO_UPDATE_STATISTICS_ASYNC est définie sur OFF. Lorsqu'il est défini sur ON, le thread d'arrière-plan utilisé pour mettre à jour les statistiques établit une connexion à la base de données et vous ne pourrez pas accéder à la base de données en mode mono-utilisateur.

Ainsi, un script complet pour supprimer la base de données avec des connexions existantes peut ressembler à ceci:

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
la source
3

Je sais qu'il est trop tard mais peut-être que cela aide quelqu'un. en utilisant ceci, mettez votre base de données hors ligne

ALTER DATABASE dbname SET OFFLINE
Abhishek Upadhyay
la source
remarque: après "drop offline database", le fichier Mdf n'est pas supprimé! stackoverflow.com/questions/33154141/…
bob217
2

J'ai essayé ce que dit hgmnz sur SQL Server 2012.

Gestion créée pour moi:

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
la source
4
Cela ne fermera pas les connexions actives.
Jens
Assurez-vous d'avoir coché "Fermer les connexions existantes"; Si vous ne le ROLLBACK IMMEDIATEfaites pas, la déclaration sera incluse. Cela sp_delete_database_backuphistoryvient de la vérification de "Supprimer la sauvegarde et restaurer les informations d'historique des bases de données".
Christian.K
Le fait de cocher «Fermer les connexions existantes» ne génère pas le ALTER DATABASE SET SINGLE_USER ...s'il n'y a pas de connexions actuelles à fermer.
ahwm
-1

essayez ce code C # pour supprimer votre base de données

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
la source