通过脚本恢复由多个文件组成的数据库备份

时间:2014-10-15 05:16:32

标签: sql-server tsql database-backups database-restore

我经常需要从我的SQL服务器上的备份文件中恢复数据库,并且我有一个可配置的脚本来处理这个问题。基本上,脚本使用RESTORE命令,并且全部都有变量来替换数据库名称,bak文件夹等。但是,我面临的一个问题是恢复一个数据库,该数据库被分成多个文件,有时数量会增加到100。 / p>

所以我的问题是如何使脚本动态化,以便我可以指定文件计数,脚本将遍历所有文件并恢复它。据我所知,RESTORE命令不允许这种灵活性。

我现在看到的一个选项是动态生成整个RESTORE命令然后执行它,但我只想将它作为最后一个选项使用。

还有其他选择吗?

谢谢,

2 个答案:

答案 0 :(得分:1)

我不确定我是否理解“指定文件计数”,但我使用某种脚本为自己实现测试环境。我希望它对你有所帮助。随意问我

declare @fileListTable table
(
    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),
    UniqueID             uniqueidentifier,
    ReadOnlyLSN          numeric(25,0),
    ReadWriteLSN         numeric(25,0),
    BackupSizeInBytes    bigint,
    SourceBlockSize      int,
    FileGroupID          int,
    LogGroupGUID         uniqueidentifier,
    DifferentialBaseLSN  numeric(25,0),
    DifferentialBaseGUID uniqueidentifier,
    IsReadOnl            bit,
    IsPresent            bit,
    TDEThumbprint        varbinary(32)
)
insert into @fileListTable exec('restore filelistonly from disk = ''C:\Share\BackUp\Reporting\Prod23.bak''') -- hear I get all files from backup
select * from @fileListTable

declare @sctript nvarchar(max)
select 
@sctript = 'restore database Prod from disk = ''C:\Share\BackUp\Reporting\Prod23.bak'' WITH FILE = 1,' + 
STUFF( (SELECT results.MoveTo + ' , '
                             from 
        (
        select
        'MOVE ''' + LogicalName+ ''' TO ''E:\MobiledbnkDB_Report\' + LogicalName +
        case [Type]
         when 'D' then '.mdf'
         when 'L' then '.ldf'
        end  + ''' ' as MoveTo
        FROM @fileListTable -- hear I mode files to another folder
        ) as results
                             FOR XML PATH('')),
                            1, 0, '')
+ ' NOUNLOAD,  STATS = 5'



use master

if exists(SELECT *  FROM sys.databases d WITH(NOLOCK) where d.name = 'Prod')
begin 
 alter database Prod set restricted_user with rollback immediate
 drop database Prod
end

print @sctript
exec (@sctript)

答案 1 :(得分:0)

我认为您正在寻找的是我提出的用于恢复未压缩的LiteSpeed文件的解决方案。由于文件数量根据备份时litespeed可用的线程数而有所不同,因此我们永远不知道要还原到报告环境需要包含多少文件。我使用了Vladimir使用stuff函数和另一个脚本来执行以下操作。将FILELOCATION替换为您的文件夹并更新您的数据库,数据和日志文件名。

Declare @BackupFolder nvarchar(100) = N'FILELOCATION'
DECLARE @BackupDirectory SYSNAME = @BackupFolder

IF OBJECT_ID('tempdb..#DirTree') IS NOT NULL
DROP TABLE #DirTree

CREATE TABLE #DirTree (
Id int identity(1,1),
SubDirectory nvarchar(255),
Depth smallint,
FileFlag bit,
ParentDirectoryID int
)

INSERT INTO #DirTree (SubDirectory, Depth, FileFlag)
EXEC master..xp_dirtree @BackupDirectory, 10, 1

UPDATE #DirTree
SET ParentDirectoryID = (
SELECT MAX(Id) FROM #DirTree d2
WHERE Depth = d.Depth - 1 AND d2.Id < d.Id
)
FROM #DirTree d

DECLARE 
@ID INT,
@BackupFile VARCHAR(MAX),
@Depth TINYINT,
@FileFlag BIT,
@ParentDirectoryID INT,
@wkSubParentDirectoryID INT,
@wkSubDirectory VARCHAR(MAX)

DECLARE @BackupFiles TABLE
(
FileNamePath VARCHAR(MAX),
TransLogFlag BIT,
BackupFile VARCHAR(MAX),    
DatabaseName VARCHAR(MAX)
)

DECLARE FileCursor CURSOR LOCAL FORWARD_ONLY FOR
SELECT * FROM #DirTree WHERE FileFlag = 1

OPEN FileCursor
FETCH NEXT FROM FileCursor INTO 
@ID,
@BackupFile,
@Depth,
@FileFlag,
@ParentDirectoryID  

SET @wkSubParentDirectoryID = @ParentDirectoryID

WHILE @@FETCH_STATUS = 0
BEGIN
--loop to generate path in reverse, starting with backup file then prefixing subfolders in a loop
WHILE @wkSubParentDirectoryID IS NOT NULL
BEGIN
SELECT @wkSubDirectory = SubDirectory, @wkSubParentDirectoryID = ParentDirectoryID 
FROM #DirTree 
WHERE ID = @wkSubParentDirectoryID

SELECT @BackupFile = @wkSubDirectory + '\' + @BackupFile
END

SELECT @BackupFile = @BackupDirectory + @BackupFile

INSERT INTO @BackupFiles (FileNamePath) VALUES(@BackupFile)

FETCH NEXT FROM FileCursor INTO 
  @ID,
  @BackupFile,
  @Depth,
  @FileFlag,
  @ParentDirectoryID 

SET @wkSubParentDirectoryID = @ParentDirectoryID      
END

CLOSE FileCursor
DEALLOCATE FileCursor

SELECT @BackupFolder + '\' + SubDirectory from #DirTree
Declare @filecount int = (select count(*) from  #DirTree)


declare @sctript nvarchar(max)
select 
@sctript = 'RESTORE DATABASE rrrealty FROM ' +
STUFF( (SELECT +',' + results.MoveTo
                         from 
    (
    select 'DISK = N''' + 'FILELOCATION'  + SubDirectory + '''' as     MoveTo
    FROM #DirTree -- hear I mode files to another folder
    ) as results
                         FOR XML PATH('')),
                        1, 1, '') + ' WITH FILE = 1
  MOVE N''file'' TO N''file.mdf'', 
MOVE N''file_Log'' TO N''L:\filelog.ldf'', 
NOUNLOAD,  REPLACE,  STATS = 5'



Exec (@sctript)