SQL Server Forums
Profile | Register | Active Topics | Members | Search | Forum FAQ
 
Register Now and get your question answered!
Username:
Password:
Save Password
Forgot your Password?

 All Forums
 General SQL Server Forums
 Script Library
 Create Restore Command from multiple DB Backup Fil
 New Topic  Reply to Topic
 Printer Friendly
Author Previous Topic Topic Next Topic  

Lumbago
Norsk Yak Master

Norway
3271 Posts

Posted - 04/30/2008 :  08:02:29  Show Profile  Reply with Quote
This script was originally posted by Michael Valentine Jones in this thread -> http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=71665. I simply added the functionality to script the restore command for all backup-files in a given folder + the posibility to alter the location of the data/log-files.
/*
Create Restore Command from multiple DB Backup Files
Originally created by Michael Valentine Jones, SQLTeam.com
- Modified by Henning Frettem
*/

SET NOCOUNT ON
GO

DECLARE 
  @backup_path nvarchar(500),
  @totCount int,
  @Current int,
  @dirCmd varchar(200),
  @Filename varchar(200),
  @tab varchar(1), 
  @cr varchar(2),
  @new_data_path varchar(500),
  @new_log_path varchar(500)

SELECT @backup_path =   'D:\Backups\'           --> Folder where full database backupfiles are located
SELECT @new_data_path = 'D:\new_data_path\'     --> Optional, leave blank to use the default from the backup file
SELECT @new_log_path =  'D:\new_log_path\'      --> Optional, leave blank to use the default from the backup file

CREATE TABLE #BackupFiles ( 
  ID INT IDENTITY(1, 1) PRIMARY KEY CLUSTERED,
  [Filename] VARCHAR(500)
)

SET @dirCmd = 'dir /b "' + @backup_path + '" '

INSERT INTO #BackupFiles ([Filename])
EXEC xp_cmdshell @dirCmd

--> Delete excess row in #BackupFiles
DELETE #BackupFiles WHERE [Filename] IS NULL

CREATE TABLE #header (
  BackupName        nvarchar(128) NULL,
  BackupDescription nvarchar(128) NULL,
  BackupType        int           NOT NULL,
  ExpirationDate    datetime      NULL,
  Compressed        int           NOT NULL,
  Position          int           NOT NULL,
  DeviceType        int           NOT NULL,
  UserName          nvarchar(128) NOT NULL,
  ServerName        nvarchar(128) NOT NULL,
  DatabaseName      nvarchar(128) NOT NULL,
  DatabaseVersion   int           NOT NULL,
  DatabaseCreationDate  datetime  NOT NULL,
  BackupSize        decimal(28,0) NOT NULL,
  FirstLsn          decimal(28,0) NOT NULL,
  LastLsn           decimal(28,0) NOT NULL,
  CheckpointLsn     decimal(28,0) NOT NULL,
  DatabaseBackupLsn decimal(28,0) NOT NULL,
  BackupStartDate   datetime      NOT NULL,
  BackupFinishDate  datetime      NOT NULL,
  SortOrder         int           NOT NULL,
  CodePage          int           NOT NULL,
  UnicodeLocaleId   int           NOT NULL,
  UnicodeComparisonStyle  int     NOT NULL,
  CompatibilityLevel      int     NOT NULL,
  SoftwareVendorId        int     NULL,
  SoftwareVersionMajor    int     NULL,
  SoftwareVersionMinor    int     NULL,
  SoftwareVersionBuild    int     NULL,
  MachineName       nvarchar(128) NOT NULL,
  Flags             int           NULL,
  BindingID         uniqueidentifier NULL,
  RecoveryForkID    uniqueidentifier NULL,
  Collation         nvarchar(128) NULL,
  Seq               int           NOT NULL identity(1,1),
)

CREATE TABLE #filelist (
  LogicalName   nvarchar(128) NOT NULL,
  PhysicalName  nvarchar(128) NOT NULL,
  Type          nvarchar(10)  NOT NULL,
  FileGroupName nvarchar(128) NULL,
  Size          decimal(28,0) NOT NULL,
  MAXSize       decimal(28,0) NOT NULL,
  Seq           int           NOT NULL identity(1,1),
)


SET @totCount = (SELECT COUNT(*) FROM #BackupFiles)
SET @Current = 1
SELECT @tab = char(9), @cr = char(13)+Char(10)

--> Loop through the files that hasn't been restored before and restore them one by one
WHILE (@Current <= @totCount AND @totCount > 0)
  BEGIN
    SELECT @Filename = [Filename] FROM #BackupFiles WHERE ID = @Current

    INSERT INTO #header
    EXEC ('RESTORE HeaderOnly FROM DISK = ''' + @backup_path + @Filename + '''')

    INSERT INTO #filelist
    EXEC ('RESTORE FilelistOnly FROM DISK = ''' + @backup_path + @Filename + '''')

    --> Replace the old data file path with a new one if specified
    IF @new_data_path <> ''
      UPDATE #filelist 
        SET PhysicalName = @new_data_path + right(physicalname, CHARINDEX('\',REVERSE(physicalname))-1)
      WHERE Type = 'D'

    --> Replace the old log file path with a new one if specified
    IF @new_data_path <> ''
      UPDATE #filelist 
        SET PhysicalName = @new_log_path + right(physicalname, CHARINDEX('\',REVERSE(physicalname))-1)
      WHERE Type = 'L'

    --> Print restore script
    SELECT
      [--Restore--] = CASE
        WHEN a.Seq = 1 THEN @cr +
          @cr + 'RESTORE DATABASE ' + c.DatabaseName +
          @cr + 'FROM DISK =' + @cr + @tab + '''' +
          @backup_path + @Filename + '''' + @cr + 'WITH' + @cr
        ELSE ''
        END 
        +
        @tab + 'MOVE ''' + a.LogicalName + ''' TO ''' + a.PhysicalName+''' ,'
        +
        CASE WHEN a.Seq = b.Seq THEN
          @cr + @tab + 'REPLACE, STATS = 5 , NORECOVERY'
        ELSE ''
        END
    FROM
      #filelist a
      CROSS JOIN
      (SELECT Seq = MAX(b1.Seq) FROM #filelist b1 ) b
      CROSS JOIN
      (SELECT DatabaseName = MAX(c1.DatabaseName) 
        FROM #header c1) c
    ORDER BY
      a.Seq

    SET @Current = @Current + 1

    TRUNCATE TABLE #header
    TRUNCATE TABLE #filelist
  END

DROP TABLE #header
DROP TABLE #filelist
DROP TABLE #BackupFiles


--
Lumbago

JohnnyG
Starting Member

USA
1 Posts

Posted - 08/08/2008 :  09:41:32  Show Profile  Reply with Quote
Would it be possible to update the script to do a recursive loop thru the backup directory to get any additional backup files in subdirectories underneath the original backup path?
Go to Top of Page

Lumbago
Norsk Yak Master

Norway
3271 Posts

Posted - 03/13/2009 :  10:33:08  Show Profile  Reply with Quote
Wow...just noticed the reply to this thread now...6 months late [:S]

But yes, this is actually *really* simple!! Just add a /s to the dir command:

SET @dirCmd = 'dir /b /s "' + @backup_path + '" '



- Lumbago
Go to Top of Page

cshah1
Constraint Violating Yak Guru

347 Posts

Posted - 04/10/2009 :  15:50:03  Show Profile  Reply with Quote
Lumbago,
in SQL 2005 when I run your script getting this error

Msg 213, Level 16, State 7, Line 1
Insert Error: Column name or number of supplied values does not match table definition


???
Go to Top of Page

Lumbago
Norsk Yak Master

Norway
3271 Posts

Posted - 04/14/2009 :  03:07:59  Show Profile  Reply with Quote
Script for 2005:
/*
Create Restore Command from multiple DB Backup Files
Originally created by Michael Valentine Jones, SQLTeam.com
- Modified by Henning Frettem
REMEMBER TO INCREASE MAX CHARACTER OUTPUT FOR EACH COLUMN BEFORE RUNNING THIS SCRIPT!!
*/
SET NOCOUNT ON
GO

DECLARE
  @backup_path varchar(500),
  @totCount int,
  @Current int,
  @dirCmd varchar(200),
  @Filename varchar(200),
  @tab varchar(1),
  @cr varchar(2),
  @new_data_path varchar(500),
  @new_log_path varchar(500)

SELECT @backup_path = 'D:\Backups\' --> Folder where full database backupfiles are located
SELECT @new_data_path = 'D:\new_data_file_path\' --> Optional, leave blank to use the default from the backup file
SELECT @new_log_path = 'D:\new_log_file_path\' --> Optional, leave blank to use the default from the backup file

CREATE TABLE #BackupFiles (
  ID INT IDENTITY(1, 1) PRIMARY KEY CLUSTERED,
  [Filename] VARCHAR(500)
)

SET @dirCmd = 'dir /b "' + @backup_path + 'Full*.bak" '

INSERT INTO #BackupFiles ([Filename])
EXEC xp_cmdshell @dirCmd

--> Delete excess row in #BackupFiles
DELETE #BackupFiles WHERE [Filename] IS NULL OR [Filename] NOT LIKE '%.bak'

CREATE TABLE #header (
  BackupName varchar(128) NULL,
  BackupDescription varchar(255) NULL,
  BackupType smallint NULL,
  ExpirationDate datetime NULL,
  Compressed tinyint NULL,
  Position smallint NULL,
  DeviceType tinyint NULL,
  UserName varchar(128) NULL,
  ServerName varchar(128) NULL,
  DatabaseName varchar(128) NULL,
  DatabaseVersion int NULL,
  DatabaseCreationDate datetime NULL,
  BackupSize numeric(20,0) NULL,
  FirstLSN numeric(25,0) NULL,
  LastLSN numeric(25,0) NULL,
  CheckpointLSN numeric(25,0) NULL,
  DatabaseBackupLSN numeric(25,0) NULL,
  BackupStartDate datetime NULL,
  BackupFinishDate datetime NULL,
  SortOrder smallint NULL,
  CodePage smallint NULL,
  UnicodeLocaleId int NULL,
  UnicodeComparisonStyle int NULL,
  CompatibilityLevel tinyint NULL,
  SoftwareVendorId int NULL,
  SoftwareVersionMajor int NULL,
  SoftwareVersionMinor int NULL,
  SoftwareVersionBuild int NULL,
  MachineName varchar(128) NULL,
  Flags int NULL,
  BindingID uniqueidentifier NULL,
  RecoveryForkID uniqueidentifier NULL,
  Collation varchar(128) NULL,
  FamilyGUID uniqueidentifier NULL,
  HasBulkLoggedData bit NULL,
  IsSnapshot bit NULL,
  IsReadOnly bit NULL,
  IsSingleUser bit NULL,
  HasBackupChecksums bit NULL,
  IsDamaged bit NULL,
  BeginsLogChain bit NULL,
  HasIncompleteMetaData bit NULL,
  IsForceOffline bit NULL,
  IsCopyOnly bit NULL,
  FirstRecoveryForkID uniqueidentifier NULL,
  ForkPointLSN numeric(25,0) NULL,
  RecoveryModel varchar(60) NULL,
  DifferentialBaseLSN numeric(25,0) NULL,
  DifferentialBaseGUID uniqueidentifier NULL,
  BackupTypeDescription varchar(60) NULL,
  BackupSetGUID uniqueidentifier NULL,
  Seq int NOT NULL identity(1,1)
)

CREATE TABLE #filelist (
  LogicalName varchar(128) NULL,
  PhysicalName varchar(260) NULL,
  Type char(1) NULL,
  FileGroupName varchar(128) NULL,
  Size numeric(20,0) NULL,
  MaxSize numeric(20,0) NULL,
  FileID bigint NULL,
  CreateLSN numeric(25,0) NULL,
  DropLSN numeric(25,0) NULL,
  UniqueID uniqueidentifier NULL,
  ReadOnlyLSN numeric(25,0) NULL,
  ReadWriteLSN numeric(25,0) NULL,
  BackupSizeInBytes bigint NULL,
  SourceBlockSize int NULL,
  FileGroupID int NULL,
  LogGroupGUID uniqueidentifier NULL,
  DifferentialBaseLSN numeric(25,0) NULL,
  DifferentialBaseGUID uniqueidentifier NULL,
  IsReadOnly bit NULL,
  IsPresent bit NULL,
  Seq int NOT NULL identity(1,1)
)

SET @totCount = (SELECT COUNT(*) FROM #BackupFiles)
SET @Current = 1

SELECT @tab = char(9), @cr = char(13)+Char(10)

--> Loop through the files that hasn't been restored before and restore them one by one
WHILE (@Current <= @totCount AND @totCount > 0)
  BEGIN
    SELECT @Filename = [Filename] FROM #BackupFiles WHERE ID = @Current
    INSERT INTO #header
    EXEC ('RESTORE HeaderOnly FROM DISK = ''' + @backup_path + @Filename + '''')

    INSERT INTO #filelist
    EXEC ('RESTORE FilelistOnly FROM DISK = ''' + @backup_path + @Filename + '''')

    --> Replace the old data file path with a new one if specified
    IF @new_data_path <> ''
      UPDATE #filelist
      SET PhysicalName = @new_data_path + right(physicalname,
      CHARINDEX('\',REVERSE(physicalname))-1)
      WHERE Type = 'D'

    --> Replace the old log file path with a new one if specified
    IF @new_data_path <> ''
      UPDATE #filelist
      SET PhysicalName = @new_log_path + right(physicalname,
      CHARINDEX('\',REVERSE(physicalname))-1)
      WHERE Type = 'L'

    --> Print restore script
    SELECT
      [--Restore--] = CASE
        WHEN a.Seq = 1 THEN @cr +
          @cr + 'RESTORE DATABASE [' + c.DatabaseName + ']' +
          @cr + 'FROM DISK =' + @cr + @tab + '''' +
          @backup_path + @Filename + '''' + @cr + 'WITH' + @cr
        ELSE ''
        END
        +
        @tab + 'MOVE ''' + a.LogicalName + ''' TO ''' + a.PhysicalName + ''' ,'
        +
        CASE WHEN a.Seq = b.Seq THEN
          @cr + @tab + 'REPLACE, STATS = 5 , --NORECOVERY'
        ELSE ''
        END
    FROM
      #filelist a
      CROSS JOIN
        (SELECT Seq = MAX(b1.Seq) FROM #filelist b1 ) b
      CROSS JOIN
        (SELECT DatabaseName = MAX(c1.DatabaseName) FROM #header c1) c
    ORDER BY
      a.Seq

    SET @Current = @Current + 1

    TRUNCATE TABLE #header
    TRUNCATE TABLE #filelist
END

DROP TABLE #header
DROP TABLE #filelist
DROP TABLE #BackupFiles


- Lumbago
Go to Top of Page

Lumbago
Norsk Yak Master

Norway
3271 Posts

Posted - 01/06/2011 :  04:22:41  Show Profile  Reply with Quote
2008-version:
/*
Create Restore Command from multiple DB Backup Files
Originally created by Michael Valentine Jones, SQLTeam.com
- Modified by Henning Frettem
REMEMBER TO INCREASE MAX CHARACTER OUTPUT FOR EACH COLUMN BEFORE RUNNING THIS SCRIPT!!
*/
SET NOCOUNT ON
GO

DECLARE
  @backup_path varchar(500),
  @totCount int,
  @Current int,
  @dirCmd varchar(200),
  @Filename varchar(200),
  @DatabaseName varchar(200),
  @CreateDBFolder bit,
  @tab varchar(1),
  @cr varchar(2),
  @new_data_path varchar(500),
  @new_data_path2 varchar(500),
  @new_log_path varchar(500),
  @new_log_path2 varchar(500)

SELECT @backup_path = 'e:\full_Backups\' --> Folder where full database backupfiles are located
SELECT @new_data_path = 'E:\MSSQL2005\Data\' --> Optional, leave blank to use the default from the backup file
SELECT @new_log_path = 'F:\MSSQL2005\Logs\' --> Optional, leave blank to use the default from the backup file
SELECT @CreateDBFolder = 1  --> If 1 is specidied the data/log files will be placed in a separate folder named after the database

CREATE TABLE #BackupFiles (
  ID INT IDENTITY(1, 1) PRIMARY KEY CLUSTERED,
  [Filename] VARCHAR(500)
)

SET @dirCmd = 'dir /b "' + @backup_path + '*full.bak" '

INSERT INTO #BackupFiles ([Filename])
EXEC xp_cmdshell @dirCmd

--> Delete excess row in #BackupFiles
DELETE #BackupFiles WHERE [Filename] IS NULL OR [Filename] NOT LIKE '%.bak'

CREATE TABLE #header (
  BackupName nvarchar(128),
  BackupDescription nvarchar(255),
  BackupType smallint,
  ExpirationDate datetime,
  Compressed bit,
  Position smallint,
  DeviceType tinyint,
  UserName nvarchar(128),
  ServerName nvarchar(128),
  DatabaseName nvarchar(128),
  DatabaseVersion int,
  DatabaseCreationDate datetime,
  BackupSize numeric(20,0),
  FirstLSN numeric(25,0),
  LastLSN numeric(25,0),
  CheckpointLSN numeric(25,0),
  DatabaseBackupLSN numeric(25,0),
  BackupStartDate datetime,
  BackupFinishDate datetime,
  SortOrder smallint,
  CodePage smallint,
  UnicodeLocaleId int,
  UnicodeComparisonStyle int,
  CompatibilityLevel tinyint,
  SoftwareVendorId int,
  SoftwareVersionMajor int,
  SoftwareVersionMinor int,
  SoftwareVersionBuild int,
  MachineName nvarchar(128),
  Flags  int,
  BindingID uniqueidentifier,
  RecoveryForkID uniqueidentifier,
  Collation nvarchar(128),
  FamilyGUID uniqueidentifier,
  HasBulkLoggedData bit,
  IsSnapshot bit,
  IsReadOnly bit,
  IsSingleUser bit,
  HasBackupChecksums bit,
  IsDamaged bit,
  BeginsLogChain bit,
  HasIncompleteMetaData bit,
  IsForceOffline bit,
  IsCopyOnly bit,
  FirstRecoveryForkID uniqueidentifier,
  ForkPointLSN numeric(25,0) NULL,
  RecoveryModel nvarchar(60),
  DifferentialBaseLSN numeric(25,0) NULL,
  DifferentialBaseGUID uniqueidentifier,
  BackupTypeDescription nvarchar(60),
  BackupSetGUID uniqueidentifier NULL,
  CompressedBackupSize bigint,
  Seq int NOT NULL identity(1,1)
  )
  
CREATE TABLE #filelist (
  LogicalName nvarchar(128),
  PhysicalName nvarchar(260),
  Type char(1),
  FileGroupName nvarchar(128),
  Size numeric(20,0),
  MaxSize numeric(20,0),
  FileID bigint,
  CreateLSN numeric(25,0),
  DropLSN numeric(25,0) NULL,
  UniqueID uniqueidentifier,
  ReadOnlyLSN numeric(25,0) NULL,
  ReadWriteLSN numeric(25,0) NULL,
  BackupSizeInBytes bigint,
  SourceBlockSize int,
  FileGroupID int,
  LogGroupGUID uniqueidentifier NULL,
  DifferentialBaseLSN numeric(25,0) NULL,
  DifferentialBaseGUID uniqueidentifier,
  IsReadOnly bit,
  IsPresent bit,
  TDEThumbprint varbinary(32),
  Seq int NOT NULL identity(1,1)
  )

SET @totCount = (SELECT COUNT(*) FROM #BackupFiles)
SET @Current = 1

SELECT @tab = char(9), @cr = char(13)+Char(10)

--> Loop through the files that hasn't been restored before and restore them one by one
WHILE (@Current <= @totCount AND @totCount > 0)
  BEGIN
    SELECT @Filename = [Filename] FROM #BackupFiles WHERE ID = @Current
    INSERT INTO #header
    EXEC ('RESTORE HeaderOnly FROM DISK = ''' + @backup_path + @Filename + '''')

    INSERT INTO #filelist
    EXEC ('RESTORE FilelistOnly FROM DISK = ''' + @backup_path + @Filename + '''')

    SELECT 
      @DatabaseName = Databasename,
      @new_data_path2 = CASE 
        WHEN @CreateDBFolder = 1 THEN @new_data_path + DatabaseName + '\' 
        ELSE @new_data_path
        END,
      @new_log_path2 = CASE 
        WHEN @CreateDBFolder = 1 THEN @new_log_path + DatabaseName + '\' 
        ELSE @new_log_path
        END
    FROM #header

    --> Replace the old data file path with a new one if specified
    IF @new_data_path2 <> ''
      UPDATE #filelist
      SET PhysicalName = @new_data_path2 + right(physicalname,
      CHARINDEX('\',REVERSE(physicalname))-1)
      WHERE Type = 'D'

    --> Replace the old log file path with a new one if specified
    IF @new_log_path2 <> ''
      UPDATE #filelist
      SET PhysicalName = @new_log_path2 + right(physicalname,
      CHARINDEX('\',REVERSE(physicalname))-1)
      WHERE Type = 'L'

    --> Print restore script
    SELECT
      [--Restore--] = 
        CASE 
          WHEN a.Seq = 1 AND @CreateDBFolder = 1 THEN 
            @cr + 'EXEC xp_cmdshell ''md ' + @new_data_path2 + '''' +
            @cr + 'EXEC xp_cmdshell ''md ' + @new_log_path2 + ''''
          ELSE ''
        END
        +
        CASE
          WHEN a.Seq = 1 THEN @cr +
            @cr + 'RESTORE DATABASE [' + c.DatabaseName + ']' +
            @cr + 'FROM DISK =' + @cr + @tab + '''' +
            @backup_path + @Filename + '''' + @cr + 'WITH' + @cr
          ELSE ''
        END
        +
        @tab + 'MOVE ''' + a.LogicalName + ''' TO ''' + a.PhysicalName + ''' ,'
        +
        CASE 
          WHEN a.Seq = b.Seq THEN
            @cr + @tab + 'REPLACE, STATS = 5, --NORECOVERY'
          ELSE ''
        END
    FROM
      #filelist a
      CROSS JOIN
        (SELECT Seq = MAX(b1.Seq) FROM #filelist b1 ) b
      CROSS JOIN
        (SELECT DatabaseName = MAX(c1.DatabaseName) FROM #header c1) c
    ORDER BY
      a.Seq

    SET @Current = @Current + 1

    TRUNCATE TABLE #header
    TRUNCATE TABLE #filelist
END

DROP TABLE #header
DROP TABLE #filelist
DROP TABLE #BackupFiles


- Lumbago

My blog (yes, I have a blog now! just not that much content yet)
-> www.thefirstsql.com
Go to Top of Page
  Previous Topic Topic Next Topic  
 New Topic  Reply to Topic
 Printer Friendly
Jump To:
SQL Server Forums © 2000-2009 SQLTeam Publishing, LLC Go To Top Of Page
This page was generated in 0.16 seconds. Powered By: Snitz Forums 2000