Question

I created a backup of an SQL Server database like this:

BACKUP DATABASE [foo] TO DISK = '\path\to\database.bak'

Now I want to restore the database to a different name on the same SQL Server instance, while the original database foo still exists. This is the command I try to use:

RESTORE DATABASE [bar] FROM DISK = '\path\to\database.bak'

When I try this in SSMS, I get a bunch of error messages telling me that foo.mdf and foo_log.ldf cannot be overwritten because they are in use by database foo. From what I have read so far on SO and other places, to resolve this issue I must use the MOVE option of the RESTORE command and specify a filesystem path!!! I have a hard time accepting that: I mean, SQL Server is a database server, and it forces me to deal with low-level filesystem details to perform a database restore?!?

Is there a way how I can tell SQL Server to automatically figure out the names of the .mdf and .ldf files based on the name of the database that I am restoring to? Maybe I need to change something about the backup command? Or maybe I can use a different, higher-level API than "backup database" / "restore database"?

Note that my use case guarantees that the database that I am restoring to does not exist.

EDIT: Interactive solutions are not an option, I need to perform the restore programmatically.

Was it helpful?

Solution 2

As there appears to be no elegant solution to the problem, I bit the bullet and implemented something that seems to work - for now. Although this is not a real answer to my question, I thought someone else might benefit from the following thoughts.


Here is a rough outline of my implementation (tested on SQL Server 2012):

  1. Create a temporary database bar
  2. Get the real logical and physical file names from the system table with SELECT * FROM sys.master_files WHERE database_id = DB_ID('bar')
  3. Drop the temporary database bar
  4. Get the backup logical and physical file names from the backup with RESTORE FILELISTONLY FROM DISK = '\path\to\database.bak'
  5. Make sure that for each file in the backup (obtained in step 4) we have corresponding real logical/physical file names (obtained in step 2)
  6. Restore the database with RESTORE DATABASE [bar] FROM DISK = '\path\to\database.bak'. Add one MOVE statement for each file in the backup where the logical file name from the backup is mapped to the real physical file name (obtained in step 2).
  7. The restored database still has the wrong logical names from the backup, so fix these as well with ALTER DATABASE [bar] MODIFY FILE (name = 'backup_logical_filename', newname = 'real_logical_filename'). Repeat for each database file.

The approach of creating a temporary database to obtain "real" information about database files (steps 1-3) allows to delegate at least a few things to the DBMS:

  • Filesystem locations are correct as per the DBA's server configuration (e.g. separate locations for data files and transaction logs)
  • Mapping of database name to file name filesystem name (e.g. if the database name contains characters that are not valid in file names, such as the ":" character)

When matching up real file names and backup file names (e.g. in step 5), the file types in sys.master_files and in the backup are not the same:

  • The file types in sys.master_files are "ROWS" and "LOG" (or 0 and 1 if you prefer the numerical file type)
  • The file types in the backup are "D" and "L"

OTHER TIPS

There error of sql server is raised because files are currently belongs to foo database, this behavior is default because normally dba's backup a database and restore it on itself (in case of disaster or corruption), but for you there are two options, one in the Management studio just change the name of .mdf and .ldf files (do not need to put them in a totally new path) and also Sql 2012 has made it easier with a new option, another way is setting new file names in your scripts. This is example:

RESTORE DATABASE AdventureWorks FROM DISK = 'C:\AdventureWorks.BAK'
WITH MOVE 'AdventureWorks_Data' TO 'G:\SQLData\AdvnetureWorks_Data.mdf',
MOVE 'AdventureWorks_Log' TO 'H:\SQLData\AdvnetureWorks_Log.ldf'
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top