ฉันจะระบุ“ ปิดการเชื่อมต่อที่มีอยู่” ในสคริปต์ sql ได้อย่างไร


153

ฉันกำลังพัฒนาอย่างแข็งขันบน schema ของฉันใน SQL Server 2008 และบ่อยครั้งที่ต้องการรันสคริปต์ฐานข้อมูลหล่น / สร้างของฉันอีกครั้ง เมื่อฉันวิ่ง

USE [master]
GO

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

ฉันมักจะได้รับข้อผิดพลาดนี้

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

หากคุณคลิกขวาที่ฐานข้อมูลในบานหน้าต่างวัตถุ explorer และเลือกงานลบจากเมนูบริบทมีช่องทำเครื่องหมายที่ "ปิดการเชื่อมต่อที่มีอยู่"

มีวิธีระบุตัวเลือกนี้ในสคริปต์ของฉันหรือไม่

คำตอบ:


247

คุณสามารถยกเลิกการเชื่อมต่อทุกคนและย้อนกลับธุรกรรมของพวกเขาด้วย:

alter database [MyDatbase] set single_user with rollback immediate

หลังจากนั้นคุณสามารถดร็อปฐานข้อมูลได้อย่างปลอดภัย :)


8
ฉันเคยใช้สิ่งนี้ แต่มักจะสงสัยว่ามีหน้าต่างแห่งโอกาสให้ผู้ใช้รายอื่นเข้ามาในฐานะ "ผู้ใช้คนเดียว" - เป็นไปได้ไหม? ทางเลือกที่เป็นไปได้คือการเปลี่ยนแปลงฐานข้อมูล [MyDatabaseName] ตั้งค่าแบบออฟไลน์ด้วยการย้อนกลับทันที
Kristen

9
ผู้ใช้ใน single_user คือคุณ นอกเสียจากคุณจะยกเลิกการเชื่อมต่อหลังจากตั้งค่าโหมดผู้ใช้คนเดียว จากนั้นหนึ่ง (1) ผู้ใช้อื่นสามารถเข้าสู่ระบบ
Andomar

เมื่อคุณลบฐานข้อมูลแล้วถ้าคุณสร้างใหม่ด้วยชื่อเดียวกันฉันคิดว่ามันจะอยู่ในโหมด multi_user? ดังนั้นคุณไม่จำเป็นต้องเรียกใช้: แก้ไขฐานข้อมูล [MyDatbase] ตั้งค่า multi_user
AndyM

@AndyM: ใช่ผู้ใช้หลายคนอาจเป็นค่าเริ่มต้น
Andomar

2
@ Kristen ใช้วิธีการของคุณฉันพบว่าเซิร์ฟเวอร์ sql ไม่ได้ลบไฟล์ mdf และ ldf ตั้ง single_user ทำงานได้ดีกับฉัน (ฉันจำเป็นต้องสร้างฐานข้อมูลอย่างต่อเนื่อง)
2xMax

36

ไปที่สตูดิโอการจัดการและทำทุกสิ่งที่คุณอธิบายเพียงคลิกตกลงคลิกที่สคริปต์ มันจะแสดงรหัสมันจะทำงานซึ่งคุณสามารถรวมในสคริปต์ของคุณ

ในกรณีนี้คุณต้องการ:

ALTER DATABASE [MyDatabase] SET SINGLE_USER WITH ROLLBACK IMMEDIATE
GO

1
ฉันจะพยายามตอบคำถามนี้โดยทำสิ่งที่คุณอธิบาย (สคริปต์การโต้ตอบ "ลบฐานข้อมูล") แต่จะไม่เพิ่มบรรทัดฐานข้อมูลแก้ไขให้กับสคริปต์หากคุณทำเครื่องหมายในช่อง "ปิดการเชื่อมต่อที่มีอยู่เดิม"
Matt Hamilton

สคริปต์ที่สร้างจากตัวช่วยสร้างนั้นมีบรรทัด 'แก้ไขฐานข้อมูล' สำหรับฉัน
Nick

แปลก. เวอร์ชันการจัดการ Studio ใด ฉันอยู่ในปี 2008 x64
แมตต์แฮมิลตัน

ฉันด้วย: ระบบปฏิบัติการ Microsoft SQL Server Management Studio 10.0.1600.22 ระบบปฏิบัติการ 6.0.6001
นิ

8
พบปัญหาเดียวกันกับการเปลี่ยนแปลงฐานข้อมูลไม่ถูกเพิ่มไปยังสคริปต์ เพื่อให้ฉันเพิ่มเข้าไปในสคริปต์ฉันต้องแน่ใจว่าฉันมีกระบวนการทำงาน (การเชื่อมต่อที่ใช้งานอยู่) กับฐานข้อมูลนั้นเมื่อสคริปต์ถูกสร้างขึ้น
Gilbert

16

จากเอกสารALTER DATABASE SETยังมีความเป็นไปได้ที่หลังจากตั้งค่าฐานข้อมูลเป็นโหมด SINGLE_USER คุณจะไม่สามารถเข้าถึงฐานข้อมูลนั้นได้:

ก่อนที่คุณจะตั้งค่าฐานข้อมูลเป็น SINGLE_USER ให้ตรวจสอบตัวเลือก AUTO_UPDATE_STATISTICS_ASYNC ว่าตั้งไว้ที่ OFF เมื่อตั้งค่าเป็น ON เธรดพื้นหลังที่ใช้เพื่ออัปเดตสถิติจะทำการเชื่อมต่อกับฐานข้อมูลและคุณจะไม่สามารถเข้าถึงฐานข้อมูลในโหมดผู้ใช้คนเดียว

ดังนั้นสคริปต์ที่สมบูรณ์เพื่อปล่อยฐานข้อมูลด้วยการเชื่อมต่อที่มีอยู่อาจมีลักษณะเช่นนี้:

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]

3

ฉันรู้ว่ามันสายเกินไป แต่อาจช่วยได้บ้าง เมื่อใช้สิ่งนี้จะทำให้ฐานข้อมูลของคุณออฟไลน์

ALTER DATABASE dbname SET OFFLINE

หมายเหตุ: หลังจาก "วางฐานข้อมูลออฟไลน์" ไฟล์ Mdf ไม่ได้ถูกทิ้ง! stackoverflow.com/questions/33154141/…
bob217

2

ฉันลองใช้สิ่งที่ hgmnz พูดใน SQL Server 2012

การจัดการที่สร้างขึ้นสำหรับฉัน:

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
นี่จะไม่ปิดการเชื่อมต่อที่ใช้งานอยู่
Jens

ตรวจสอบให้แน่ใจว่าคุณได้เลือก "ปิดการเชื่อมต่อที่มีอยู่"; หากคุณไม่สวมROLLBACK IMMEDIATEคำสั่งจะรวมอยู่ด้วย sp_delete_database_backuphistoryมาจากการตรวจสอบ "การสำรองข้อมูลและเรียกคืนลบข้อมูลประวัติสำหรับฐานข้อมูล"
Christian.K

การตรวจสอบ "ปิดการเชื่อมต่อที่มีอยู่" ไม่ได้สร้างALTER DATABASE SET SINGLE_USER ...หากไม่มีการเชื่อมต่อปัจจุบันที่จะปิด
ahwm

-1

ลองใช้รหัส C # นี้เพื่อวางฐานข้อมูลของคุณ

โมฆะสาธารณะคงเป็นโมฆะ DropDatabase (ฐานข้อมูลสตริง) {

        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();
            }
        }
    }
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.