SQL 스크립트에서 "기존 연결 닫기"를 지정하는 방법


153

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.

개체 탐색기 창에서 데이터베이스를 마우스 오른쪽 단추로 클릭하고 상황에 맞는 메뉴에서 작업 삭제를 선택하면 "기존 연결을 닫습니다"확인란이 있습니다.

내 스크립트에서이 옵션을 지정하는 방법이 있습니까?

답변:


247

다음을 사용하여 모든 사람을 연결 해제하고 트랜잭션을 롤백 할 수 있습니다.

alter database [MyDatbase] set single_user with rollback immediate

그 후에는 데이터베이스를 안전하게 삭제할 수 있습니다 :)


8
나는 이것을 사용했지만 종종 다른 사용자가 "단일 사용자"로 들어갈 기회가 있는지 궁금해했다. 가능합니까? 가능한 대안은 ALTER DATABASE [MyDatabaseName]으로 오프라인으로 롤백 즉시 설정
Kristen

9
single_user의 사용자는 귀하입니다. 단일 사용자 모드를 설정 한 후 연결을 끊지 않으면 그런 다음 한 명의 다른 사용자가 로그온 할 수 있습니다.
Andomar

데이터베이스를 삭제하면 같은 이름으로 새 데이터베이스를 만들면 다중 사용자 모드에 있다고 가정합니다. 그래서 당신은 실행할 필요가 없습니다 : alter database [MyDatbase] set multi_user
AndyM

@AndyM : 예, multi_user가 기본값 일 것입니다.
Andomar

2
@Kristen 귀하의 접근 방식을 사용하여 SQL 서버가 mdf 및 ldf 파일을 제거하지 않는다는 것을 알았습니다. single_user 설정이 제대로 작동합니다 (DB를 지속적으로 다시 만들어야 함).
2xMax

36

관리 스튜디오로 이동하여 설명을 모두 수행하십시오. 확인을 클릭하는 대신 스크립트를 클릭하십시오. 스크립트에 통합 할 수있는 코드가 표시됩니다.

이 경우에는 다음을 원합니다.

ALTER DATABASE [MyDatabase] SET SINGLE_USER WITH ROLLBACK IMMEDIATE
GO

1
"데이터베이스 삭제"대화 상자를 설명하는 그대로 수행하여이 질문에 대답하려고했지만 "기존 연결 닫기"확인란을 선택하면 스크립트에 ALTER DATABASE 줄이 추가 되지 않습니다 .
매트 해밀턴

마법사에서 생성하는 스크립트에는 'alter database'줄이 포함되어 있습니다.
nick

기묘한. 어떤 Management Studio 버전입니까? 저는 2008 x64입니다.
매트 해밀턴

나도 : Microsoft SQL Server Management Studio 10.0.1600.22 운영 체제 6.0.6001
nick

8
ALTER DATABASE가 스크립트에 추가되지 않은 것과 동일한 문제가 있습니다. 스크립트에 추가하려면 스크립트가 생성 될 때 해당 데이터베이스에 대해 프로세스가 실행 중 (활성 연결) 상태 여야합니다.
길버트

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]


2

SQL Server 2012에서 hgmnz의 말을 시도했습니다.

나에게 만든 관리 :

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.

"기존 연결 닫기"를 체크해 ALTER DATABASE SET SINGLE_USER ...도 현재 연결이 닫히지 않으면를 생성하지 않습니다 .
ahwm

-1

이 C # 코드를 사용하여 데이터베이스를 삭제하십시오.

공공 정적 무효 DropDatabases (문자열 데이터베이스) {

        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.