Problem
I frequently get requests to refresh a test / dev SQL Server database and need a way to test database backups from the latest full backup of a production database. It’s easy enough to do this with SQL Server Management Studio, but I would rather have an easy to configure script that’s less prone to making a mistake that I could run on demand and / or easily automate rather than do this as a manual process.
Solution
We previously saw how to accomplish this in this tip: Automating a SQL Server Database Refresh, with a little PowerShell, a little T-SQL and SQL Server Agent. In the interest of keeping the configuration simpler and only changed in one script the following is a revised way to do it with just PowerShell and optionally SQL Server Agent.
The following versions were used writing this tip:
- SQL Server 2017 CU19 Developer Edition
- SQL Server Management Objects (SMO) installed SQL Server Management Studio 18.4
- PowerShell 5.1.17763.1007
Configure PowerShell Script
To get started, copy the following PowerShell into the editor of your choice and configuring the variables for your purposes.
# restores a full database backup to another database from source's latest full backup file in specified directory
# begin script configuration here
$TargetSqlServerInstance = "JGAVIN-L\SQL2017" # target server instance
$TargetDb = "RefreshTest" # target database
$BackupDir = "\\jgavin-l\SQL2017_Backup\RefreshProd" # directory / share where backups are stored
$SourceLogicalDataFileName = "RefreshProd" # logical data file name of source db
$SourceLogicalLogFileName = "RefreshProd_log" # logical log file name of source db
$TargetLogicalDataFileName = "RefreshTest" # logical name you want to change logical data file on target db to
$TargetLogicalLogFileName = "RefreshTest_log" # logical name you want to change logical log file on target db to
$TargetPhysicalDataFileName = "C:\Program Files\Microsoft SQL Server\MSSQL14.SQL2017\MSSQL\DATA\RefreshTest.mdf" # full path\file of target db physical data file
$TargetPhysicalLogFileName = "C:\Program Files\Microsoft SQL Server\MSSQL14.SQL2017\MSSQL\DATA\RefreshTest_log.mdf" # full path\file of target db physical log file
$CompatLevel = 140 # compatibility level to set target database to (2019=150, 2017=140, 2016=130, 2014=120, 2012=110, 2008/2008R2=100, 2005=90, 2000=80, 7=70)
# end script configuration here
# import sqlserver module
Import-Module sqlserver
# latest full backup file name is dynamically determined and appended to backup directory
$LatestFullBackupFile = Get-ChildItem -Path $BackupDir -Filter *.bak | Sort-Object LastAccessTime -Descending | Select-Object -First 1
$FileToRestore = $BackupDir + '\' + $LatestFullBackupFile
# kill any connections in target database
$KillConnectionsSql=
"
USE master
GO
ALTER DATABASE $TargetDb SET SINGLE_USER WITH ROLLBACK IMMEDIATE
GO
USE master
GO
ALTER DATABASE $TargetDb SET MULTI_USER
GO
USE master
GO
"
Invoke-Sqlcmd -ServerInstance $TargetSqlServerInstance -Query $KillConnectionsSql
# import sqlserver module
Import-Module sqlserver
# restore
$RelocateData = New-Object Microsoft.SqlServer.Management.Smo.RelocateFile("$SourceLogicalDataFileName", "$TargetPhysicalDataFileName")
$RelocateLog = New-Object Microsoft.SqlServer.Management.Smo.RelocateFile("$SourceLogicalLogFileName", "$TargetPhysicalLogFileName")
Restore-SqlDatabase -ServerInstance $TargetSqlServerInstance -Database $TargetDb -BackupFile $FileToRestore -RelocateFile @($RelocateData,$RelocateLog) -ReplaceDatabase
# end restore
# set db owner to sa
Invoke-Sqlcmd -ServerInstance $TargetSqlServerInstance -Database $TargetDb -Query "EXEC sp_changedbowner sa"
# set compatibility level
Invoke-Sqlcmd -ServerInstance $TargetSqlServerInstance -Query "ALTER DATABASE $($TargetDb) SET COMPATIBILITY_LEVEL =$($CompatLevel)"
# set recovery model to simple
Invoke-Sqlcmd -ServerInstance $TargetSqlServerInstance -Query "ALTER DATABASE $($TargetDb) SET RECOVERY SIMPLE WITH NO_WAIT"
# rename logical files
Invoke-Sqlcmd -ServerInstance $TargetSqlServerInstance -Query "ALTER DATABASE $TargetDb MODIFY FILE (NAME='$SourceLogicalDataFileName', NEWNAME='$TargetLogicalDataFileName')"
Invoke-Sqlcmd -ServerInstance $TargetSqlServerInstance -Query "ALTER DATABASE $TargetDb MODIFY FILE (NAME='$SourceLogicalLogFileName', NEWNAME='$TargetLogicalLogFileName')"
# dbcccheckdb
Invoke-Sqlcmd -ServerInstance $TargetSqlServerInstance -Query "DBCC checkdb ($TargetDb) --WITH NO_INFOMSGS"
# display sp_helpdb
Invoke-Sqlcmd -ServerInstance $TargetSqlServerInstance -Query "EXEC sp_helpdb $($TargetDb)" The following table lists each configurable variable and its description:
| Variable | Description |
|---|---|
| $TargetSqlServerInstance | Name of SQL Server with database we’re restoring to in the form: MachineName or MachineName\InstanceName |
| $TargetDb | Name of target database we’re restoring to |
| $BackupDir | Path to local drive or UNC share with backup files in the form: \\ServerName\ShareName or DriveLetter:\DirectoryName |
| $SourceLogicalDataFileName | Logical data file name of source database |
| $SourceLogicalLogFileName | Logical log file name of source database |
| $TargetLogicalDataFileName | Logical data file name of target database |
| $TargetLogicalLogFileName | Logical data file name of target database |
| $TargetPhysicalDataFileName | Fully qualified path to physical data file of target database |
| $SourceLogicalLogFileName | Fully qualified path to physical log file of target database |
| $CompatLevel | Compatibility Level we want for target database |
To obtain the logical and physical file names for the source and target databases:
From Object Explorer in SQL Server Management Studio:
- Right click on source database
- Properties

- Files

Repeat for the target database.
- Right click on source database
- Properties

- Files

Our source database full and transaction log backups are saved in the C:\Program Files\Microsoft SQL Server\MSSQL14.SQL2017\MSSQL\Backup\RefreshProd directory. Looking at the time and date stamps, we see that RefreshProd_full_backup_2.bak is the latest full backup, and that’s the one we want to refresh the test database with. The fully qualified name is determined by the string in $BackupDir appended with the dynamically generated string in $LatestFullBackupFile.

Execute Script
After configuring the variables, I’ve saved the PowerShell as C:\DbaScripts\RefreshTestDb.ps1. Execute it and we see the output of sp_helpdb on our newly refreshed database.

The SQL Server errorlog shows us:
- C:\Program Files\Microsoft SQL Server\MSSQL14.SQL2017\MSSQL\Backup\RefreshProd, RefreshProd_full_backup_2.bak was restored
- Restore completed
- Compatibility Level was set
- Database recovery model set to SIMPLE
- DBCC CHECKDB ran without errors

Automate Script in a SQL Server Agent Job
Now, we’ll automate it in a SQL Server Agent Job.
- Expand SQL Server Agent dropdown
- Right click Jobs
- New Job…

- Name Job
- Set Job owner
- Enter Job description
- Steps

- New

- Name Step
- Choose Operating System (CmdExec) in Type dropdown
- Enter PowerShell executable name with a -File=FullyQualifiedScriptName
- OK

- Schedules
- New

- Name Job Schedule
- Choose Frequency
- OK

- OK

- Expand Jobs
- Right click on new Job
- Start Job at Step…

Look for Success in Status column.

- Right click on Job
- View History



Next Steps
Here are links to tips with a wealth of information on the following related topics:
- Database backups: SQL Server Backup Tips
- Database restores: SQL Server Restore Tips
- PowerShell: SQL Server PowerShell Tips
- SQL Agent: SQL Server Agent Tips
- Renaming database logical files: Rename logical database file name for a SQL Server database

Joe Gavin is from Greater Boston and has worked in technology as a Field Service Engineer for an automotive dealer computer system vendor, a Technical Consultant and Operations Analyst with Sybase and SQL Server based database applications in financial services and now works as a SQL Server Database Administrator.
- MSSQLTips Awards:
- Achiever Award (75+ Tips) – 2024 | Author of the Year – 2021 | Author Contender – 2024 |
- Rookie Contender – 2018



Younes, that’s just a basic connectivity error. It’s likely the server name is wrong, listening on a port other than 1433, or not running.
I run this script qt powershell but i found this erreur anyone here can help me
Invoke-Sqlcmd : A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the
instance name is correct and that SQL Server is configured to allow remote connections. (provider: Named Pipes Provider, error: 40 – Could not open a connection to SQL Server)
Au caracte Ligne:27 : 1
+ Invoke-Sqlcmd -ServerInstance $TargetSqlServerInstance -Query $KillCo …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation : (:) [Invoke-Sqlcmd], SqlException
+ FullyQualifiedErrorId : SqlExceptionError,Microsoft.SqlServer.Management.PowerShell.GetScriptCommand
Invoke-Sqlcmd : DÉtection d’une syntaxe incorrecte pendant l’analyse de ”.
Au caracte Ligne:27 : 1
+ Invoke-Sqlcmd -ServerInstance $TargetSqlServerInstance -Query $KillCo …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ParserError: (:) [Invoke-Sqlcmd], BatchParserException
+ FullyQualifiedErrorId : ExecutionFailureException,Microsoft.SqlServer.Management.PowerShell.GetScriptCommand
Restore-SqlDatabase : Échec de la connexion au serveur 192.168.108.100.
Au caracte Ligne:32 : 1
+ Restore-SqlDatabase -ServerInstance $TargetSqlServerInstance -Databas …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Restore-SqlDatabase], ConnectionFailureException
+ FullyQualifiedErrorId : Microsoft.SqlServer.Management.Common.ConnectionFailureException,Microsoft.SqlServer.Management.PowerShell.RestoreSqlDatabaseCommand
Invoke-Sqlcmd : A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the
instance name is correct and that SQL Server is configured to allow remote connections. (provider: Named Pipes Provider, error: 40 – Could not open a connection to SQL Server)
Au caracte Ligne:35 : 1
+ Invoke-Sqlcmd -ServerInstance $TargetSqlServerInstance -Database $Tar …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation : (:) [Invoke-Sqlcmd], SqlException
+ FullyQualifiedErrorId : SqlExceptionError,Microsoft.SqlServer.Management.PowerShell.GetScriptCommand
Invoke-Sqlcmd : DÉtection d’une syntaxe incorrecte pendant l’analyse de ”.
Au caracte Ligne:35 : 1
+ Invoke-Sqlcmd -ServerInstance $TargetSqlServerInstance -Database $Tar …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ParserError: (:) [Invoke-Sqlcmd], BatchParserException
+ FullyQualifiedErrorId : ExecutionFailureException,Microsoft.SqlServer.Management.PowerShell.GetScriptCommand
Invoke-Sqlcmd : A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the
instance name is correct and that SQL Server is configured to allow remote connections. (provider: Named Pipes Provider, error: 40 – Could not open a connection to SQL Server)
Au caracte Ligne:38 : 1
+ Invoke-Sqlcmd -ServerInstance $TargetSqlServerInstance -Database $Tar …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation : (:) [Invoke-Sqlcmd], SqlException
+ FullyQualifiedErrorId : SqlExceptionError,Microsoft.SqlServer.Management.PowerShell.GetScriptCommand
Invoke-Sqlcmd : DÉtection d’une syntaxe incorrecte pendant l’analyse de ”.
Au caracte Ligne:38 : 1
+ Invoke-Sqlcmd -ServerInstance $TargetSqlServerInstance -Database $Tar …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ParserError: (:) [Invoke-Sqlcmd], BatchParserException
+ FullyQualifiedErrorId : ExecutionFailureException,Microsoft.SqlServer.Management.PowerShell.GetScriptCommand
Invoke-Sqlcmd : A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the
instance name is correct and that SQL Server is configured to allow remote connections. (provider: Named Pipes Provider, error: 40 – Could not open a connection to SQL Server)
Au caracte Ligne:41 : 1
+ Invoke-Sqlcmd -ServerInstance $TargetSqlServerInstance -Database $Tar …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation : (:) [Invoke-Sqlcmd], SqlException
+ FullyQualifiedErrorId : SqlExceptionError,Microsoft.SqlServer.Management.PowerShell.GetScriptCommand
Invoke-Sqlcmd : DÉtection d’une syntaxe incorrecte pendant l’analyse de ”.
Au caracte Ligne:41 : 1
+ Invoke-Sqlcmd -ServerInstance $TargetSqlServerInstance -Database $Tar …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ParserError: (:) [Invoke-Sqlcmd], BatchParserException
+ FullyQualifiedErrorId : ExecutionFailureException,Microsoft.SqlServer.Management.PowerShell.GetScriptCommand
Invoke-Sqlcmd : A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the
instance name is correct and that SQL Server is configured to allow remote connections. (provider: Named Pipes Provider, error: 40 – Could not open a connection to SQL Server)
Au caracte Ligne:44 : 1
+ Invoke-Sqlcmd -ServerInstance $TargetSqlServerInstance -Database $Tar …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation : (:) [Invoke-Sqlcmd], SqlException
+ FullyQualifiedErrorId : SqlExceptionError,Microsoft.SqlServer.Management.PowerShell.GetScriptCommand
Invoke-Sqlcmd : DÉtection d’une syntaxe incorrecte pendant l’analyse de ”.
Au caracte Ligne:44 : 1
+ Invoke-Sqlcmd -ServerInstance $TargetSqlServerInstance -Database $Tar …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ParserError: (:) [Invoke-Sqlcmd], BatchParserException
+ FullyQualifiedErrorId : ExecutionFailureException,Microsoft.SqlServer.Management.PowerShell.GetScriptCommand
Invoke-Sqlcmd : A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the
instance name is correct and that SQL Server is configured to allow remote connections. (provider: Named Pipes Provider, error: 40 – Could not open a connection to SQL Server)
Au caracte Ligne:45 : 1
+ Invoke-Sqlcmd -ServerInstance $TargetSqlServerInstance -Database $Tar …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation : (:) [Invoke-Sqlcmd], SqlException
+ FullyQualifiedErrorId : SqlExceptionError,Microsoft.SqlServer.Management.PowerShell.GetScriptCommand
Invoke-Sqlcmd : DÉtection d’une syntaxe incorrecte pendant l’analyse de ”.
Au caracte Ligne:45 : 1
+ Invoke-Sqlcmd -ServerInstance $TargetSqlServerInstance -Database $Tar …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ParserError: (:) [Invoke-Sqlcmd], BatchParserException
+ FullyQualifiedErrorId : ExecutionFailureException,Microsoft.SqlServer.Management.PowerShell.GetScriptCommand
Invoke-Sqlcmd : A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the
instance name is correct and that SQL Server is configured to allow remote connections. (provider: Named Pipes Provider, error: 40 – Could not open a connection to SQL Server)
Au caracte Ligne:48 : 1
+ Invoke-Sqlcmd -ServerInstance $TargetSqlServerInstance -Database $Tar …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation : (:) [Invoke-Sqlcmd], SqlException
+ FullyQualifiedErrorId : SqlExceptionError,Microsoft.SqlServer.Management.PowerShell.GetScriptCommand
Invoke-Sqlcmd : DÉtection d’une syntaxe incorrecte pendant l’analyse de ”.
Au caracte Ligne:48 : 1
+ Invoke-Sqlcmd -ServerInstance $TargetSqlServerInstance -Database $Tar …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ParserError: (:) [Invoke-Sqlcmd], BatchParserException
+ FullyQualifiedErrorId : ExecutionFailureException,Microsoft.SqlServer.Management.PowerShell.GetScriptCommand
Invoke-Sqlcmd : A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the
instance name is correct and that SQL Server is configured to allow remote connections. (provider: Named Pipes Provider, error: 40 – Could not open a connection to SQL Server)
Au caracte Ligne:51 : 1
+ Invoke-Sqlcmd -ServerInstance $TargetSqlServerInstance -Database $Tar …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation : (:) [Invoke-Sqlcmd], SqlException
+ FullyQualifiedErrorId : SqlExceptionError,Microsoft.SqlServer.Management.PowerShell.GetScriptCommand
Invoke-Sqlcmd : DÉtection d’une syntaxe incorrecte pendant l’analyse de ”.
Au caracte Ligne:51 : 1
+ Invoke-Sqlcmd -ServerInstance $TargetSqlServerInstance -Database $Tar …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ParserError: (:) [Invoke-Sqlcmd], BatchParserException
+ FullyQualifiedErrorId : ExecutionFailureException,Microsoft.SqlServer.Management.PowerShell.GetScriptCommand
Ivan, I’m guessing the account you’re running this doesn’t have right to the backup directory. If you step through the script manually, after this line ‘$LatestFullBackupFile = Get-ChildItem -Path $BackupDir -Filter *.bak | Sort-Object LastAccessTime -Descending | Select-Object -First 1’, $LatestFullBackupFile is likely empty.
Hi, Just want to ask about my error while doing this script. Actually, this script worked previously on the sql servers, however, when i changed the target SQL servers, i received an error message indicating that Error: 18204, Severity 16, State:1
BackupDiskFile:OpenMedia: BackupDevice “path of backups” failed to open. Operating System Error 123(the filename, , the directory name, or volume label syntax is incorrect)
Kindly help me with this one. Thank you
Thanks Abel. Stay tuned, there may be another tip coming that will include restoring full plus differential backups.
Hello,
Thanks for the information, greately appreciated, just have question, what would you need to add if I would want to restore a full and a diferential.
Thanks again.
Excellent Mando. Glad the fix was easy.
That was it, Joe! Thanks so much. Now trying to get this to work on databases with multiple data files…
Mando, I’m suspecting you may have omitted the -ReplaceDatabase.
Glenn’s issue is his db name has a ‘-‘ in it.
I’m working through using this script myself and currently getting this error:
“
Restore-SqlDatabase : System.Data.SqlClient.SqlError: The file ‘F:\Program Files\Microsoft SQL Server\MSSQL15.MSSQLSERVER\MSSQL\DATA\[DBNAME].mdf’ cannot be overwritten. It is being used
by database ‘[DBNAME]’.
“
Any ideas?
C. Uerel, the database will be overwritten. No need to drop drop and recreate it.
if a database was restored from an earlier backup and thus already exists on the SQL server, does this procedure overwrite that db with the newest bak file or do I have to delete that db first by an additional script?
Glenn, I can’t really tell where the issue is. I did copy and paste the PowerShell from the tip again, configured it and tested it successfully. Guessing you may have inadvertently have an an additional character or 2 that’s breaking things. I’d suggest copying and pasting it again.
Hello,
I’m trying to run the script but we are getting the below error, anyone has a idea?
Invoke-Sqlcmd : Incorrect syntax near ‘GO’.
Incorrect syntax near ‘-‘.
Incorrect syntax near the keyword ‘with’. If this statement is a common table expression, an
xmlnamespaces clause or a change tracking context clause, the previous statement must be
terminated with a semicolon.
Incorrect syntax near ‘IMMEDIATE’.
Incorrect syntax near ‘-‘.
‘MULTI_USER’ is not a recognized SET option.
Msg 102, Level 15, State 1, Procedure , Line 1.
+ Invoke-Sqlcmd -ServerInstance $TargetSqlServerInstance -Query $KillCo …
Good question Jack. That’s a little out of scope for these requirements. I put this together based on a common request I get to restore test/dev from the previous nights’ full backup. Don’t know off the top of my head how I’d go about with this script. The dbatools Restore-DbaDatabase cmdlet is probably the best place to start.
how would you include all the subsequent log files so we always restore the latest copy from production?
tyia!
Thanks Joe. you are very helpful.
I have Joey. The reason is with SQL Server (and Sybase for that matter), logins to the SQL Server and users in a database are 2 separate but related entities tied together with a number called a sid. If you’re restoring the backup to the same SQL Server or another one where the logins were added in the same order, the sids will match, and you’re all set. Here are a couple of tips that will give you some more detail:
https://www.mssqltips.com/sqlservertip/1063/sql-server-database-restores-mapping-users-to-logins/
https://www.mssqltips.com/sqlservertip/1590/understanding-and-dealing-with-orphaned-users-in-a-sql-server-database/
Thanks Joe. Do you come across the user permission issue or login problem after the full backup restore? even the dev database already has the same user logins created as the production database.
You are 100% correct Joey. I frequently get requests to restore a dev database from the previous night’s full backup of production so that was my basic requirement for this tip.
seems like your script only restore the bak file, it does not restore the subsequent (transaction logs files *.trn). Please correct me if I am wrong.
Joe and Greg, no worries and thank you, This script helps me a a lot and saved me loads of time, exactly I was after , keep up the good work!
The code has been updated.
-Greg
Ima, sorry you had problems with this. Thanks for pointing it out.
Greg,
I confirmed the following lines had soem spaces removed:
ALTER DATABASE$TargetDb SET SINGLE_USER WITH ROLLBACK IMMEDIATE
ALTER DATABASE$TargetDb SET MULTI_USER
Invoke-Sqlcmd -ServerInstance $TargetSqlServerInstance -Query “ALTER DATABASE$($TargetDb) SET COMPATIBILITY_LEVEL =$($CompatLevel)”
Invoke-Sqlcmd -ServerInstance $TargetSqlServerInstance -Query “ALTER DATABASE$($TargetDb) SET RECOVERY SIMPLE WITH NO_WAIT”
Invoke-Sqlcmd -ServerInstance $TargetSqlServerInstance -Query “ALTER DATABASE$TargetDb MODIFY FILE (NAME=’$SourceLogicalDataFileName’, NEWNAME=’$TargetLogicalDataFileName’)”
Invoke-Sqlcmd -ServerInstance $TargetSqlServerInstance -Query “ALTER DATABASE$TargetDb MODIFY FILE (NAME=’$SourceLogicalLogFileName’, NEWNAME=’$TargetLogicalLogFileName’)”
Invoke-Sqlcmd -ServerInstance $TargetSqlServerInstance -Query “EXEC sp_helpdb$($TargetDb)”
Here are the edited lines:
ALTER DATABASE $TargetDb SET SINGLE_USER WITH ROLLBACK IMMEDIATE
ALTER DATABASE $TargetDb SET MULTI_USER
Invoke-Sqlcmd -ServerInstance $TargetSqlServerInstance -Query “ALTER DATABASE $($TargetDb) SET COMPATIBILITY_LEVEL = $($CompatLevel)”
Invoke-Sqlcmd -ServerInstance $TargetSqlServerInstance -Query “ALTER DATABASE $($TargetDb) SET RECOVERY SIMPLE WITH NO_WAIT”
Invoke-Sqlcmd -ServerInstance $TargetSqlServerInstance -Query “ALTER DATABASE $TargetDb MODIFY FILE (NAME=’$SourceLogicalDataFileName’, NEWNAME=’$TargetLogicalDataFileName’)”
Invoke-Sqlcmd -ServerInstance $TargetSqlServerInstance -Query “ALTER DATABASE $TargetDb MODIFY FILE (NAME=’$SourceLogicalLogFileName’, NEWNAME=’$TargetLogicalLogFileName’)”
Invoke-Sqlcmd -ServerInstance $TargetSqlServerInstance -Query “EXEC sp_helpdb $($TargetDb)”
I can send you the whole scripts with edits if you like.
Joe, let me know if the script needs to be updated. It is possible the formatting got messed up when it was converted.
Thanks
Greg
Great article, thanks very much!
In case if it helps anyone I wasted couple hours due to errors like below
Logical file xxx is not part of database yyy..
Unkown object type ‘xxx’ used in a create, drop..
Turned out I had to add spaces in multiple places in the script
DATABASE$($TargetDb) –>DATABASE $($TargetDb)
DATABASE$TargetDb –> DATABASE $TargetDb
sp_helpdb$($TargetDb) –> sp_helpdb $($TargetDb)
Thanks Mike. Glad you like it.
I’m presuming we’re talking about multiple full backup files in one directory and you want to test each file. In that case I’d do something like this to build a list of backup files in order then restore each of them within a ForEach.
# build list of backup files in order from oldest to newest
$BackupFiles = Get-ChildItem -Path $BackupDir -Filter *.bak | Sort-Object LastAccessTime
ForEach($FileToRestore in $BackupFiles)
{
# kill any connections in target database
$KillConnectionsSql=
“
USE master
GO
ALTER DATABASE $TargetDb SET SINGLE_USER WITH ROLLBACK IMMEDIATE
GO
USE master
GO
ALTER DATABASE $TargetDb SET MULTI_USER
GO
USE master
GO
“
Invoke-Sqlcmd -ServerInstance $TargetSqlServerInstance -Query $KillConnectionsSql
# restore
$RelocateData = New-Object Microsoft.SqlServer.Management.Smo.RelocateFile(“$SourceLogicalDataFileName”, “$TargetPhysicalDataFileName”)
$RelocateLog = New-Object Microsoft.SqlServer.Management.Smo.RelocateFile(“$SourceLogicalLogFileName”, “$TargetPhysicalLogFileName”)
Restore-SqlDatabase -ServerInstance $TargetSqlServerInstance -Database $TargetDb -BackupFile $BackupDir\$FileToRestore -RelocateFile @($RelocateData,$RelocateLog) -ReplaceDatabase
# end restore
}