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

How can I clone an SQL Server database on the same server in SQL Server 2008 Express?

我有一个MS SQL Server 2008 Express系统,它包含一个我想要"复制和重命名"的数据库(用于测试目的),但我不知道实现这一目的的简单方法。

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

有问题的数据库是围绕着一个演出。
我试图恢复我要复制到新数据库的数据库的备份,但没有运气。


  • 安装Microsoft SQL Management Studio,您可以从Microsoft的网站免费下载:

    版本2008

    Microsoft SQL Management Studio 2008是带有高级服务的SQL Server 2008 Express的一部分

    版本2012

    单击下载按钮并选中ENU\x64\SQLManagementStudio_x64_ENU.exe

    版本2014

    单击下载按钮并检查MgmtStudio 64BIT\SQLManagementStudio_x64_ENU.exe

  • 打开Microsoft SQL Management Studio。

  • 将原始数据库备份到.BAK文件(db - >任务 - >备份)。
  • 使用新名称(克隆)创建空数据库。请注意以下注释,因为这是可选的。
  • 单击以克隆数据库并打开还原对话框(参见图像)
    restore dialog
  • 选择"设备"并添加步骤3中的备份文件。
    add backup file
  • 将目标更改为测试数据库
    change destination
  • 更改数据库文件的位置,它必须与原始文件不同。您可以直接在文本框中输入,只需添加后缀即可。 (注意:订单很重要。选择复选框,然后更改文件名。)
    change location
  • 检查WITH REPLACE和WITH KEEP_REPLICATION
    with replace

  • 右键单击要克隆的数据库,单击Tasks,单击Copy Database...。按照向导,你就完成了。


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

    在SQL中:

    1
    2
    3
    4
    5
    USE master;
    GO
    EXEC sp_detach_db
        @dbname = N'OriginalDB';
    GO

    在命令提示符下(为了这个例子,我简化了文件路径):

    1
    2
    3
    4
    copy c:\OriginalDB.mdf c:
    ewDB.mdf
    copy c:\OriginalDB.ldf c:
    ewDB.ldf

    再次在SQL中:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    USE master;
    GO
    CREATE DATABASE OriginalDB
        ON (FILENAME = 'C:\OriginalDB.mdf'),
           (FILENAME = 'C:\OriginalDB.ldf')
        FOR ATTACH;
    GO
    CREATE DATABASE NewDB
        ON (FILENAME = 'C:
    ewDB.mdf'),
           (FILENAME = 'C:
    ewDB.ldf')
        FOR ATTACH;
    GO


    事实证明,我曾试图从备份中错误地恢复。

    最初我创建了一个新数据库,然后尝试在此处恢复备份。
    我应该做的以及最终的工作是打开恢复对话框并在目标字段中键入新数据库的名称。

    因此,简而言之,从备份中恢复就可以了。

    感谢所有的反馈和建议


    这是我使用的脚本。有点棘手,但它的工作原理。在SQL Server 2012上测试过。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    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:\tmp\' + 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


    使用MS SQL Server 2012,您需要执行3个基本步骤:

  • 首先,生成仅包含源DB结构的.sql文件

    • 右键单击源数据库,然后单击"任务",然后单击"生成脚本"
    • 按照向导并在本地保存.sql文件
  • 其次,将源DB替换为.sql文件中的目标源

    • 右键单击目标文件,选择New Query and Ctrl-H或(Edit - Find and replace - Quick replace)
  • 最后,填充数据

    • 右键单击目标数据库,然后选择"任务"和"导入数据"
    • 数据源下拉设置为"SQL Server的.net框架数据提供程序"+在DATA ex:Data Source=Mehdi\SQLEXPRESS;Initial Catalog=db_test;User ID=sa;Password=sqlrpwrd15下设置连接字符串文本字段
    • 对目的地做同样的事情
    • 检查要传输的表或"source:..."旁边的复选框以检查所有这些
  • 你完成了。


    这里提到的解决方案都不适用于我 - 我正在使用SQL Server Management Studio 2014。

    相反,我必须取消选中"选项"屏幕中的"在恢复前进行尾部日志备份"复选框:在我的版本中,默认情况下会检查它并阻止恢复操作完成。
    取消选中后,还原操作没有问题。

    enter image description here


    在SQL Server 2008 R2中,将数据库作为文件备份到文件夹中。
    然后选择"数据库"文件夹中显示的还原选项。
    在向导中,在目标数据库中输入所需的新名称。
    并选择restore frrom文件并使用刚刚创建的文件。
    我jsut做了它并且它非常快(我的DB很小,但仍然)
    巴勃罗。


    该解决方案基于此评论:https://stackoverflow.com/a/22409447/2399045。
    只需设置设置:DB名称,临时文件夹,db文件夹。
    运行后,您将拥有"sourceDBName_yyyy-mm-dd"格式的DB副本。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    -- Settings --
    -- New DB name will have name = sourceDB_yyyy-mm-dd
    declare @sourceDbName nvarchar(50) = 'MyDbName';
    declare @tmpFolder nvarchar(50) = 'C:\Temp\'
    declare @sqlServerDbFolder nvarchar(100) = 'C:\Databases\'

    --  Execution --
    declare @sourceDbFile nvarchar(50);
    declare @sourceDbFileLog nvarchar(50);
    declare @destinationDbName nvarchar(50) = @sourceDbName + '_' + (select convert(varchar(10),getdate(), 121))
    declare @backupPath nvarchar(400) = @tmpFolder + @destinationDbName + '.bak'
    declare @destMdf nvarchar(100) = @sqlServerDbFolder + @destinationDbName + '.mdf'
    declare @destLdf nvarchar(100) = @sqlServerDbFolder + @destinationDbName + '_log' + '.ldf'

    SET @sourceDbFile = (SELECT top 1 files.name
                        FROM sys.databases dbs
                        INNER JOIN sys.master_files files
                            ON dbs.database_id = files.database_id
                        WHERE dbs.name = @sourceDbName
                            AND files.[type] = 0)

    SET @sourceDbFileLog = (SELECT top 1 files.name
                        FROM sys.databases dbs
                        INNER JOIN sys.master_files files
                            ON dbs.database_id = files.database_id
                        WHERE dbs.name = @sourceDbName
                            AND files.[type] = 1)

    BACKUP DATABASE @sourceDbName TO DISK = @backupPath

    RESTORE DATABASE @destinationDbName FROM DISK = @backupPath
    WITH REPLACE,
       MOVE @sourceDbFile     TO @destMdf,
       MOVE @sourceDbFileLog  TO @destLdf

    如果数据库不是很大,您可以查看SQL Server Management Studio Express中的"脚本数据库"命令,这些命令位于资源管理器中数据库项本身的上下文菜单中。

    你可以选择所有脚本;当然,你想要对象和数据。然后,您将整个脚本保存到单个文件中。然后您可以使用该文件重新创建数据库;只需确保顶部的USE命令设置为正确的数据库。


    您可以创建一个新数据库,然后转到任务,导入数据,并将要复制的数据库中的所有数据导入到刚创建的数据库中。


    基于Joe回答的脚本(分离,复制文件,附加两者)。

  • 以管理员帐户运行Managment Studio。
  • 这没有必要,但可能在执行时拒绝访问错误。

  • 配置sql server以执行xp_cmdshel
  • 1
    2
    3
    4
    5
    6
    7
    8
    EXEC sp_configure 'show advanced options', 1
    GO
    RECONFIGURE
    GO
    EXEC sp_configure 'xp_cmdshell', 1
    GO
    RECONFIGURE
    GO
  • 运行脚本,但之前在@dbName@copyDBName变量中键入数据库名称。
  • 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    USE master;
    GO

    DECLARE @dbName NVARCHAR(255) = 'Products'
    DECLARE @copyDBName NVARCHAR(255) = 'Products_branch'

    -- get DB files
    CREATE TABLE ##DBFileNames([FileName] NVARCHAR(255))
    EXEC('
        INSERT INTO ##DBFileNames([FileName])
        SELECT [filename] FROM ' + @dbName + '.sys.sysfiles')

    -- drop connections
    EXEC('ALTER DATABASE ' + @dbName + ' SET OFFLINE WITH ROLLBACK IMMEDIATE')

    EXEC('ALTER DATABASE ' + @dbName + ' SET SINGLE_USER')

    -- detach
    EXEC('EXEC sp_detach_db @dbname = ''' + @dbName + '''')

    -- copy files
    DECLARE @filename NVARCHAR(255), @path NVARCHAR(255), @ext NVARCHAR(255), @copyFileName NVARCHAR(255), @command NVARCHAR(MAX) = ''
    DECLARE
        @oldAttachCommand NVARCHAR(MAX) =
            'CREATE DATABASE ' + @dbName + ' ON ',
        @newAttachCommand NVARCHAR(MAX) =
            'CREATE DATABASE ' + @copyDBName + ' ON '

    DECLARE curs CURSOR FOR
    SELECT [filename] FROM ##DBFileNames
    OPEN curs  
    FETCH NEXT FROM curs INTO @filename
    WHILE @@FETCH_STATUS = 0  
    BEGIN
        SET @path = REVERSE(RIGHT(REVERSE(@filename),(LEN(@filename)-CHARINDEX('\', REVERSE(@filename),1))+1))
        SET @ext = RIGHT(@filename,4)
        SET @copyFileName = @path + @copyDBName + @ext

        SET @command = 'EXEC master..xp_cmdshell ''COPY"' + @filename + '""' + @copyFileName + '"'''
        PRINT @command
        EXEC(@command);

        SET @oldAttachCommand = @oldAttachCommand + '(FILENAME ="' + @filename + '"),'
        SET @newAttachCommand = @newAttachCommand + '(FILENAME ="' + @copyFileName + '"),'

        FETCH NEXT FROM curs INTO @filename
    END
    CLOSE curs
    DEALLOCATE curs

    -- attach
    SET @oldAttachCommand = LEFT(@oldAttachCommand, LEN(@oldAttachCommand) - 1) + ' FOR ATTACH'
    SET @newAttachCommand = LEFT(@newAttachCommand, LEN(@newAttachCommand) - 1) + ' FOR ATTACH'

    -- attach old db
    PRINT @oldAttachCommand
    EXEC(@oldAttachCommand)

    -- attach copy db
    PRINT @newAttachCommand
    EXEC(@newAttachCommand)

    DROP TABLE ##DBFileNames

    另一种通过使用导入/导出向导完成技巧的方法,首先创建一个空数据库,然后选择源服务器和源数据库,然后在目标中选择与目标数据库相同的服务器(使用空数据库)你最初创建的,然后点击完成

    它将创建所有表并将所有数据传输到新数据库中,