7

I am migrating SQL Server DBs to a new instance.

I have been told that it is possible to dynamically build a RESTORE script from available backups in the system catalog.

Does anyone know of a sample script to do this?

Thanks!

3 Answers 3

12

I, personally, use sp_restorecriptgenie by Paul Brewer. Here's the link to the SCC article that has it. Under 'The Procedure'

http://www.sqlservercentral.com/articles/Restore+database/95839/

Basically, once you build the stored procedure, just run exec sp_restorescriptgenie and the script will go out and get all backups for every DB (even transaction logs) and give you a script to generate them. Also generates the DBCC CHECKDB commands to check the DBs after restoring.

I actually just used this script about an hour ago so I can do a test restore and verify my backups.

0
3

there is a very good script on the link below:

How to generate database restore script in SQL Server

Based on that script I have created my stored procedure below, which works very well, although it does not generate the DBCC CHECKDB:

it needs 3 parameters:

@Database sysname - the database name you want to generate the restore
@MovePathLog NVARCHAR(1008) - where to move the transaction log file to
@MovePathData NVARCHAR(1008) - where to move the data file(s) to

Here is the code:

use master
go

IF OBJECT_ID('sp_genRestoreScripts') IS NOT NULL
   DROP PROCEDURE sp_genRestoreScripts
GO

create procedure sp_genRestoreScripts
@Database sysname,
@MovePathLog NVARCHAR(1008),
@MovePathData NVARCHAR(1008)
as begin

DECLARE @FullMediaSetID NVARCHAR(20)
DECLARE @BackupSetID NVARCHAR(20)
DECLARE @FullPath NVARCHAR(400)
DECLARE @FullPosition NVARCHAR(20)

DECLARE @LogMediaSetID NVARCHAR(20)
DECLARE @LogPath NVARCHAR(400)
DECLARE @LogPosition NVARCHAR(20)

DECLARE @DiffMediaSetID NVARCHAR(20)
DECLARE @DiffPath NVARCHAR(400)
DECLARE @DiffPosition NVARCHAR(20)

DECLARE @SQLMove NVARCHAR(MAX)
SET @SQLMove =''

IF ( @MovePathData <> '' OR @MovePathLog <> '')
BEGIN
    DECLARE @LogicalName NVARCHAR(200)
    DECLARE @FileID NVARCHAR(10)
    DECLARE @FileType NVARCHAR(10)
    DECLARE @ExtName NVARCHAR(20)

    DECLARE MoveCur CURSOR FOR 
    SELECT m.name
        ,m.file_id
        ,m.type 
    FROM sys.master_files m 
        INNER JOIN sys.databases d 
            ON m.database_id = d.database_id
    WHERE d.name = @Database

    OPEN MoveCur

    FETCH NEXT FROM MoveCur INTO @LogicalName,@FileID,@FileType

    WHILE @@FETCH_STATUS = 0
    BEGIN
        SET @ExtName = CASE  
                            WHEN @FileID = 1 THEN '.mdf'
                            WHEN @FileID > 1 THEN CASE @FileType 
                                                       WHEN 0 THEN '.ndf' 
                                                       ELSE '.ldf' 
                                                  END
                       END
        SET @SQLMove = @SQLMove + CHAR(10) + '   , MOVE ' + '''' + @LogicalName + '''' 
                       + ' TO ' + '''' + 

                      CASE @FileType 
                           WHEN 0 THEN @MovePathData 
                           ELSE @MovePathLog
                      END

                       + @LogicalName + @ExtName + ''''
        FETCH NEXT FROM MoveCur INTO @LogicalName,@FileID,@FileType     
    END
    CLOSE MoveCur
    DEALLOCATE MoveCur
END


SELECT 
    @BackupSetID = backup_set_id,
    @FullMediaSetID = media_set_id, 
    @FullPosition = position
FROM msdb.dbo.backupset 
WHERE backup_set_id =
(
    SELECT MAX(backup_set_id) 
    FROM msdb.dbo.backupset 
    WHERE database_name = @Database 
        AND type='D'
    GROUP BY database_name
)

SELECT @FullPath = physical_device_name  
FROM msdb.dbo.backupmediafamily 
WHERE media_set_id = @FullMediaSetID

IF NOT EXISTS(SELECT 1 FROM msdb.dbo.backupset 
    WHERE database_name = @Database AND type IN('L','I') AND backup_set_id > @BackupSetID)
BEGIN
    PRINT REPLICATE('-',200)
    PRINT '-----------//Full backup restore only'
    PRINT REPLICATE('-',200)
    PRINT 'RESTORE DATABASE ' + @Database + CHAR(10) 
        + ' FROM DISK = ''' + @FullPath + '''' + CHAR(10) 
        + '   WITH FILE = ' + @FullPosition + ', REPLACE' + @SQLMove
END


IF EXISTS(SELECT 1 FROM msdb.dbo.backupset 
    WHERE database_name = @Database AND type='L' AND backup_set_id > @BackupSetID)
BEGIN
    PRINT REPLICATE('-',200)
    PRINT '-----------//Full backup and log backup restore '
    PRINT REPLICATE('-',200)
    PRINT 'RESTORE DATABASE ' + @Database + CHAR(10)
        + ' FROM DISK = ''' + @FullPath + '''' + CHAR(10)
        + '   WITH FILE = ' + @FullPosition + ', NORECOVERY, REPLACE ' + @SQLMove

    DECLARE log_cursor CURSOR FOR 
    SELECT media_set_id
        ,position 
    FROM msdb.dbo.backupset 
    WHERE database_name = @Database 
        AND type='L' 
        AND backup_set_id > @BackupSetID 
    ORDER BY backup_set_id

    OPEN log_cursor

    FETCH NEXT FROM log_cursor INTO @LogMediaSetID,@LogPosition

    WHILE @@FETCH_STATUS = 0
    BEGIN
        SELECT @LogPath = physical_device_name  
        FROM msdb.dbo.backupmediafamily 
        WHERE media_set_id = @LogMediaSetID

        PRINT 'RESTORE Log ' + @Database + CHAR(10) 
            + ' FROM DISK = ''' + @LogPath
            + ''' WITH FILE = ' + @LogPosition + ', NORECOVERY'
        FETCH NEXT FROM log_cursor INTO @LogMediaSetID,@LogPosition
    END
    CLOSE log_cursor
    DEALLOCATE log_cursor

    PRINT 'RESTORE DATABASE ' + @Database + ' WITH RECOVERY '
END


IF EXISTS(SELECT 1 FROM msdb.dbo.backupset 
    WHERE database_name = @Database AND type='I' AND backup_set_id > @BackupSetID)
BEGIN
    PRINT REPLICATE('-',200)
    PRINT '-----------//Full backup and differential backup restore '
    PRINT REPLICATE('-',200)
    PRINT 'RESTORE DATABASE ' + @Database + CHAR(10)  
        + ' FROM DISK = ''' + @FullPath + '''' + CHAR(10)
        + '   WITH FILE = ' + @FullPosition + ', NORECOVERY, REPLACE ' + @SQLMove

    DECLARE diff_cursor CURSOR FOR 
    SELECT media_set_id
        ,position 
    FROM msdb.dbo.backupset 
    WHERE database_name = @Database 
        AND type='I' 
        AND backup_set_id > @BackupSetID 
    ORDER BY backup_set_id

    OPEN diff_cursor

    FETCH NEXT FROM diff_cursor INTO @DiffMediaSetID,@DiffPosition

    WHILE @@FETCH_STATUS = 0
    BEGIN
        SELECT @DiffPath = physical_device_name  
        FROM msdb.dbo.backupmediafamily 
        WHERE media_set_id = @DiffMediaSetID

        PRINT 'RESTORE DATABASE ' + @Database + CHAR(10)
            + ' FROM DISK = ''' + @DiffPath 
            + ''' WITH FILE = ' + @DiffPosition + ', NORECOVERY'

        FETCH NEXT FROM diff_cursor INTO @DiffMediaSetID,@DiffPosition
    END
    CLOSE diff_cursor
    DEALLOCATE diff_cursor

    PRINT 'RESTORE DATABASE ' + @Database + ' WITH RECOVERY '
END
end 
GO

This is how you run the procedure for a single database:

use master
go
exec sp_genRestoreScripts
        @Database ='CAAltosextracts',
        @MovePathLog ='F:\logs\',
        @MovePathData ='e:\DATA\'

and for multi-databases I use the sp_foreachdb stored procedure

     declare @db_list NVARCHAR(MAX)


     SELECT @db_list  = STUFF((
                                SELECT ', ' + name FROM sys.databases
                                WHERE name NOT IN ('DBA','TABLEBACKUPS','MASTER','MSDB','MODEL','TEMPDB')
                                FOR XML PATH(''), TYPE).value('.[1]', 'nvarchar(max)'), 1, 2, '')

     --exec sp_foreachdb @database_list = @db_list
              --       ,@command='use ?; print db_name() + char(13)'   

     exec sp_foreachdb @database_list = @db_list
                     ,@command='
                                 exec sp_genRestoreScripts
                                        @Database =[?],
                                        @MovePathLog =''F:\logs\'',
                                        @MovePathData =''E:\DATA\'' 
                               ' 
2
  • It is throwing the below error I use your multi database script Msg 103, Level 15, State 4, Line 3 The identifier that starts with '[ABC], @MovePathLog ='F:\Program Files\Microsoft SQL Server\MSSQL13.MSSQLSERVER\MSSQ' is too long. Maximum length is 128.
    – Feivel
    Commented Jul 12, 2019 at 21:36
  • @Database sysname that is 128 chars. do you want database names greater than 128? No thank you. Commented Jul 13, 2019 at 19:51
0

I am migrating SQL Server DBs to a new instance.

You can use dbatools - Copy-DbaDatabase to do backup/restore from one source to multiple destinations.

Also, for restore dbatools - Restore-DbaDatabase - allows you to just point to a backup location or Trust your msdb backup history to build commands and allow you to do a point in time restore as well. It automatically figures out full, diff and tlogs.

You can even generate your restore scripts using Export-DbaScript to a file.

Note: I have used both dbatools and sp_restoreGene - both are really good. The plus point of dbatools is that you can use other cmdlets for your entire server management.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.