27

I am getting an error using SQL Server 2012 when restoring a backup made with a previous version (SQL Server 2008). I actually have several backup files of the same database (taken at different times in the past). The newest ones are restored without any problems; however, one of them gives the following error:

System.Data.SqlClient.SqlError: Directory lookup for the file "C:\PROGRAM FILES\MICROSOFT SQL SERVER\MSSQL.1\MSSQL\DATA\MYDB_ABC.MDF" failed with the operating system error 3(The system cannot find the path specified.). (Microsoft.SqlServer.SmoExtended)

This is a x64 machine, and my database file(s) are in this location: c:\Program Files\Microsoft SQL Server\MSSQL11.MSSQLSERVER\MSSQL.

I do not understand why it tries to restore on MSSQL.1 and not MSSQL11.MSSQLSERVER.

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Marius Bancila
  • 16,053
  • 9
  • 49
  • 91
  • 3
    This has nothing to do with version problems. (The message tells you that) – usr May 24 '12 at 16:30
  • @marc_s, why do you people feel obliged to alter the questions? I could understand the bold, but not the title, the quote, the ending, etc. – Marius Bancila May 25 '12 at 06:46
  • @usr, I mentioned SQL Server 2012, because the problems does not occur on machines with SQL Serve 2008. So, I guess, there is a connection. – Marius Bancila May 25 '12 at 06:47
  • @MariusBancila: the system used belongs into the tags - not the title - that's what the tags are for. Path and table names etc. should be put between back quotes to make them stand out as such (bold isn't optimal for that). I was just trying to make your question look more like a well formatted question - but OK, if you don't like it - I'll try to never touch any of your questions anymore..... – marc_s May 25 '12 at 07:47
  • This answers below don't directly address the context Marius was working in (that of the SMO), using c# or powershell; these answers are work arounds, and using WITH MOVE eventually gets things working. For example, restore using WITH MOVE from 2008 to 2012, then retry the SMO method and it will work. Because the internal paths and structures have been updated. The answer why is here: http://dba.stackexchange.com/questions/73541/with-replace-restore-failing-with-same-logical-filenames – SnapJag Jun 30 '16 at 23:16
  • OP mentions doing restore using c# in comments (and his own answer) down this page - not in the question - not very helpful! – Brett Spencer Jun 14 '21 at 18:46

14 Answers14

41

Sounds like the backup was taken on a machine whose paths do not match yours. Try performing the backup using T-SQL instead of the UI. Also make sure that the paths you're specifying actually exist, that the SQL Server service account has the ability to write there, and that there aren't already copies of these files there.

RESTORE DATABASE MYDB_ABC 
  FROM DISK = 'C:\path\file.bak'
  WITH MOVE 
            /* this is the logical data file name, not the path: */
            'mydb_logical_data_filename' 

         TO 
            /* this is the physical data file path: */
            'c:\valid_data_path\MYDB_ABC.mdf',

       MOVE 
            /* this is the logical log file name, not the path: */
            'mydb_logical_log_filename' 

         TO 
            /* this is the physical log file path: */
            'c:\valid_log_path\MYDB_ABC.ldf';

From the documentation, Restore a Database to a New Location (SQL Server):

Restore syntax

Aaron Bertrand
  • 272,866
  • 37
  • 466
  • 490
  • the backup was taken on another machine yes. I'm doing the restore from code, but I get the same result when I do it from SQL server 2012 UI. No problems on machines with SQL Server 2008 – Marius Bancila May 25 '12 at 06:27
  • in my SQL Server 2012 (machine 1) the default database location is C:\Program Files\Microsoft SQL Server\MSSQL11.MSSQLSERVER\MSSQL\DATA. in SQL Server 2008 (machine 2) the default database location is C:\Program Files\Microsoft SQL Server\MSSQL10_50.MARIUSPC\MSSQL\DATA. Restore from the same detabase fails with SQL Server 2012 but succeeds with SQL Server 2008. So what's that setting that says "if the default location from the backup" is not available on this machine use the default? Because that's what it looks like it happens with 2008 – Marius Bancila May 25 '12 at 08:11
  • I had the same issue. The backup which i tool was of SQL Server 2016 and i was trying to restore it at SQL Server 2016, but it was not working. Backup which i took was of 13.0.5201.2 which was a Cumulative Update on SQL 2016, and the one i had on which i was trying to restore the backup was running as 13.0.1601.5 which is not even a service packed with. So, what i did, i downloaded service pack 2 (13.0.5026.0) and then installed CU 13.0.5201.2 on it and it worked. You can find all versions [MSSQL 2016 Versions](https://support.microsoft.com/en-us/help/3177312/sql-server-2016-build-versions) – Atta H. May 01 '19 at 18:26
  • Yes, this is the right answer but the `MOVE` clause expects the **`LogicalName`** of the file and not the physical path! I wasted an hour on that one! I kept getting `Logical file 'C:\Program Files\Microsoft SQL Server\ugly\ass\path\my file.mdf' is not part of database 'mydb_name'. Use RESTORE FILELISTONLY to list the logical file names.` When you do so, look at the first field `LogicalName`, and not `PhysicalName` – Daniel Santos Jun 10 '23 at 02:38
  • @DanielSantos Where did my answer suggest putting the physical path into the first argument of the `MOVE` clause? I've made it more clear but I don't think that idea came from me. – Aaron Bertrand Jun 10 '23 at 11:45
  • @AaronBertrand Hello! Well first off your question comes off as rude, but perhaps that was not your intention. I like your improvements! The problem is that given the context, and without deeper knowledge of mssql server, the physical path is arguably *implied*. Nowhere in the question, error message, or your previous answer is the *logical* name mentioned, only the physical name. I blame upstream first. A better error message would specify the context, e.g., `Directory lookup for file LogicalName="mydb_data", PhysicalName="C:\\.mdf" failed with [...]`. – Daniel Santos Jun 11 '23 at 21:47
  • @DanielSantos /shrug, ok, I didn't write the error messages in SQL Server, and also if you think my response was rude, I wonder if you noticed that you implied that _my answer_ is the thing that caused you to waste an hour of your time? – Aaron Bertrand Jun 12 '23 at 12:36
  • @AaronBertrand Either way, your answer is awesome now, so our experience of each other coming off as rude has been helpful to the community. Of course I'm not blaming you for the upstream error message, I'm simply citing what I believe to be the *primary* cause of me wasting an hour -- not that I'm *that* concerned about my wasted hour of frustration, but it's easy to interpolate and conclude similar misunderstandings for others. Thank you for your time and effort on this. – Daniel Santos Jun 13 '23 at 21:26
25

When restoring, under Files, check 'Relocate all files to folder'

check 'Relocate all files to folder'

Hypenate
  • 1,907
  • 3
  • 22
  • 38
  • 2
    Although not the answer to this specific Q because he is doing it in code, it save my butt and is very useful, thanks man. – After_Sunset Apr 28 '20 at 22:08
10

The backup stores the original location of the database files and, by default, attempts to restore to the same location. Since your new server installation is in new directories and, presumably, the old directories no longer exist, you need to alter the directories from the defaults to match the location you wish it to use.

Depending on how you are restoring the database, the way to do this will differ. If you're using SSMS, look through the tabs and lists until you find the list of files and their associated disk locations - you can then edit those locations before restoring.

Daniel Renshaw
  • 33,729
  • 8
  • 75
  • 94
7

I have managed to do this from code. This was not enough

Restore bkp = new Restore();
bkp.PercentCompleteNotification = 1;
bkp.Action = RestoreActionType.Database;
bkp.Database = sDatabase;
bkp.ReplaceDatabase = true;

The RelocateFiles property must be filled with the names and paths of the files to be relocated. For each file you must specify the name of the file and the new physical path. So what I did was looking at the PrimaryFilePath of the database I was restoring to, and use that as the physical location. Something like this:

if (!string.IsNullOrEmpty(sDataFileName) && !File.Exists(sDataFileName))
{
   if (originaldb != null)
   {
      if (string.Compare(Path.GetDirectoryName(sDataFileName), originaldb.PrimaryFilePath, true) != 0)
      {
         string sPhysicalDataFileName = Path.Combine(originaldb.PrimaryFilePath, sDatabase + ".MDF");
         bkp.RelocateFiles.Add(new RelocateFile(sLogicalDataFileName, sPhysicalDataFileName));
      }                  
   }
}

Same for the log file.

Marius Bancila
  • 16,053
  • 9
  • 49
  • 91
  • You know, C# can also build and send a RESTORE DATABASE command. – Aaron Bertrand May 25 '12 at 11:36
  • Yes. I had this code that was working fine, until we tried out SQL Server 2012. So I had to make some corrections for it to work. Don't know what was changed in 2012 so that it doesn't work like with 2008. – Marius Bancila May 25 '12 at 12:17
  • Nothing, except that your paths were different, that's all. It has nothing to do with the version. Same thing would have happened if you had different named instances of SQL Server 2008. – Aaron Bertrand May 25 '12 at 12:23
  • But that's the catch. I do have that. I have several machines where I was testing this. For instance my development machine the path is c:\Program Files\Microsoft SQL Server\MSSQL10_50.MYSERVER\MSSQL\DATA. A different path also, yet it worked like a charm. – Marius Bancila May 25 '12 at 12:38
  • 1
    Possibly because it placed the data files in the other location (which was also valid on your machine). Imagine you have two folders: c:\foo\ and c:\bar\. A certain database backup defaults to c:\foo\ (another machine). You can restore it to a different instance (which uses c:\bar\) even if the data files go to c:\foo\ since the instance doesn't have exclusivity on that folder. But the folder has to exist. I guarantee you this is not a problem with version, nor is it magic or voodoo - the problem you were having is because the folder the database backup was expecting did not exist. Period. – Aaron Bertrand May 25 '12 at 12:41
  • Yes, I know the folder does not exist. I've said that from the very beginning. What I'm saying is that the folder does not exist on the machine with SQL Server 2008 either. Do you understand that? And restoring on that machine with that server instance does work. I know it's no magic, no voodoo, but there is something that works differently and defaults to the actually physical database. – Marius Bancila May 25 '12 at 15:35
  • -> Which namespace for Restore class should I use? -> If anyone missing this Restore class, have to add 'Microsoft.SqlServer.SmoExtended' extension namespace. – Hamit Enes Mar 09 '20 at 14:08
6

I had the same problem, and this fixed it without any C# code:

USE [master]
ALTER DATABASE [MyDb] 
SET SINGLE_USER WITH ROLLBACK IMMEDIATE
RESTORE DATABASE [MyDb] 
FROM  DISK = N'D:\backups\mydb.bak' 
WITH  FILE = 1,  
MOVE N'MyDb' TO N''c:\valid_data_path\MyDb.mdf',  
MOVE N'MyDb_log' TO N'\valid_log_path\MyDb.ldf',  
NOUNLOAD,  
REPLACE,  
STATS = 5
ALTER DATABASE [MyDb] SET MULTI_USER
GO
DJDaveMark
  • 2,669
  • 23
  • 35
Paul W
  • 226
  • 3
  • 5
  • This also worked for me. The database I backed up from had different paths than the target database. It seems that in situations like this, you have to use the MOVE options when executing RESTORE DATABASE. When I added the MOVE options for both files providing the locations in the target database (the one mentioned in the RESTORE command), the restore completed successfully. – Aron Boyette Apr 21 '15 at 20:17
  • I'm using a restore command similar to this one, with MOVE and even single user lock, but the database still complains about not finding files on the location from the old machine (like in OP). However, once I've done a manual restore once, I can run the script with no problems. Maybe, I have a different problem... I'm used to solving Microsoft problems with ham-handed methods, so... – Erk Oct 18 '16 at 17:36
  • Maybe the the SQL manager needs to be run as administrator. It is possible that it is not able to create the files. You could also try creating empty mdf and ldf files in the MOVE location. I am assuming it is those files you are referring to. – Paul W Oct 19 '16 at 02:02
  • @PaulW: upon further analysis of the original database(es) I found a bunch of discrepancies that doesn't cover this specific case (multiple data files due to full-text indexes, the wrong [?!] database restored at some point–the application uses several databases–etc). I think we can safely assume I'm not having problems with this query! :D – Erk Oct 24 '16 at 00:31
3

As has already been said a few times, restoring a backup where the new and old paths for the mdf and ldf files don't match can cause this error. There are several good examples here already of how to deal with that with SQL, none of them however worked for me until I realised that in my case I needed to include the '.mdf' and '.ldf' extensions in the from part of the 'MOVE' statement, e.g.:

RESTORE DATABASE [SomeDB] 
FROM DISK = N'D:\SomeDB.bak' 
WITH MOVE N'SomeDB.mdf' TO N'D:\SQL Server\MSSQL12.MyInstance\MSSQL\DATA\SomeDB.mdf', 
MOVE N'SomeDb_log.ldf' TO N'D:\SQL Server\MSSQL12.MyInstance\MSSQL\DATA\SomeDB_log.ldf'

Hope that saves someone some pain, I could not understand why SQL was suggesting I needed to use the WITH MOVE option when I already was doing so.

tomRedox
  • 28,092
  • 24
  • 117
  • 154
0

Please try to uncheck the “Tail-Log Backup” option on the Options page of the Restore Database dialog

0

There is some version issue in this. You can migrate your database to 2012 by 2 another methods:-

1) take the database offline > copy the .mdf and .ldf files to the target server data folder and attach the database. refer this:- https://dba.stackexchange.com/questions/30440/how-do-i-attach-a-database-in-sql-server

2) Create script of the whole database with schema & Data and run it on the target server(very slow process takes time). refer this:- Generate script in SQL Server Management Studio

Community
  • 1
  • 1
0

Try restarting the SQL Service. Worked for me.

Chris
  • 365
  • 7
  • 19
0

Just in case this is useful for someone working directly with Powershell (using the SMO library), in this particular case there were secondary data files as well. I enhanced the script a little by killing any open processes and then doing the restore.

Import-module SQLPS
$svr = New-Object ("Microsoft.SqlServer.Management.Smo.Server") "server name";
$svr.KillAllProcesses("database_name");
$RelocateData1 = New-Object "Microsoft.SqlServer.Management.Smo.RelocateFile, Microsoft.SqlServer.SmoExtended, Version=13.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91" ("primary_logical_name","C:\...\SQLDATA\DATA\database_name.mdf")
$RelocateData2 = New-Object "Microsoft.SqlServer.Management.Smo.RelocateFile, Microsoft.SqlServer.SmoExtended, Version=13.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91" ("secondary_logical_name_2","C:\...\SQLDATA\DATA\secondary_file_2.mdf")
$RelocateData3 = New-Object "Microsoft.SqlServer.Management.Smo.RelocateFile, Microsoft.SqlServer.SmoExtended, Version=13.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91" ("secondary_logical_name_3","C:\...\SQLDATA\DATA\secondary_file_3.mdf")
$RelocateLog = New-Object "Microsoft.SqlServer.Management.Smo.RelocateFile, Microsoft.SqlServer.SmoExtended, Version=13.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91" ("database_name_log","C:\...\SQLDATA\LOGS\database_name_log.ldf")
Restore-SqlDatabase -ServerInstance "server-name" -Database "database_name" -BackupFile "\\BACKUPS\\database_name.bak" -RelocateFile @($RelocateData1, $RelocateData2, $RelocateData3, $RelocateLog) -ReplaceDatabase
dim_user
  • 969
  • 1
  • 13
  • 24
0

You should remove these lines from your script.

CONTAINMENT = NONE
 ON  PRIMARY 
( NAME = N'StudentManagement', FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL11.SQLEXPRESS\MSSQL\DATA\StudentManagement.mdf' , SIZE = 10240KB , MAXSIZE = UNLIMITED, FILEGROWTH = 1024KB )
 LOG ON 
( NAME = N'StudentManagement_log', FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL11.SQLEXPRESS\MSSQL\DATA\StudentManagement_log.ldf' , SIZE = 5696KB , MAXSIZE = 2048GB , FILEGROWTH = 10%)
GO
ALTER DATABASE [StudentManagement] SET COMPATIBILITY_LEVEL = 110
GO
IF (1 = FULLTEXTSERVICEPROPERTY('IsFullTextInstalled'))
begin
EXEC [StudentManagement].[dbo].[sp_fulltext_database] @action = 'enable'
end
GO
ALTER DATABASE [StudentManagement] SET ANSI_NULL_DEFAULT OFF 
GO
ALTER DATABASE [StudentManagement] SET ANSI_NULLS OFF 
GO
ALTER DATABASE [StudentManagement] SET ANSI_PADDING OFF 
GO
ALTER DATABASE [StudentManagement] SET ANSI_WARNINGS OFF 
GO
ALTER DATABASE [StudentManagement] SET ARITHABORT OFF 
GO
ALTER DATABASE [StudentManagement] SET AUTO_CLOSE OFF 
GO
ALTER DATABASE [StudentManagement] SET AUTO_CREATE_STATISTICS ON 
GO
ALTER DATABASE [StudentManagement] SET AUTO_SHRINK OFF 
GO
ALTER DATABASE [StudentManagement] SET AUTO_UPDATE_STATISTICS ON 
GO
ALTER DATABASE [StudentManagement] SET CURSOR_CLOSE_ON_COMMIT OFF 
GO
ALTER DATABASE [StudentManagement] SET CURSOR_DEFAULT  GLOBAL 
GO
ALTER DATABASE [StudentManagement] SET CONCAT_NULL_YIELDS_NULL OFF 
GO
ALTER DATABASE [StudentManagement] SET NUMERIC_ROUNDABORT OFF 
GO
ALTER DATABASE [StudentManagement] SET QUOTED_IDENTIFIER OFF 
GO
ALTER DATABASE [StudentManagement] SET RECURSIVE_TRIGGERS OFF 
GO
ALTER DATABASE [StudentManagement] SET  DISABLE_BROKER 
GO
ALTER DATABASE [StudentManagement] SET AUTO_UPDATE_STATISTICS_ASYNC OFF 
GO
ALTER DATABASE [StudentManagement] SET DATE_CORRELATION_OPTIMIZATION OFF 
GO
ALTER DATABASE [StudentManagement] SET TRUSTWORTHY OFF 
GO
ALTER DATABASE [StudentManagement] SET ALLOW_SNAPSHOT_ISOLATION OFF 
GO
ALTER DATABASE [StudentManagement] SET PARAMETERIZATION SIMPLE 
GO
ALTER DATABASE [StudentManagement] SET READ_COMMITTED_SNAPSHOT OFF 
GO
ALTER DATABASE [StudentManagement] SET HONOR_BROKER_PRIORITY OFF 
GO
ALTER DATABASE [StudentManagement] SET RECOVERY SIMPLE 
GO
ALTER DATABASE [StudentManagement] SET  MULTI_USER 
GO
ALTER DATABASE [StudentManagement] SET PAGE_VERIFY CHECKSUM  
GO
ALTER DATABASE [StudentManagement] SET DB_CHAINING OFF 
GO
ALTER DATABASE [StudentManagement] SET FILESTREAM( NON_TRANSACTED_ACCESS = OFF ) 
GO
ALTER DATABASE [StudentManagement] SET TARGET_RECOVERY_TIME = 0 SECONDS 
max
  • 4,141
  • 5
  • 26
  • 55
0

This usually happens, when you are using one MSSQL Studio for backup (connected to old server) and restore (connected to new one). Just make sure you are executing the restore on the correct server. Either check the server name and IP in the left pane in UI or dou

kafe
  • 157
  • 8
0

If you're doing this with C#, and the physical paths are not the same, you need to use RelocateFiles, as one answer here also mentioned.

For most cases, the below code will work, assuming:

  1. You're just restoring a backup of a database from elsewhere, otherwise meant to be identical. For example, a copy of production to a local Db.

  2. You aren't using an atypical database layout, for example one where the rows files are spread across multiple files on multiple disks.

In addition, the below is only necessary on first restore. Once a single successful restore occurs, the below file mapping will already be setup for you in Sql Server. But, the first time - restoring a bak file to a blank db - you basically have to say, "Yes, use the Db files in their default, local locations, instead of freaking out" and you need to tell it to keep things in the same place by, oddly enough, telling it to relocate them:

var dbDataFile = db.FileGroups[0].Files[0];
restore.RelocateFiles.Add(new RelocateFile(dbDataFile.Name, dbDataFile.FileName));
var dbLogFile = db.LogFiles[0];
restore.RelocateFiles.Add(new RelocateFile(dbLogFile.Name, dbLogFile.FileName));

To better clarify what a typical case would be, and how you'd do the restore, here's the full code for a typical restore of a .bak file to a local machine:

var smoServer = new Microsoft.SqlServer.Management.Smo.Server(
    new Microsoft.SqlServer.Management.Common.ServerConnection(sqlServerInstanceName));

var db = smoServer.Databases[dbName];
if (db == null)
{
    db = new Microsoft.SqlServer.Management.Smo.Database(smoServer, dbName);
    db.Create();
}

restore.Devices.AddDevice(backupFileName, DeviceType.File);
restore.Database = dbName;
restore.FileNumber = 0;
restore.Action = RestoreActionType.Database;
restore.ReplaceDatabase = true;

var dbDataFile = db.FileGroups[0].Files[0];
restore.RelocateFiles.Add(new RelocateFile(dbDataFile.Name, dbDataFile.FileName));
var dbLogFile = db.LogFiles[0];
restore.RelocateFiles.Add(new RelocateFile(dbLogFile.Name, dbLogFile.FileName));

restore.SqlRestore(smoServer);

db.SetOnline();
smoServer.Refresh();
db.Refresh();

This code will work whether you've manually restored this Db before, created one manually with just the name and no data, or done nothing - started with a totally blank machine, with just Sql Server installed and no databases whatsoever.

Chris Moschini
  • 36,764
  • 19
  • 160
  • 190
-1

Please change the .mdf file path. Just create a folder in any drive, ie - in "D" drive, just create a folder with custom name (dbase) and point the path to the new folder, mssql will automatically create the files.

"C:\PROGRAM FILES\MICROSOFT SQL SERVER\MSSQL.1\MSSQL\DATA\MYDB_ABC.MDF" to "D:\dbase\MYDB_ABC.MDF"

Harish Kumar
  • 39
  • 1
  • 1
  • 5