param ( #local test datatabase server to restore your live database [string]$TargetSQLServer= ".\MSSQLSERVER_2012", #name of your live database [string]$LiveSQLDatabase= "TestDB", #name of your final test database being set after restoration [string]$TargetSQLDatabase= "TestDB_DEV", #data root of mssql server - containing .mdf files of your test database [string]$TargetSQLDatabaseDataRoot= "C:\Program Files\Microsoft SQL Server\MSSQL11.MSSQLSERVER_2012\MSSQL\DATA", #folder where current backup file will be copied and processed - must be local folder [string]$TempLocalFolder= "C:\Program Files\Microsoft SQL Server\MSSQL11.MSSQLSERVER_2012\MSSQL\Backup_temp", #backup location of your live database - can be located on the network drive [string]$BackupLiveFolder = "C:\Program Files\Microsoft SQL Server\MSSQL11.MSSQLSERVER_2012\MSSQL\Backup", #show copy progress or copy in bacground [bool]$silentCopying = 0, #log location [string]$Logfile = "C:\Program Files\Microsoft SQL Server\MSSQL11.MSSQLSERVER_2012\MSSQL\Log\CopyLiveDBToTestLog.txt" ) Function LogWrite { Param ([string]$logstring) $currentdate = get-date -format "M-d-yyyy HH:mm:ss" Add-content $Logfile -value "$currentdate | $logstring" write-host "$currentdate | $logstring" } try { LogWrite "acquiring backup file..." #get most recent backup file $liveBackupFile = (dir -Path $BackupLiveFolder) | where {$_.extension -eq ".bak" } | sort lastwritetime –Descending | select -first 1; LogWrite "validating paths..." if($liveBackupFile -eq $null -or -not (Test-path $liveBackupFile.FullName)){ LogWrite "Could not find the backup file, check the backup folder location!"; return;} if(-not(Test-path $TempLocalFolder)) { LogWrite "Incorrect local backup location!"; return;} #copy backup file to temp location if(-not(Test-Path "$TempLocalFolder\$liveBackupFile")) { #remove all backups in temp location dir -path $TempLocalFolder | Foreach-Object { get-childitem -Path $_.FullName | where-object { ($_.FullName.tolower().EndsWith(".bak") -and $_.FullName.tolower().contains($LiveSQLDatabase.ToLower())) } | Foreach-Object { LogWrite "removing file: $_.FullName" remove-item -path $_.FullName } } LogWrite "copying backup file $liveBackupFile ..." if(-not($silentCopying -eq 1)) { #use shell to see progress $FOF_CREATEPROGRESSDLG = "&H0&" $objShell = New-Object -ComObject "Shell.Application" $objFolder = $objShell.NameSpace($TempLocalFolder) $objFolder.CopyHere($liveBackupFile.FullName, $FOF_CREATEPROGRESSDLG) } else { copy-item -Path $liveBackupFile.FullName -Destination "$TempLocalFolder\$liveBackupFile" -PassThru -Verbose } LogWrite "copying backup file $liveBackupFile finished" } else { LogWrite "backup file already exists: $TempLocalFolder\$liveBackupFile" } #---------------------------------------------------------- LogWrite "connecting to $TargetSQLServer" $TargetSQLDatabase_temp = $TargetSQLDatabase + "_"+ (get-date).tostring("yy_MM_dd"); $mdfCurrentPath = "$TargetSQLDatabaseDataRoot\$TargetSQLDatabase_temp.mdf" if(Test-Path $mdfCurrentPath) { LogWrite "database $TargetSQLDatabase_temp.mdf already exists!" return; } LogWrite "restoring database from file: $TempLocalFolder\$liveBackupFile to temp database $TargetSQLDatabase_temp ..." $DBLogicalFileName = $LiveSQLDatabase; $DBLogicalFileName_log = $LiveSQLDatabase + "_Log"; $query = "RESTORE DATABASE [$TargetSQLDatabase_temp] FROM DISK = N'$TempLocalFolder\$liveBackupFile' WITH FILE = 1, MOVE N'$DBLogicalFileName' TO N'$TargetSQLDatabaseDataRoot\"+$TargetSQLDatabase_temp+".mdf', MOVE N'$DBLogicalFileName_log' TO N'$TargetSQLDatabaseDataRoot\"+$TargetSQLDatabase_temp+".ldf', NORECOVERY, NOUNLOAD, REPLACE, STATS = 10"; SQLCMD -S $TargetSQLServer -E -Q $query Start-Sleep -s 10 #bring it to live from restoring mode $query = "RESTORE DATABASE "+$TargetSQLDatabase_temp+" WITH RECOVERY" SQLCMD -S $TargetSQLServer -E -Q $query LogWrite "dropping old $TargetSQLDatabase database..." #drop current database $query = "ALTER DATABASE [$TargetSQLDatabase] SET OFFLINE WITH ROLLBACK IMMEDIATE DROP DATABASE [$TargetSQLDatabase]" SQLCMD -S $TargetSQLServer -E -Q $query Start-Sleep -s 10 LogWrite "renaming temp database $TargetSQLDatabase_temp to $TargetSQLDatabase ..." #rename temp database $query = "ALTER DATABASE ["+$TargetSQLDatabase_temp+"] SET SINGLE_USER WITH ROLLBACK IMMEDIATE ALTER DATABASE ["+$TargetSQLDatabase_temp+"] MODIFY NAME = [$TargetSQLDatabase] ALTER DATABASE [$TargetSQLDatabase] SET MULTI_USER" SQLCMD -S $TargetSQLServer -E -Q $query LogWrite "recreating db permissions..." #recreate permissions $query = "ALTER AUTHORIZATION ON DATABASE::[$TargetSQLDatabase] TO [sa] use [$TargetSQLDatabase] ALTER User [domain\Administrators] with LOGIN = [domain\Administrators]" #enable if used #SQLCMD -S $TargetSQLServer -E -Q $query LogWrite "cleaning and shrinking database $TargetSQLDatabase ..." $query = "use $TargetSQLDatabase; ALTER DATABASE $TargetSQLDatabase SET RECOVERY SIMPLE; truncate table dbo.TestTable; DBCC SHRINKFILE('$DBLogicalFileName_Log'); DBCC SHRINKFILE('$DBLogicalFileName')" SQLCMD -S $TargetSQLServer -E -Q $query LogWrite "optimizing table indexes..." $query = "USE [$TargetSQLDatabase]; EXEC [dbo].[IndexOptimize] @IndexFragmentationMin = 5, @IndexFragmentationRebuildMin = 30, @skiplargetables = 0, @PrintInformationOnly = 0" #enable if used #SQLCMD -S $TargetSQLServer -E -Q $query LogWrite "removing old database files..." #remove all old database files $fileEntries = [IO.Directory]::GetFiles("$TargetSQLDatabaseDataRoot"); $todayDatePart = (get-date).tostring("yy_MM_dd"); foreach($fileName in $fileEntries) { if($fileName.tolower().contains("$TargetSQLDatabase".tolower()) -and -not($fileName.tolower().contains($todayDatePart))) { LogWrite $fileName #remove-item -path $fileName } } LogWrite "Done!" } catch { $msg = "Unexpected Error. Error details: $_.Exception.Message" LogWrite $msg Write-Host $msg -foreground Red }