Point in time restore to a new DB from files of a Full Recovery Model
This script is designed to restore to a new DB in a specific point in time from backup files (FULL/DIFF/LOG) created from Ola Hallengren's backup solution (http://ola.hallengren.com). Just fill the "Initialize variables" section and the generator will print all the necessary commands, you can review and execute them manually for extra security. Although it is based on a specific solution with little or no modifications it can be universal for all directory/file naming conventions.
USE Master;
GO
SET NOCOUNT ON
-- 1 - Variable declaration
DECLARE @RestoredbName sysname
DECLARE @OriginaldbName sysname
DECLARE @backupPath NVARCHAR(500)
DECLARE @RestorePath NVARCHAR(500)
DECLARE @cmd NVARCHAR(3000)
DECLARE @comments NVARCHAR(250)
DECLARE @fileList TABLE (backupFile NVARCHAR(255))
DECLARE @lastFullBackup NVARCHAR(500)
DECLARE @lastDiffBackup NVARCHAR(500)
DECLARE @backupFile NVARCHAR(500)
DECLARE @PointInTime NVARCHAR(50)
-- 2 - Initialize variables
SET @OriginaldbName = 'GLDatabase'
SET @RestoredbName = 'GLDatabase_Restore'
SET @backupPath = 'D:\SQL_DATA\DatabaseWeeklyBackup\'
SET @RestorePath = 'D:\SQL_DATA\GL\'
SET @PointInTime = N'2011-05-19 17:05:15'
-- 3 - Create Database to restore to
SET @cmd =
'CREATE DATABASE ['+@RestoredbName+'] ON PRIMARY
( NAME = N'''+@RestoredbName+''', FILENAME = N'''+@RestorePath+@RestoredbName+'.mdf'', SIZE = 100000KB , FILEGROWTH = 10% )
LOG ON
( NAME = N'''+@RestoredbName+'_log'', FILENAME = N'''+@RestorePath+@RestoredbName+'_log.ldf'', SIZE = 1024KB , FILEGROWTH = 5%)
GO
ALTER DATABASE ['+@RestoredbName+'] SET COMPATIBILITY_LEVEL = 100
GO
ALTER DATABASE ['+@RestoredbName+'] SET ANSI_NULL_DEFAULT OFF
GO
ALTER DATABASE ['+@RestoredbName+'] SET ANSI_NULLS OFF
GO
ALTER DATABASE ['+@RestoredbName+'] SET ANSI_PADDING OFF
GO
ALTER DATABASE ['+@RestoredbName+'] SET ANSI_WARNINGS OFF
GO
ALTER DATABASE ['+@RestoredbName+'] SET ARITHABORT OFF
GO
ALTER DATABASE ['+@RestoredbName+'] SET AUTO_CLOSE OFF
GO
ALTER DATABASE ['+@RestoredbName+'] SET AUTO_CREATE_STATISTICS ON
GO
ALTER DATABASE ['+@RestoredbName+'] SET AUTO_SHRINK OFF
GO
ALTER DATABASE ['+@RestoredbName+'] SET AUTO_UPDATE_STATISTICS ON
GO
ALTER DATABASE ['+@RestoredbName+'] SET CURSOR_CLOSE_ON_COMMIT OFF
GO
ALTER DATABASE ['+@RestoredbName+'] SET CURSOR_DEFAULT GLOBAL
GO
ALTER DATABASE ['+@RestoredbName+'] SET CONCAT_NULL_YIELDS_NULL OFF
GO
ALTER DATABASE ['+@RestoredbName+'] SET NUMERIC_ROUNDABORT OFF
GO
ALTER DATABASE ['+@RestoredbName+'] SET QUOTED_IDENTIFIER OFF
GO
ALTER DATABASE ['+@RestoredbName+'] SET RECURSIVE_TRIGGERS OFF
GO
ALTER DATABASE ['+@RestoredbName+'] SET DISABLE_BROKER
GO
ALTER DATABASE ['+@RestoredbName+'] SET AUTO_UPDATE_STATISTICS_ASYNC OFF
GO
ALTER DATABASE ['+@RestoredbName+'] SET DATE_CORRELATION_OPTIMIZATION OFF
GO
ALTER DATABASE ['+@RestoredbName+'] SET PARAMETERIZATION SIMPLE
GO
ALTER DATABASE ['+@RestoredbName+'] SET READ_WRITE
GO
ALTER DATABASE ['+@RestoredbName+'] SET RECOVERY SIMPLE
GO
ALTER DATABASE ['+@RestoredbName+'] SET MULTI_USER
GO
ALTER DATABASE ['+@RestoredbName+'] SET PAGE_VERIFY CHECKSUM
GO
USE ['+@RestoredbName+']
GO
IF NOT EXISTS (SELECT name FROM sys.filegroups WHERE is_default=1 AND name = N''PRIMARY'') ALTER DATABASE ['+@RestoredbName+'] MODIFY FILEGROUP [PRIMARY] DEFAULT
GO
'
PRINT @cmd
PRINT ''
SET @cmd = 'USE Master;'
PRINT @cmd
-- 4 - get list of files
SET @cmd = 'DIR /b /s ' + @backupPath
INSERT INTO @fileList(backupFile)
EXEC master.sys.xp_cmdshell @cmd
SET @comments = 'PRINT ''Starting Restoration at:'' + CONVERT(VARCHAR(20),GETDATE(),113)'
PRINT @comments
-- 5 - Find latest full backup
SELECT @lastFullBackup = MAX(backupFile)
FROM @fileList
WHERE backupFile LIKE '%_FULL_%.bak'
AND
RIGHT(backupFile,19) < REPLACE(REPLACE(REPLACE(CONVERT(VARCHAR(30),@PointInTime,120),'-',''),':',''),' ','_')+'.bak'
SET @cmd = 'RESTORE DATABASE [' + @RestoredbName + '] FROM DISK = N'''
+ @lastFullBackup + '''
WITH FILE = 1,
MOVE N'''+@OriginaldbName+''' TO N'''+@RestorePath+@RestoredbName+'.mdf'',
MOVE N'''+@OriginaldbName+'_log'' TO N'''+@RestorePath+@RestoredbName+'_log.ldf'',
NORECOVERY, NOUNLOAD, REPLACE, STATS = 10'
SET @comments = 'PRINT ''Restoring Database Full Backup:'''
PRINT @comments
PRINT @cmd
-- 6 - Find latest diff backup
SELECT @lastDiffBackup = MAX(backupFile)
FROM @fileList
WHERE backupFile LIKE '%_DIFF_%.bak'
AND RIGHT(backupFile,19) > RIGHT(@lastFullBackup,19)
AND
RIGHT(backupFile,19) < REPLACE(REPLACE(REPLACE(CONVERT(VARCHAR(30),@PointInTime,120),'-',''),':',''),' ','_')+'.bak'
-- check to make sure there is a diff backup
IF @lastDiffBackup IS NOT NULL
BEGIN
SET @cmd = 'RESTORE DATABASE [' + @RestoredbName + '] FROM DISK = N'''
+ @lastDiffBackup + '''
WITH FILE = 1,
MOVE N'''+@OriginaldbName+''' TO N'''+@RestorePath+@RestoredbName+'.mdf'',
MOVE N'''+@OriginaldbName+'_log'' TO N'''+@RestorePath+@RestoredbName+'_log.ldf'',
NORECOVERY, NOUNLOAD, REPLACE, STATS = 10'
SET @comments = 'PRINT ''Restoring Database Nearest Differential Backup:'''
PRINT @comments
PRINT @cmd
SET @lastFullBackup = @lastDiffBackup
END
-- 7 - check for log backups
DECLARE backupFiles CURSOR FOR
SELECT backupFile
FROM
(
SELECT ROW_NUMBER() OVER (ORDER BY backupFile) AS RowNumber, backupFile
FROM @fileList
WHERE backupFile LIKE '%_LOG_%.trn'
AND RIGHT(backupFile,19) > RIGHT(@lastFullBackup,19)
) LogFiles
WHERE RowNumber <=
(
SELECT ISNULL(MAX(derivdtbl.RowNumber),0) + 1
FROM
(
SELECT ROW_NUMBER() OVER (ORDER BY backupFile) AS RowNumber, backupFile
FROM @fileList
WHERE backupFile LIKE '%_LOG_%.trn'
AND RIGHT(backupFile,19) > RIGHT(@lastFullBackup,19))
AS derivdtbl
WHERE
RIGHT(derivdtbl.backupFile,19) < REPLACE(REPLACE(REPLACE(CONVERT(VARCHAR(30),@PointInTime,120),'-',''),':',''),' ','_')+'.trn'
AND RIGHT(backupFile,19) > RIGHT(@lastFullBackup,19)
)
SET @comments = 'PRINT ''Restoring Sequentially Log Backups:'''
PRINT @comments
OPEN backupFiles
-- Loop through all the files for the database
FETCH NEXT FROM backupFiles INTO @backupFile
WHILE @@FETCH_STATUS = 0
BEGIN
SET @cmd = 'RESTORE LOG [' + @RestoredbName + '] FROM DISK = N'''
+ @backupFile + ''' WITH NORECOVERY, NOUNLOAD, STATS = 10, STOPAT = N'''+ @PointInTime +''''
PRINT @cmd
FETCH NEXT FROM backupFiles INTO @backupFile
END
CLOSE backupFiles
DEALLOCATE backupFiles
-- 8 - put database in a useable state
SET @comments = 'PRINT ''Bringing Database to Online Status...'''
PRINT @comments
SET @cmd = 'RESTORE DATABASE [' + @RestoredbName + '] WITH RECOVERY'
PRINT @cmd
SET @comments = 'PRINT ''Succesfully restored database ' +@OriginaldbName+ ' to ' +@RestoredbName+ ' as it was on ' +@PointInTime+ '. Finished at '' +CONVERT(VARCHAR(20),GETDATE(),113)'
PRINT @comments