By: Mike Eastland | Updated: 2013-11-22 | Comments (15) | Related: > Restore
Problem
A recent tip related to RESTORE operations reminded me of something I've wanted to share for quite some time. I frequently restore production databases to various development servers. The drive layouts between the servers are almost never the same. I am constantly shuffling files on my development servers due to space constraints, which in turn breaks the automated restore scripts because the MOVE clauses are invalidated. Do I have to use the MOVE clause every time I do a restore?
Solution
The short answer is NO...but stopping there wouldn't make a very worthwhile tip. So let's work through an example scenario to illustrate.
Prerequisites
While the code within this tip was developed and tested against a SQL Server 2005 instance, it should function on any version currently in use. The scenario assumes that the AdventureWorks sample database has been attached. SQL Server sample databases can be found on codeplex.
Disclaimer
The paths used in the code may need to be updated to reflect the folder structure in use by your environment.
Code to test SQL Restore
First, drop the test database "AdventureWorksCopy" used by the RESTORE commands, if it already exists.
USE [master]
GO
IF DB_ID('AdventureWorksCopy') IS NOT NULL
BEGIN
ALTER DATABASE [AdventureWorksCopy] SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
DROP DATABASE [AdventureWorksCopy];
END
Next, review the current layout of the database files.
USE [master]
GO
SELECT DB_NAME([database_id]) [database_name] , [file_id] , [type_desc] [file_type] , [name] [logical_name] , [physical_name]
FROM sys.[master_files]
WHERE [database_id] IN (DB_ID('AdventureWorks'), DB_ID('AdventureWorksCopy'))
ORDER BY [type], DB_NAME([database_id]);
The query should only return two rows at this point, one each for the data and log file associated with the AdventureWorks database.
Backup the AdventureWorks database.
GO
BACKUP DATABASE [AdventureWorks] TO DISK = 'c:\mssql\backup\yukon\AW2K5_Full.bak'
WITH CHECKSUM, COPY_ONLY, FORMAT, INIT, STATS = 10;
Attempt to restore a copy of the AdventureWorks database to AdventureWorksCopy without using the MOVE clause.
GO
RESTORE DATABASE [AdventureWorksCopy] FROM DISK = 'c:\mssql\backup\yukon\AW2K5_Full.bak'
WITH CHECKSUM, RECOVERY, REPLACE, STATS = 10;
An error similar to the following is returned because the RESTORE command is attempting to overwrite files already in use by the source database.
The file 'C:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\Data\AdventureWorks_Data.mdf' cannot be overwritten. It is being used by database 'AdventureWorks'.
Msg 3156, Level 16, State 4, Line 1
File 'AdventureWorks_Data' cannot be restored to 'C:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\Data\AdventureWorks_Data.mdf'. Use WITH MOVE to identify a valid location for the file.
Msg 1834, Level 16, State 1, Line 1
The file 'C:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\Data\AdventureWorks_Log.ldf' cannot be overwritten. It is being used by database 'AdventureWorks'.
Msg 3156, Level 16, State 4, Line 1
File 'AdventureWorks_Log' cannot be restored to 'C:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\Data\AdventureWorks_Log.ldf'. Use WITH MOVE to identify a valid location for the file.
Msg 3119, Level 16, State 1, Line 1
Problems were identified while planning for the RESTORE statement. Previous messages provide details.
Msg 3013, Level 16, State 1, Line 1
RESTORE DATABASE is terminating abnormally.
Now execute the restore command using the MOVE clause.
GO
RESTORE DATABASE [AdventureWorksCopy] FROM DISK = 'c:\mssql\backup\yukon\AW2K5_Full.bak'
WITH CHECKSUM,
MOVE 'AdventureWorks_Data' TO 'c:\mssql\data\yukon\AdventureWorksCopy_Data.mdf',
MOVE 'AdventureWorks_Log' TO 'c:\mssql\log\yukon\AdventureWorksCopy_Log.ldf',
RECOVERY, REPLACE, STATS = 10;
The restore completes successfully as expected.
20 percent processed.
30 percent processed.
40 percent processed.
50 percent processed.
60 percent processed.
70 percent processed.
80 percent processed.
90 percent processed.
100 percent processed.
Processed 20576 pages for database 'AdventureWorksCopy', file 'AdventureWorks_Data' on file 1.
Processed 1 pages for database 'AdventureWorksCopy', file 'AdventureWorks_Log' on file 1.
RESTORE DATABASE successfully processed 20577 pages in 6.501 seconds (25.929 MB/sec).
What if we try the restore again without the MOVE clause?
GO
RESTORE DATABASE [AdventureWorksCopy] FROM DISK = 'c:\mssql\backup\yukon\AW2K5_Full.bak'
WITH CHECKSUM, RECOVERY, REPLACE, STATS = 10;
The restore completes successfully once again, even though we omitted the MOVE clause.
Review the file layout of both databases using the same query as before.
GO
SELECT
DB_NAME([database_id]) [database_name]
, [file_id]
, [type_desc] [file_type]
, [name] [logical_name]
, [physical_name]
FROM sys.[master_files]
WHERE [database_id] IN (DB_ID('AdventureWorks'), DB_ID('AdventureWorksCopy'))
ORDER BY [type], DB_NAME([database_id]);
Notice that both databases have the same two file_id values, even though the physical paths are different.
Conclusion
As long as the database being restored already has the same number and type of files to match those contained in the backupset being restored, the MOVE clause is not required. This functionality offers additional flexibility in automating regularly-scheduled restore operations.
Next Steps
- Review any scheduled restore jobs that may be improved by omitting the MOVE clause where possible.
- Check out other mssqltips related to backup and restore operations.
About the author
This author pledges the content of this article is based on professional experience and not AI generated.
View all my tips
Article Last Updated: 2013-11-22