11/*
2- EXEC dbo.DatabaseRestore
2+ EXEC dbo.sp_DatabaseRestore
33 @Database = 'LogShipMe',
44 @BackupPathFull = 'D:\Backup\SQL2016PROD1A\LogShipMe\FULL\',
55 @BackupPathLog = 'D:\Backup\SQL2016PROD1A\LogShipMe\LOG\',
66 @ContinueLogs = 0,
77 @RunRecovery = 0;
88
9- EXEC dbo.DatabaseRestore
9+ EXEC dbo.sp_DatabaseRestore
1010 @Database = 'LogShipMe',
1111 @BackupPathFull = 'D:\Backup\SQL2016PROD1A\LogShipMe\FULL\',
1212 @BackupPathLog = 'D:\Backup\SQL2016PROD1A\LogShipMe\LOG\',
1313 @ContinueLogs = 1,
1414 @RunRecovery = 0;
1515
16- EXEC dbo.DatabaseRestore
16+ EXEC dbo.sp_DatabaseRestore
1717 @Database = 'LogShipMe',
1818 @BackupPathFull = 'D:\Backup\SQL2016PROD1A\LogShipMe\FULL\',
1919 @BackupPathLog = 'D:\Backup\SQL2016PROD1A\LogShipMe\LOG\',
2020 @ContinueLogs = 1,
2121 @RunRecovery = 1;
2222
23- EXEC dbo.DatabaseRestore
23+ EXEC dbo.sp_DatabaseRestore
2424 @Database = 'LogShipMe',
2525 @BackupPathFull = 'D:\Backup\SQL2016PROD1A\LogShipMe\FULL\',
2626 @BackupPathLog = 'D:\Backup\SQL2016PROD1A\LogShipMe\LOG\',
2727 @ContinueLogs = 0,
2828 @RunRecovery = 1;
29+
30+ EXEC dbo.sp_DatabaseRestore
31+ @Database = 'LogShipMe',
32+ @BackupPathFull = 'D:\Backup\SQL2016PROD1A\LogShipMe\FULL\',
33+ @BackupPathDiff = 'D:\Backup\SQL2016PROD1A\LogShipMe\DIFF\',
34+ @BackupPathLog = 'D:\Backup\SQL2016PROD1A\LogShipMe\LOG\',
35+ @RestoreDiff = 1,
36+ @ContinueLogs = 0,
37+ @RunRecovery = 1;
38+
39+ --
40+ EXEC dbo.sp_DatabaseRestore
41+ @Database = 'LogShipMe',
42+ @BackupPathFull = '\\StorageServer\LogShipMe\FULL\',
43+ @BackupPathDiff = '\\StorageServer\LogShipMe\DIFF\',
44+ @BackupPathLog = '\\StorageServer\LogShipMe\LOG\',
45+ @RestoreDiff = 1,
46+ @ContinueLogs = 0,
47+ @RunRecovery = 1,
48+ @TestRestore = 1,
49+ @RunCheckDB = 1,
50+ @Debug = 0;
2951*/
3052
3153IF OBJECT_ID (' dbo.sp_DatabaseRestore' ) IS NULL
3254 EXEC (' CREATE PROCEDURE dbo.sp_DatabaseRestore AS RETURN 0;' )
3355GO
3456
3557ALTER PROCEDURE [dbo].[sp_DatabaseRestore]
36- @Database NVARCHAR (128 ), @RestoreDatabaseName NVARCHAR (128 ) = NULL , @BackupPathFull NVARCHAR (MAX ), @BackupPathLog NVARCHAR (MAX ),
37- @MoveFiles bit = 0 , @MoveDataDrive NVARCHAR (260 ) = NULL , @MoveLogDrive NVARCHAR (260 ) = NULL , @TestRestore bit = 0 , @RunCheckDB bit = 0 ,
38- @ContinueLogs bit = 0 , @RunRecovery bit = 0
58+ @Database NVARCHAR (128 ), @RestoreDatabaseName NVARCHAR (128 ) = NULL , @BackupPathFull NVARCHAR (MAX ), @BackupPathDiff NVARCHAR ( MAX ), @ BackupPathLog NVARCHAR (MAX ),
59+ @MoveFiles bit = 0 , @MoveDataDrive NVARCHAR (260 ) = NULL , @MoveLogDrive NVARCHAR (260 ) = NULL , @TestRestore bit = 0 , @RunCheckDB bit = 0 , @RestoreDiff bit = 0 ,
60+ @ContinueLogs bit = 0 , @RunRecovery bit = 0 , @Debug INT = 0
3961AS
4062SET NOCOUNT ON ;
4163
42- DECLARE @cmd NVARCHAR (4000 ), @sql NVARCHAR (MAX ), @LastFullBackup NVARCHAR (500 ), @BackupFile NVARCHAR (500 );
64+ DECLARE @cmd NVARCHAR (4000 ), @sql NVARCHAR (MAX ), @LastFullBackup NVARCHAR (500 ), @LastDiffBackup NVARCHAR ( 500 ), @ BackupFile NVARCHAR (500 ), @BackupDateTime AS CHAR ( 15 ), @FullLastLSN NUMERIC ( 25 , 0 ), @DiffLastLSN NUMERIC ( 25 , 0 );
4365DECLARE @FileList TABLE (BackupFile NVARCHAR (255 ));
4466
4567IF @RestoreDatabaseName IS NULL
@@ -113,7 +135,9 @@ SET @FileListParamSQL += ')' + CHAR(13) + CHAR(10);
113135SET @FileListParamSQL + = ' EXEC ('' RESTORE FILELISTONLY FROM DISK='' '' {Path}'' '' '' )' ;
114136
115137SET @sql = REPLACE (@FileListParamSQL, ' {Path}' , @BackupPathFull + @LastFullBackup);
116- PRINT @sql;
138+ IF @Debug = 2
139+ PRINT @sql;
140+
117141EXEC (@sql);
118142
119143-- Build SQL for RESTORE HEADERONLY - this will be used a bit further below
@@ -174,101 +198,136 @@ BEGIN
174198 SELECT @MoveOption = @MoveOption + logicalcmds
175199 FROM Files;
176200END ;
177-
178201IF @ContinueLogs = 0
179202BEGIN
180203 SET @sql = ' RESTORE DATABASE '+ @RestoreDatabaseName+ ' FROM DISK = '' '+ @BackupPathFull + @LastFullBackup+ ' '' WITH NORECOVERY, REPLACE' + @MoveOption+ CHAR (13 );
181204 PRINT @sql;
182- EXECUTE @sql = [dbo].[CommandExecute] @Command = @sql, @CommandType = ' RESTORE DATABASE' , @Mode = 1 , @DatabaseName = @Database, @LogToTable = ' Y' , @Execute = ' Y' ;
205+ IF @Debug = 0
206+ EXECUTE @sql = [dbo].[CommandExecute] @Command = @sql, @CommandType = ' RESTORE DATABASE' , @Mode = 1 , @DatabaseName = @Database, @LogToTable = ' Y' , @Execute = ' Y' ;
183207
184- -- get the backup completed data so we can apply tlogs from that point forwards
185-
208+ -- get the backup completed data so we can apply tlogs from that point forwards
186209 SET @sql = REPLACE (@HeadersSQL, ' {Path}' , @BackupPathFull + @LastFullBackup);
187- PRINT @sql;
210+ IF @Debug = 2
211+ PRINT @sql;
212+
188213 EXECUTE (@sql);
189-
190- DECLARE @BackupDateTime AS CHAR (15 ), @FullLastLSN NUMERIC (25 , 0 );
191-
214+ -- DECLARE @BackupDateTime AS CHAR(15), @FullLastLSN NUMERIC(25, 0); Commented out for testing
192215 SELECT @BackupDateTime = RIGHT (@LastFullBackup, 19 )
193-
194- SELECT @FullLastLSN = CAST (LastLSN AS NUMERIC ( 25 , 0 )) FROM #Headers WHERE BackupType = 1 ;
195-
216+ SELECT @FullLastLSN = CAST (LastLSN AS NUMERIC ( 25 , 0 )) FROM #Headers WHERE BackupType = 1 ;
217+ IF @Debug = 2
218+ PRINT @BackupDateTime
196219END ;
197220ELSE
198221BEGIN
199222 DECLARE @DatabaseLastLSN NUMERIC (25 , 0 );
200-
201223 SELECT @DatabaseLastLSN = CAST (f .redo_start_lsn AS NUMERIC (25 , 0 ))
202224 FROM master .sys .databases d
203225 JOIN master .sys .master_files f ON d .database_id = f .database_id
204226 WHERE d .name = @RestoreDatabaseName AND f .file_id = 1
205227END ;
206228
229+ -- Clear out table variables for differential
230+ DELETE FROM @FileList;
231+
232+ -- get list of files
233+ SET @cmd = ' DIR /b "'+ @BackupPathDiff + ' "' ;
234+ INSERT INTO @FileList (BackupFile)
235+ EXEC master .sys .xp_cmdshell @cmd;
236+
237+ -- select * from @fileList
238+ -- Find latest diff backup
239+ SELECT @LastDiffBackup = MAX (BackupFile)
240+ FROM @FileList
241+ WHERE BackupFile LIKE ' %.bak'
242+ AND
243+ BackupFile LIKE ' %'+ @Database+ ' %' ;
244+
245+ IF @RestoreDiff = 1 AND @BackupDateTime < RIGHT (@LastDiffBackup, 19 )
246+ BEGIN
247+ SET @sql = ' RESTORE DATABASE '+ @RestoreDatabaseName+ ' FROM DISK = '' '+ @BackupPathDiff + @LastDiffBackup+ ' '' WITH NORECOVERY'+ CHAR (13 );
248+ PRINT @sql;
249+ IF @Debug = 0
250+ EXECUTE @sql = [dbo].[CommandExecute] @Command = @sql, @CommandType = ' RESTORE DATABASE' , @Mode = 1 , @DatabaseName = @Database, @LogToTable = ' Y' , @Execute = ' Y' ;
251+
252+ -- get the backup completed data so we can apply tlogs from that point forwards
253+ SET @sql = REPLACE (@HeadersSQL, ' {Path}' , @BackupPathDiff + @LastDiffBackup);
254+ IF @Debug = 2
255+ PRINT @sql;
256+
257+ EXECUTE (@sql);
258+ -- DECLARE @BackupDateTime AS CHAR(15), @FullLastLSN NUMERIC(25, 0);
259+ SELECT @BackupDateTime = RIGHT (@LastDiffBackup, 19 )
260+ SELECT @DiffLastLSN = CAST (LastLSN AS NUMERIC (25 , 0 )) FROM #Headers WHERE BackupType = 5 ;
261+ END ;
262+
207263-- Clear out table variables for translogs
208264DELETE FROM @FileList;
209265
210266SET @cmd = ' DIR /b "'+ @BackupPathLog + ' "' ;
211267INSERT INTO @FileList (BackupFile)
212268EXEC master .sys .xp_cmdshell @cmd;
213-
214269-- check for log backups
215270DECLARE BackupFiles CURSOR FOR
216271 SELECT BackupFile
217272 FROM @FileList
218273 WHERE BackupFile LIKE ' %.trn'
219274 AND BackupFile LIKE ' %'+ @Database+ ' %'
220- AND (@ContinueLogs = 1 OR (@ContinueLogs = 0 AND LEFT (RIGHT (BackupFile, 19 ), 15 ) >= @BackupDateTime));
221-
275+ AND (@ContinueLogs = 1 OR (@ContinueLogs = 0 AND LEFT (RIGHT (BackupFile, 19 ), 15 ) >= @BackupDateTime))
276+ ORDER BY BackupFile;
222277OPEN BackupFiles;
223-
224278DECLARE @i tinyint = 1 , @LogFirstLSN NUMERIC (25 , 0 ), @LogLastLSN NUMERIC (25 , 0 );
225-
226279-- Loop through all the files for the database
227280FETCH NEXT FROM BackupFiles INTO @BackupFile;
228281WHILE @@FETCH_STATUS = 0
229282BEGIN
230283 IF @i = 1
231284 BEGIN
232285 SET @sql = REPLACE (@HeadersSQL, ' {Path}' , @BackupPathLog + @BackupFile);
233- PRINT @sql;
234- EXECUTE (@sql);
286+ IF @Debug = 2
287+ PRINT @sql;
288+ EXECUTE (@sql);
235289
236290 SELECT @LogFirstLSN = CAST (FirstLSN AS NUMERIC (25 , 0 )), @LogLastLSN = CAST (LastLSN AS NUMERIC (25 , 0 )) FROM #Headers WHERE BackupType = 2 ;
237291
238- IF (@ContinueLogs = 0 AND @LogFirstLSN <= @FullLastLSN AND @FullLastLSN <= @LogLastLSN) OR (@ContinueLogs = 1 AND @LogFirstLSN <= @DatabaseLastLSN AND @DatabaseLastLSN < @LogLastLSN)
292+ IF (@ContinueLogs = 0 AND @LogFirstLSN <= @FullLastLSN AND @FullLastLSN <= @LogLastLSN AND @RestoreDiff = 0 ) OR (@ContinueLogs = 1 AND @LogFirstLSN <= @DatabaseLastLSN AND @DatabaseLastLSN < @LogLastLSN AND @RestoreDiff = 0 )
293+ SET @i = 2 ;
294+ IF (@ContinueLogs = 0 AND @LogFirstLSN <= @DiffLastLSN AND @DiffLastLSN <= @LogLastLSN AND @RestoreDiff = 1 ) OR (@ContinueLogs = 1 AND @LogFirstLSN <= @DatabaseLastLSN AND @DatabaseLastLSN < @LogLastLSN AND @RestoreDiff = 1 )
239295 SET @i = 2 ;
240-
241296 DELETE FROM #Headers WHERE BackupType = 2 ;
242297 END ;
243-
244298 IF @i = 2
245299 BEGIN
246300 SET @sql = ' RESTORE LOG '+ @RestoreDatabaseName+ ' FROM DISK = '' '+ @BackupPathLog + @BackupFile+ ' '' WITH NORECOVERY'+ CHAR (13 );
247301 PRINT @sql
248- EXECUTE @sql = [dbo].[CommandExecute] @Command = @sql, @CommandType = ' RESTORE LOG' , @Mode = 1 , @DatabaseName = @Database, @LogToTable = ' Y' , @Execute = ' Y' ;
302+ IF @Debug = 0
303+ EXECUTE @sql = [dbo].[CommandExecute] @Command = @sql, @CommandType = ' RESTORE LOG' , @Mode = 1 , @DatabaseName = @Database, @LogToTable = ' Y' , @Execute = ' Y' ;
249304 END ;
250-
251305 FETCH NEXT FROM BackupFiles INTO @BackupFile;
252306END ;
253-
254307CLOSE BackupFiles;
255308DEALLOCATE BackupFiles;
256-
257309-- put database in a useable state
258310IF @RunRecovery = 1
259311BEGIN
260- SET @sql = ' RESTORE DATABASE '+ @RestoreDatabaseName+ ' WITH RECOVERY' ;
261- EXECUTE sp_executesql @sql;
312+ SET @sql = ' RESTORE DATABASE '+ @RestoreDatabaseName+ ' WITH RECOVERY'+ CHAR (13 );
313+ PRINT @sql
314+ IF @Debug = 0
315+ EXECUTE sp_executesql @sql;
262316END ;
263317
264318 -- Run checkdb against this database
265319IF @RunCheckDB = 1
266- EXECUTE [dbo].[DatabaseIntegrityCheck] @Databases = @RestoreDatabaseName, @LogToTable = ' Y' ;
267-
320+ BEGIN
321+ SET @sql = ' EXECUTE [dbo].[DatabaseIntegrityCheck] @Databases = ' + @RestoreDatabaseName + ' , @LogToTable = '' Y'' '+ CHAR (13 );
322+ PRINT @sql
323+ IF @Debug = 0
324+ EXECUTE sys .sp_executesql @sql
325+ END ;
268326 -- If test restore then blow the database away (be careful)
269327IF @TestRestore = 1
270328BEGIN
271- SET @sql = ' DROP DATABASE '+ @RestoreDatabaseName;
272- EXECUTE sp_executesql @sql;
273- END ;
274-
329+ SET @sql = ' DROP DATABASE '+ @RestoreDatabaseName+ CHAR (13 );
330+ PRINT @sql
331+ IF @Debug = 0
332+ EXECUTE sp_executesql @sql;
333+ END ;
0 commit comments