Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
SQL Server在还原数据库时指定mdf文件名_Sql_Sql Server_Tsql - Fatal编程技术网

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

SQL Server在还原数据库时指定mdf文件名,sql,sql-server,tsql,Sql,Sql Server,Tsql,我正在尝试使用以下命令从BAK文件还原数据库,以对数据库的干净副本执行单元测试: RESTORE DATABASE MyDbUnitTest FROM DISK = 'c:\db\MyDb.bak'; 它试图还原数据库,但抛出了一个错误,即MyDb.mdf正被我的机器上用于开发的原始数据库使用,这是正确的 有没有办法指定MDF文件的名称,它将随开发数据库一起导入该文件?这可能是因为您在还原时有一个尾部日志备份 更改为: RESTORE DATABASE [MyDB2] FROM DISK =

我正在尝试使用以下命令从BAK文件还原数据库,以对数据库的干净副本执行单元测试:

RESTORE DATABASE MyDbUnitTest FROM DISK = 'c:\db\MyDb.bak';
它试图还原数据库,但抛出了一个错误,即MyDb.mdf正被我的机器上用于开发的原始数据库使用,这是正确的


有没有办法指定MDF文件的名称,它将随开发数据库一起导入该文件?

这可能是因为您在还原时有一个尾部日志备份

更改为:

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
请注意,列出的数字与“我的环境”的一个示例有关,因此您需要确保对其进行修改以满足您的需要。

不使用脚本的另一种方法是在ManagementStudio中右键单击数据库名称,然后选择任务->恢复->数据库。然后在“选项”选项卡上删除“在还原之前进行尾部日志备份”选项

最简单的方法是从management studio内部执行,并让management studio为您生成脚本,如图所示:

以下是我(在批处理文件中)用于从备份中恢复特定的现有数据库的内容。“Replace”会导致它重写现有文件,所以我不需要指定它们

RESTORE DATABASE [%DatabaseName%] 
FROM DISK = N'%DestinationFolder%\%backupFile%' 
WITH FILE = 1, NOUNLOAD, REPLACE, STATS = 10
这可能不能完全满足您的需要,但我认为它可能对其他搜索此问题的人有用。

(显然,您要么设置环境变量DatatbaseName、DestinationFold和backupFile……要么将这些占位符替换为硬编码的名称和路径等,以实现您的特定目的……只是想弄清楚这一点)

(如果您只是先创建要还原到的数据库,然后使用REPLACE还原到该数据库,那么也应该可以正常工作,让您的原始数据库和还原后的副本都能正常工作)

为了更具相关性,我拼凑了一个脚本,它可以将任何备份恢复到任何数据库(无论是否存在),并执行适当的移动以始终工作:

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

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

您需要知道此备份文件中的内容。因此,您需要通过执行两种类型的恢复来检查此文件的内容,然后才能实际从此备份中恢复数据库

正面恢复

RESTORE HEADERONLY 
FROM DISK = N'c:\db\MyDb.bak'
GO
RESTORE FILELISTONLY 
FROM DISK = N'c:\db\MyDb.bak'
 WITH FILE = 1   --<-- this will be the position of the backup from headerOnly restore
GO
这将给出此备份文件中的备份列表。您应该查找备份类型为1的数据库
MyDb
。获取该文件的位置并执行以下操作 以下

仅恢复文件列表

RESTORE HEADERONLY 
FROM DISK = N'c:\db\MyDb.bak'
GO
RESTORE FILELISTONLY 
FROM DISK = N'c:\db\MyDb.bak'
 WITH FILE = 1   --<-- this will be the position of the backup from headerOnly restore
GO
仅还原文件列表
FROM DISK=N'c:\db\MyDb.bak'

WITH FILE=1——sql server的哪个版本?您想在MOVE中使用
。这是。John你怎么知道日志备份在备份文件的第3位???或者后卫在位置1??您是如何获得所有这些信息的?@M.Ali-这是一个使用我的数据库的示例,他需要修改这些信息以满足他的需要。最简单的方法是使用我的第二个建议,并从中生成一个脚本。然后你会给这个人一个工具来捕捉鱼,OP需要执行restore
FILELISTONLY
HEADERONLY
以实际获取备份文件位置和文件名,然后使用restore命令恢复数据库并将文件移动到适当的位置。@M.Ali-当我发布答案时请耐心等待,因为我添加了与我的备份文件相关的特定信息环境不要这么快做出判断。你的第一句话是
,这是因为你在还原时有一个尾部日志备份。
我不是说你的脚本不起作用(因为用MOVE可以解决实际问题),我只是说你的错误声明不一定是真的。我可以复制OP遇到的问题,而不引入任何日志问题。@MAli我的猜测是酸葡萄和一个假设,即你也是一个失败的选民@阿伦伯特朗:是的,没错:)评论不是为了进行广泛的讨论;这段对话已经结束。