SQL强制关闭数据库连接
金蝶云社区-二次开发刘玉
二次开发刘玉
1人赞赏了该文章 1,123次浏览 未经作者许可,禁止转载编辑于2018年12月05日 14:08:34
summary-icon摘要由AI智能服务提供

在SQL Server中,当需要备份、还原、分离、脱机或删除数据库但遇到其他用户正在使用时,SQL Server默认会报错并终止操作。SQL 2005提供了“关闭所有连接”选项用于分离或删除数据库,但备份/还原操作无此选项。文本提供了三种解决方法,包括拔掉网线(影响大)、通知用户断开连接(可能不可行)、使用StopLogin命令强行断开连接,并给出了StopLogin命令的详细实现和示例。

1.问题引入

在SQL Server中备份/还原/分离/脱机/删除指定数据库时, 如果有其他用户正在使用此数据库时, SQL Server为了防止数据异常, 会报错而终止你的操作.
当然, 在SQL 2005里, 在做[分离/删除]数据库时提供了一个选项[关闭所以连接]供勾选(SQL 2000好像没有哦), 然而[备份/还原]操作却没有此选择, 也许你会说可以先[脱机数据库]再做[备份还原]操作, 对, 但你会发现[脱机]处理太慢了J, 那在SQL2005以及SQL 2000下有哪些方法可以解决此问题呢???

2.解决方法:
1. 拔掉此机器的网线. 呵呵, 这种方法立竿见影, 但是可能对其他的连接造成影响.
2. 通知连接至此数据库的用户断开连接. 如果可能连接的用户很多或不知道哪个用户正在连接的话就不可行了.
3. 在SQL Server中用命令StopLogin强行断开连接.详细说明如下:

使用说明:
StopLogin @Dname

其中@Dname为要强行断开连接的数据库名称, 如果您想断开数据库’DEMO’的所有连接,则只要在查询分析器中执行[StopLogin ’DEMO’]即可, 如果您要断开所有数据库的连接进行维护的话则只要执行[StopLogin ’’]即可.

下面用例子说明:

EX1. 使用StopLogin强行断开连接前后SQL的执行结果对比

首先, 我们执行如下SQL语句:

USE DEMO2

GO

SELECT TOP 1 * FROM INVMB

执行结果为:

查询已成功执行

下面我们来执行如下SQL语句:

StopLogin 'DEMO2'


执行结果为:

由于数据库'DEMO2' 离线,无法打开该数据库。

3. StopLogin详细代码(写的仓促, 若有bug请谅解)

IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = object_id(N'[dbo].[StopLogin]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)

DROP PROCEDURE [dbo].[StopLogin]

GO

CREATE PROCEDURE StopLogin

@Dname varchar(50)

AS

DECLARE
@name varchar(50),
@s varchar(1000)
BEGIN
IF (@Dname = '')
BEGIN
DECLARE DataName CURSOR FOR
SELECT name FROM sysdatabases WHERE name not in ('master')

OPEN DataName
FETCH NEXT FROM DataName
INTO @name
WHILE (@@FETCH_STATUS = 0)
BEGIN
DECLARE tb CURSOR local
FOR
SELECT N'kill '+CAST(spid AS varchar)
FROM master..sysprocesses
WHERE dbid=db_id(@name)

OPEN tb
FETCH next FROM tb INTO @s

WHILE @@FETCH_STATUS=0
BEGIN

EXEC(@s)
FETCH NEXT FROM tb INTO @s

END
CLOSE tb
DEALLOCATE tb

FETCH NEXT FROM DataName
INTO @name

END
CLOSE DataName
DEALLOCATE DataName
END

ELSE

BEGIN

DECLARE tb CURSOR local
FOR

SELECT N'kill '+CAST(spid AS varchar)
FROM master..sysprocesses
WHERE dbid=db_id(@Dname)
OPEN tb
FETCH next FROM tb INTO @s
WHILE @@FETCH_STATUS=0
BEGIN
EXEC(@s)
FETCH NEXT FROM tb INTO @s
END
CLOSE tb
DEALLOCATE tb
END
END