简体   繁体   English

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

[英]SQL Server specify mdf file name when restoring database

I'm trying to restore a database from a BAK file using the following command to perform unit test on a clean copy of the db: 我正在尝试使用以下命令从BAK文件还原数据库,以对db的干净副本执行单元测试:

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

it tries to restore the database bu throws an error that MyDb.mdf is in use - and it's correct - it is - by the original database that's used for development on my machine. 它尝试还原数据库,但会抛出一个错误,表明MyDb.mdf正在使用-正确-是-用于在我的机器上进行开发的原始数据库。

Is there a way to specify the name of the MDF file that it will import it along side the development db? 有没有办法指定MDF文件的名称,它将在开发数据库旁边导入该文件?

This might be because you have a tail-log backup being done on the restore. 可能是因为您在还原中完成了尾日志备份。

Change to this: 更改为此:

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

Please note the numbers listed pertain to an example of my environment, so you need to ensure you modify this to fit your needs. 请注意,所列数字与我的环境示例有关,因此您需要确保对其进行修改以适合您的需求。

Another way to do this without a script is to simply right click on the database name in management studio and select Tasks->Restore->Database . 无需脚本即可执行此操作的另一种方法是,只需在Management Studio中右键单击数据库名称,然后选择Tasks-> Restore-> Database Then on the options tab remove the "Take tail-log backup before restore" option. 然后在“选项”选项卡上,删除“还原前进行尾日志备份”选项。

Easiest way to do that is to do it from within management studio and have management studio generate the script for you as shown: 最简单的方法是在Management Studio中进行操作,并让Management Studio为您生成脚本,如下所示:

在此处输入图片说明

You need to know whats in this backup file. 您需要知道此备份文件中的内容。 Therefore you need to check the content of this file by doing two types of restores before you can actually resotre a database from this backup. 因此,您需要通过执行两种类型的还原来检查此文件的内容,然后才能实际从该备份中重新分配数据库。

HEADERONLY RESTORE 强力恢复

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

This will give the list of backups in this backup file. 这将提供此备份文件中的备份列表。 You should be looking for database MyDb with Backup type = 1. Get the position of that file and do the following 您应该使用备份类型= 1查找数据库MyDb 。获取该文件的位置,然后执行以下操作

FILELISTONLY RESTORE FILELISTONLY还原

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

This will return all the files for that database in that backup. 这将返回该备份中该数据库的所有文件。

Primary file , any .ndf and Log file name. 主文件,任何.ndf和日志文件名。

Use these file names and write the restore command like this.... 使用这些文件名并编写恢复命令,如下所示。...

Database Restore 数据库还原

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

Here's what I use (in a batch file) to restore a specific already-existing database from backup. 这是我使用的(在批处理文件中)从备份还原特定的现有数据库的方法。 The "Replace" causes it to over-write the existing files, so I don't need to specify them. “替换”使它覆盖现有文件,因此无需指定它们。

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

This may not serve your needs exactly , but I thought it might be useful for others searching on this issue. 这可能无法完全满足您的需求, 但我认为这可能对其他搜索此问题的人有用。

(Obviously you'd either set environment variables DatatbaseName, DestinationFold, and backupFile ... or replace those place-holders with the hard-coded names and paths and such for your specific purpose... just wanted to be clear about that) (显然,您可以设置环境变量DatatbaseName,DestinationFold和backupFile…或将这些占位符替换为硬编码的名称和路径,并根据您的特定目的进行替换……只是想清楚一点)

(And if you just script out creating the database you want to restore to first, then restoring to it WITH REPLACE should work as well, leaving you both your original database, and the restored copy of it, both functional, as expected) (并且,如果您只编写脚本来创建要还原的数据库,那么使用REPLACE还原到数据库也应该可以正常工作,这样既可以保留原始数据库,也可以保留还原的副本,两者都可以正常工作)

For the sake of being even more relevant, here's a script I cobbled together that will restore any backup to any database (whether it exists or not), and does the appropriate MOVE to always work: 为了更加相关,这是我拼凑而成的脚本,该脚本会将所有备份还原到任何数据库(无论是否存在),并执行适当的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

Just edit the two constants at the top of the script, to specify the database name to restore to (whether or not it already exists), and the full path to the backup file you wish to restore. 只需编辑脚本顶部的两个常量,以指定要还原到的数据库名称(是否已经存在),以及要还原的备份文件的完整路径。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM