如何在SQL Server 2008 Express上克隆同一服务器上的SQL Server数据库?

353

我有一个包含数据库的 MS SQL Server 2008 Express 系统,我想要将其“复制并重命名”(用于测试),但我不知道如何简单地实现这一点。

我注意到在 SQL Server 的 R2 版本中有一个复制数据库向导,但遗憾的是我无法升级。

所涉及的数据库大小约为1G。我尝试将所需复制的数据库的备份还原到一个新数据库中,但没有成功。


2
恢复备份应该是可以的。你能提供更多关于它失败的细节吗? - Ed Harper
8
我意识到在从备份中恢复时犯了一个错误。我先创建了一个新的空数据库,然后尝试从那里还原备份。我应该做的是打开还原对话框,然后在其中输入新数据库的名称,而不是事先创建它。这样做可以很好地克隆数据库! - Sergio
当我试图将数据库恢复到不同的名称下时,它只是给了我一个错误提示:"数据库 'My Database (New)' 的恢复失败。... 无法获得独占访问权限,因为数据库正在使用中。" - 在其新名称下的数据库并不存在,那么它怎么可能正在使用中呢?! - Matt Arnold
18个回答

481
  1. 安装 Microsoft SQL Management Studio,你可以从 Microsoft 网站免费下载:

    版本 2008

    Microsoft SQL Management Studio 2008 是 SQL Server 2008 Express with Advanced Services 的一部分。

    版本 2012

    点击下载按钮并勾选ENU\x64\SQLManagementStudio_x64_ENU.exe

    版本 2014

    点击下载按钮并勾选 MgmtStudio 64BIT\SQLManagementStudio_x64_ENU.exe

  2. 打开Microsoft SQL Management Studio

  3. 备份原始数据库到 .BAK 文件(db -> Task -> Backup)。
  4. 创建一个空的新数据库并赋予新名称(clone)。注意下面的注释是可选项。
  5. 点击复制数据库并打开还原对话框(如图) restore dialog
  6. 选择设备并添加第三步中的备份文件。 add backup file
  7. 更改目标数据库为测试数据库。 change destination
  8. 更改数据库文件的位置,它必须与原始文件不同。你可以直接在文本框中输入,只需添加后缀。(注意:顺序很重要。先选择复选框,然后再更改文件名。) change location
  9. 勾选 WITH REPLACE 和 WITH KEEP_REPLICATION。 with replace

124
  1. 不要创建一个空的数据库并将.bak文件还原到其中。
  2. 使用SQL Server Management Studio中“Databases”分支右键点击后可访问的“还原数据库”选项,在提供源以进行还原时同时提供数据库名称。参考:https://dev59.com/cWkv5IYBdhLWcg3w_lzE
- taynguyen
1
Microsoft SQL Management Studio - 它是免费的。 - Tomas Kubes
8
无法运行 - “由于数据库正在使用,无法获取独占访问权限”。 - Emanuele Ciriachi
26
我还必须取消选中“在还原之前备份日志尾部”的选项。 默认情况下,这个选项会导致“无法获得独占访问权限,因为数据库正在使用”错误。 - Turnip
5
我的原始数据库卡在“正在还原”的状态。 - dvgrape
显示剩余9条评论

126

右键数据库进行克隆,点击任务,再点击复制数据库...。按照向导操作即可完成。


8
以下是如何在Express中进行操作的步骤:https://dev59.com/Om855IYBdhLWcg3wj1MS - Th 00 mÄ s
2
如果您的数据库中有加密对象,则此方法无法正常工作。 - cjbarth
1
我认为,主要问题实际上在于在哪里执行?你所描述的相当直观。我之前在一些工具(0xDBE、Visual Studio SQL Server对象浏览器)中尝试了完全相同的操作,但没有发现这样的功能。 - David Ferenczy Rogožan
5
不可能!任务 -> 没有菜单项可以复制数据库。 - raiserle
1
您需要在目标服务器上安装SQL Server代理。 - Jan
显示剩余7条评论

113

您可以尝试将数据库分离,通过命令提示符将文件复制到新名称,然后附加两个数据库。

在SQL中:

USE master;
GO 
EXEC sp_detach_db
    @dbname = N'OriginalDB';
GO

在命令提示符下(为了简化示例中的文件路径):

copy c:\OriginalDB.mdf c:\NewDB.mdf
copy c:\OriginalDB.ldf c:\NewDB.ldf

再次回到SQL:

USE master;
GO
CREATE DATABASE OriginalDB
    ON (FILENAME = 'C:\OriginalDB.mdf'),
       (FILENAME = 'C:\OriginalDB.ldf')
    FOR ATTACH;
GO
CREATE DATABASE NewDB
    ON (FILENAME = 'C:\NewDB.mdf'),
       (FILENAME = 'C:\NewDB.ldf')
    FOR ATTACH;
GO

10
使用select * from OriginalDB.sys.sysfiles语句可以查找数据库文件的位置。 - JohnLBevan
是的,我也最喜欢这个解决方案,因为它不需要任何特殊工具。但是我无法创建一个NewDB,它在.mdf文件上显示“权限被拒绝”。我现在不需要它,我只需要原始数据库的备份,以便稍后可以用它覆盖原始数据库,我只是好奇为什么会出现这样的错误。 - David Ferenczy Rogožan
3
如果你可以停止sql服务,复制mdf和ldf文件,为新数据库重命名它们,然后重新启动sql服务,那么你就不必分离原始数据库。在master下运行最后的create database命令即可:USE master; GO CREATE DATABASE NewDB ON (FILENAME = 'C:\NewDB.mdf'), (FILENAME = 'C:\NewDB.ldf') FOR ATTACH; GO - danpop

36

事实证明,我之前尝试从备份中还原数据的方式错误了。

最初我创建了一个新的数据库,然后试图在此处恢复备份。而我应该做的是打开还原对话框,并在目标字段中键入新数据库的名称,这才是最终有效的方法。

因此,简而言之,从备份中还原数据解决了问题。

感谢大家提供的反馈和建议。


当我这样做时,对话框告诉我文件与我最初备份的数据库位于同一位置。因此,我不敢恢复,担心文件会被覆盖。 - Niels Brinch
2
尼尔斯,快照中的文件默认相同。您可以更改它们的名称,以创建新的文件,用于新命名的数据库。 - Colin Dabritz
注意:此方法需要 SQL Agent 服务,请确保在开始数据库复制操作之前已启动该服务。 - dvdmn
你现在已经第三次帮我解决了这个问题。我总是忘记输入它而不是创建它。+啤酒 - Piotr Kula
这个方法对我有效,只需要在“文件”窗口中重命名.mdf和.log文件即可。 - Wollan

28

这是我使用的脚本。有点复杂,但它可以工作。 在SQL Server 2012上进行了测试。

DECLARE @backupPath nvarchar(400);
DECLARE @sourceDb nvarchar(50);
DECLARE @sourceDb_log nvarchar(50);
DECLARE @destDb nvarchar(50);
DECLARE @destMdf nvarchar(100);
DECLARE @destLdf nvarchar(100);
DECLARE @sqlServerDbFolder nvarchar(100);

SET @sourceDb = 'db1'
SET @sourceDb_log = @sourceDb + '_log'
SET @backupPath = 'E:\DB SQL\MSSQL11.MSSQLSERVER\MSSQL\Backup\' + @sourceDb + '.bak'    --ATTENTION: file must already exist and SQL Server must have access to it
SET @sqlServerDbFolder = 'E:\DB SQL\MSSQL11.MSSQLSERVER\MSSQL\DATA\'
SET @destDb = 'db2'
SET @destMdf = @sqlServerDbFolder + @destDb + '.mdf'
SET @destLdf = @sqlServerDbFolder + @destDb + '_log' + '.ldf'

BACKUP DATABASE @sourceDb TO DISK = @backupPath

RESTORE DATABASE @destDb FROM DISK = @backupPath
WITH REPLACE,
   MOVE @sourceDb     TO @destMdf,
   MOVE @sourceDb_log TO @destLdf

2
在我的环境中,文件名与数据库名称不匹配(来自另一个还原),因此我需要使用 SET @sourceDb_log = (SELECT files.name FROM sys.databases dbs INNER JOIN sys.master_files files ON dbs.database_id=files.database_id WHERE dbs.name=@sourceDb AND files.type=1) 和一个类似的查询的单独变量 @sourceDb_data(替换为 files.type=0)。希望对你有所帮助! - Dan Caseley
出现错误:Msg 137, Level 15, State 2, Line 25 Must declare the scalar variable "@destDb". 原来我在变量声明和使用之间放了一个 GO 语句,我们不能这样做,参见:https://dev59.com/0Ww05IYBdhLWcg3wiyRJ#55347161 - Arsinclair
1
非常有用的脚本! 只需要在第11行的变量前加上 '@' 即可进行语法修正: SET @backupPath = 'E:\tmp\' + @sourceDb + '.bak' --注意:文件必须已经存在,SQL Server 必须能够访问它。 此外,您可以将备份文件夹设置为 E:\DB SQL\MSSQL11.MSSQLSERVER\MSSQL\Backup\,以避免设置安全访问权限。 - Andreas Venieris

18

从SSMS :

1 - 备份原始数据库为 .BAK 文件 (your_source_db -> 任务 -> 备份).

2 - 右键点击 "Databases" 和 '还原数据库'

3 - 设备 > ... (按钮) > 添加 > 选择 your_source_db.bak

4 - 在 '常规' 选项卡中,在 '目标' 部分,将 your_source_db 重命名为 new_name_db

5 - 在 '文件' 选项卡中,勾选 '重定位所有文件到文件夹',

  • 在 '还原为' 列中将两行重命名以保持与 new_name_db 的一致性 (.mdf、_log.ldf)

6 - 在 '选项' 选项卡中,在 '还原选项' 部分中,勾选前两个选项 ('覆盖...', '保留...'),并对 '恢复状态' 选择 'RESTORE WITH RECOVERY'

  • 还要确保在 '尾随日志备份' 部分中取消选中选项,以避免将源数据库保留在 '正在还原状态' 中!

输入图像描述


15

这里提到的解决方案对我都不起作用——我正在使用 SQL Server Management Studio 2014。

相反,我必须取消“选项”屏幕中“还原前获取尾随日志备份”的复选框:在我的版本中,默认情况下已选中,并防止完成“还原”操作。 取消选中后,“还原”操作顺利完成。

输入图片说明


2
这个答案救了我的一天。 - Dilhan Jayathilake
2
也救了我的一天 :) - ashilon
1
当使用SQL Server 2017时,如果不这样做,原始数据库将保持在“正在还原...”状态。您的解决方案起了作用 - 谢谢! - mu88

11
使用MS SQL Server 2012,您需要执行3个基本步骤:
  1. 首先,生成仅包含源数据库结构的.sql文件
    • 右键单击源数据库,然后选择“任务”,接着选择“生成脚本”
    • 按照向导操作并将.sql文件保存在本地
  2. 其次,在.sql文件中用目标数据库替换源数据库
    • 右键单击目标文件,选择“新建查询”,然后按下Ctrl-H或(“编辑” - “查找和替换” - “快速替换”)
  3. 最后,填充数据
    • 右键单击目标数据库,然后选择“任务”和“导入数据”
    • 数据源下拉设置为“SQL Server .NET Framework 数据提供程序”+在DATA下设置连接字符串文本字段,例如:Data Source=Mehdi\SQLEXPRESS;Initial Catalog=db_test;User ID=sa;Password=sqlrpwrd15
    • 与目标执行相同操作
    • 选中要传输的表或选中旁边的复选框"source: ..."以选中所有表格
您已经完成了。

顺便说一下,我猜Import Data可以在目标表不存在的情况下创建表。。简单的解决方案 +1 - Khurram Ishaque

7
如果数据库并不是特别庞大,您可以查看 SQL Server Management Studio Express 中的“脚本数据库”命令。该命令位于资源管理器中数据库项本身的上下文菜单中。
您可以选择需要脚本的所有内容;当然,您需要包括对象和数据。然后将整个脚本保存到单个文件中。接下来,您可以使用该文件重新创建数据库;只需确保顶部的 USE 命令设置为正确的数据库即可。

1
谢谢,数据库相当大(约1GB),所以我认为可能会发生糟糕的事情 :-) - Sergio
2
好的,那么这不是最好的方法。相反,您可以使用脚本数据库仅在新数据库中创建结构,然后使用导入/导出移动数据。只需确保首先执行脚本数据库;如果表不存在,则导入/导出将创建表,您可能不喜欢它的方式。 - Andrew Barber

7
在SQL Server 2008 R2中,将数据库作为文件备份到文件夹中。 然后选择出现在“数据库”文件夹中的恢复选项。 在向导中输入目标数据库中想要的新名称。 选择从文件还原并使用刚创建的文件。 我刚刚做了这件事,非常快速(我的数据库很小,但仍然如此) Pablo。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接