SQL Server在还原数据库时指定mdf文件名

时间:2015-02-25 19:01:48

标签: sql sql-server tsql

我尝试使用以下命令从BAK文件恢复数据库,以便在数据库的干净副本上执行单元测试:

RESTORE DATABASE MyDbUnitTest FROM DISK = 'c:\db\MyDb.bak';

它尝试恢复数据库bu抛出MyDb.mdf正在使用的错误 - 它是正确的 - 它是 - 用于我的机器上用于开发的原始数据库。

有没有办法指定MDF文件的名称,它将在开发db旁边导入它?

3 个答案:

答案 0 :(得分:1)

可能,因为您在还原时已完成尾部日志备份。

更改为:

RESTORE DATABASE [MyDB2] FROM  DISK = N'C:\db\MyDb.BAK' WITH  FILE = 1,  MOVE N'MyDb' TO N'C:\db\MyDb2.mdf',  MOVE N'Mydb_log' TO N'D:\SQLLogs\MyDb2_log.ldf',  NORECOVERY,  NOUNLOAD,  STATS = 5
RESTORE LOG [MyDB2] FROM  [MyDB_Log] WITH  FILE = 3,  NOUNLOAD,  STATS = 5

请注意列出的数字与我的环境示例有关,因此您需要确保修改此数字以满足您的需求。

在没有脚本的情况下执行此操作的另一种方法是只需右键单击management studio中的数据库名称,然后选择任务 - >恢复 - >数据库。然后在选项选项卡上删除“恢复前进行尾部日志备份”选项。

最简单的方法是在管理工作室内完成,并让管理工作室为您生成脚本,如下所示:

enter image description here

答案 1 :(得分:0)

您需要知道此备份文件中的最新信息。因此,您需要通过执行两种类型的还原来检查此文件的内容,然后才能从此备份实际重新定位数据库。

HEADERONLY RESTORE

RESTORE HEADERONLY 
FROM DISK = N'c:\db\MyDb.bak'
GO

这将提供此备份文件中的备份列表。您应该查找备份类型= 1的数据库MyDb。获取该文件的位置并执行 以下

FILELISTONLY RESTORE

RESTORE FILELISTONLY 
FROM DISK = N'c:\db\MyDb.bak'
 WITH FILE = 1   --<-- this will be the position of the backup from headerOnly restore
GO

这将返回该备份中该数据库的所有文件。

主文件,任何.ndf和日志文件名。

使用这些文件名并像这样编写恢复命令....

数据库恢复

RESTORE [DatabaseName]
 FROM DISK = N'c:\db\MyDb.bak'
 WITH RECOVERY , 
 MOVE N'PrimaryFile' TO N'C:\Folder\MyDB.mdf',    --<-- should be a valid path
 MOVE N'LogFile'     TO N'C:\Folder\MyDB_Logs.ldf' --<-- should be a valid path
 -- anymore files ......
 GO

答案 2 :(得分:-3)

这是我使用(在批处理文件中)从备份恢复特定的现有数据库的内容。 &#34;替换&#34;导致它覆盖现有文件,因此我不需要指定它们。

RESTORE DATABASE [%DatabaseName%] 
FROM DISK = N'%DestinationFolder%\%backupFile%' 
WITH FILE = 1, NOUNLOAD, REPLACE, STATS = 10

这可能无法满足您的需求完全,但我认为这可能对其他人搜索此问题很有用。

(显然,你要么设置环境变量DatatbaseName,DestinationFold和backupFile ......要么用硬编码的名称和路径替换那些占位符,以满足你的特定目的......只是想成为清楚这一点)

(如果您只是编写要创建要首先恢复的数据库的脚本,那么恢复到它WITH REPLACE也应该可以正常工作,保留原始数据库及其恢复的副本,两者都是正常的,如预期的那样)

为了更加相关,这里有一个我拼凑在一起的脚本,可以将任何备份恢复到任何数据库(无论是否存在),并使相应的MOVE始终有效:

USE master;

DECLARE @dbNameDestination sysname
DECLARE @backupFileName nvarchar(max)
DECLARE @sql nvarchar(max)
DECLARE @restoreSql nvarchar(max)
DECLARE @params nvarchar(max)
DECLARE @mdfFile nvarchar(400)
DECLARE @ldfFile nvarchar(400)

SET @dbNameDestination = 'TestUserTest'   -- The name of the database you want to restore to
SET @backupFileName = 'D:\DB\TestDB.bak'  -- The full path to the *.bak file you wish to restore

IF NOT EXISTS (SELECT 1 FROM sys.databases WHERE [name] = @dbNameDestination)
BEGIN
    -- Create Destination DB
    SET @sql = 'CREATE DATABASE [' + @dbNameDestination + ']'
    EXEC (@sql)
END
ELSE
BEGIN
    -- Force other users off:
    SET @sql = 'ALTER DATABASE [' + @dbNameDestination + '] SET SINGLE_USER WITH ROLLBACK IMMEDIATE'
    EXEC (@sql);
    SET @sql = 'ALTER DATABASE [' + @dbNameDestination + '] SET MULTI_USER'
    EXEC (@sql);
END

-- Restore database WITH REPLACE
SET @params = '@mdfOUT nvarchar(400) OUTPUT, @ldfOut nvarchar(400) OUTPUT'
SET @sql = N'USE ' + @dbNameDestination + N';
SELECT @mdfOUT = physical_name FROM sys.database_files WHERE type = 0
SELECT @ldfOUT = physical_name FROM sys.database_files WHERE type = 1'
EXEC sp_ExecuteSql @sql, @params, @mdfOUT=@mdfFile OUTPUT, @ldfOUT=@ldfFile OUTPUT

DECLARE @FileList TABLE ( 
    LogicalName nvarchar(128) NOT NULL, 
    PhysicalName nvarchar(260) NOT NULL, 
    Type char(1) NOT NULL, 
    FileGroupName nvarchar(120) NULL, 
    Size numeric(20, 0) NOT NULL, 
    MaxSize numeric(20, 0) NOT NULL, 
    FileID bigint NULL, 
    CreateLSN numeric(25,0) NULL, 
    DropLSN numeric(25,0) NULL, 
    UniqueID uniqueidentifier NULL, 
    ReadOnlyLSN numeric(25,0) NULL , 
    ReadWriteLSN numeric(25,0) NULL, 
    BackupSizeInBytes bigint NULL, 
    SourceBlockSize int NULL, 
    FileGroupID int NULL, 
    LogGroupGUID uniqueidentifier NULL, 
    DifferentialBaseLSN numeric(25,0)NULL, 
    DifferentialBaseGUID uniqueidentifier NULL, 
    IsReadOnly bit NULL, 
    IsPresent bit NULL, 
    TDEThumbprint varbinary(32) NULL 
 ); 

SET @restoreSql =  N'RESTORE FILELISTONLY FROM DISK=N''' + @backupFileName + '''' 
INSERT INTO @FileList EXEC(@restoreSql); 

DECLARE @logical_data nvarchar(max)
DECLARE @logical_log nvarchar(max); 
SET @logical_data = (SELECT [LogicalName] FROM @FileList WHERE [Type] = 'D' AND [FileID] = 1) 
SET @logical_log = (SELECT [LogicalName] FROM @FileList WHERE [Type] = 'L' AND [FileID] = 2) 

-- Now issue RESTORE command
RESTORE DATABASE @dbNameDestination 
FROM DISK = @backupFileName 
WITH REPLACE,
MOVE @logical_data TO @mdfFile, 
MOVE @logical_log TO @ldfFile 
GO

只需编辑脚本顶部的两个常量,指定要还原到的数据库名称(无论它是否已存在),以及要还原的备份文件的完整路径。