省里要统一的收集下属各县的数据,要求各县把业务数据库进行备份,并通过专网传到省里的服务器上,因为业务软件是由公司做的(顺便说一句,是 SQL server2000 的数据库),所以这100多个数据数据合并工作,就是由公司代劳了,数据是收齐了,第一步肯定是要先把这100多个库恢得出来了,手工恢得几个后实在是不能接受,拷一个过来,右键一个“所有任务->恢复数据库->选择文件->再选择目标目录,又两三个“确定”,又等待一两分钟,出现恢复完成了,又来一下个,动作很简单, 就是有些繁琐,省里的一位同志突然又说“这次的数据可能不是最终的,这次是让你们先整理一下试试,过些天呢,会让他们再上报一次。。。。”,这是什么道理,甲方说什么就是什么吧。
干脆也别一个一个的点鼠标了,怪累的,两个人恢复一晚上也弄不完呀,就算弄完了,过些天又来新的数据,还得一晚上,不如写个脚本,把所有的库都放在同一个目录下,让机器一个一个的玩吧,好在省里让他们把备份库的文件名都统一了。
基本思路是:
1.先用 xp_cmdshell 把所有的文件名都写到一张表里;
2.用 RESTORE HEADERONLY 得到备份集的头部分
3.用 RESTORE FILELISTONLY 得备份集中数据文件及日志文件的 物理文件名和逻辑文件名
4.用 RESTORE DATABASE 把库一恢复,万了防止文件名重复,每个库会单独创建一个目录,当然也是 xp_cmdshell 啦。
5.在特定的里中记录一下,某个库完活了。。。
| drop procedure sp_batch_restore go |
| create procedure sp_batch_restore as declare @m_strSourcePath varchar(100) -- 所的备份集 存放源目录 , 及 备份集的扩展名 例如: 2011年XXXX省XXX县XXXX业务.bak (.bak) declare @m_strDestPath varchar(100) -- 还原的目标目录 declare @m_strFileName varchar(100) -- declare @m_strDBName varchar(100) , @m_strDBName_cn varchar(100) -- 恢复时的英文名 -- 中文名字 declare @m_strLogicalName varchar(100) , @m_strPhysicalName varchar(100) , @m_strPhysicalName_New varchar(100) -- 备份集中的 <逻辑文件名>和<物理文件名>, declare @m_strYear varchar(10) -- 年度 declare @m_dwCount int declare @m_strSQL varchar(766) -- 临时的SQL ,使用该变量,应该小心 begin set @m_strSourcePath = 'E:\*.msbak' -- 最近要加 \ set @m_strDestPath = 'E:\XXX\' -- 最后要加 \ set @m_strYear = '2011' set @m_dwCount = 0 create table #file(strFileName varchar(100) ) create table #header(BackupName nvarchar(128) , BackupDescription nvarchar(255) , BackupType smallint , ExpirationDate datetime , Compressed int , Position int , DeviceType int , 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) , DifferentialBaseLsn numeric(25,0) , BackupStartDate datetime , BackupFinishDate datetime , SortOrder smallint , CodePage smallint , UnicodeLocaleId int , UnicodeComparisionStyle int , CompatibilityLevel tinyint , SoftwareVendorId int , SoftwareVersionMajor int , SoftwareVersionMinor int , SoftwareVersionBuild int , MachineName nvarchar(128) , Flags int , BindingID uniqueidentifier, RecoveryForkID uniqueidentifier , Collation nvarchar(128) ) -- create table #logical(LogicalName varchar(255) , PhysicalName varchar(255) , Type varchar(100) , FileGroupName varchar(100) , Size numeric(25,0) , MaxSize numeric(25,0) ) insert into #file(strFileName) exec xp_cmdshell 'dir /b ' + @m_strSourcePath declare cur_file cursor for select strFileName from #file where strFileName is not null open cur_file fetch next from cur_file into @m_strFileName while @@fetch_status <> -1 begin -- 以下取得备份集中原数据库的名称 truncate table #header insert into #header execute ('RESTORE HEADERONLY FROM DISK = ''' + @m_strSourcePath + @m_strFileName + '''') select @m_strDBName = DatabaseName from #header -- 英文名称 从备份集中取出 select @m_strDBName_cn = replace( @m_strFileName ,@m_strExtend , '') -- 中文名字 直接取文件名称 -- 为每个数据库建立单独的目录 set @m_strSQL = 'MD ' + @m_strDestPath + @m_strDBName exec xp_cmdshell @m_strSQL -- 以下取得原数据库的文件信息(数据文件或日志文件的位置) truncate table #logical insert into #logical execute ('RESTORE FILELISTONLY FROM DISK = ''' + @m_strSourcePath + @m_strFileName + '''') set @m_strSQL = 'RESTORE DATABASE ' + @m_strDBName + ' FROM DISK= ''' + @m_strSourcePath + @m_strFileName + ''' WITH ' -- restore database from disk ='c:\aa.bak' declare cur_logical cursor for select LogicalName , PhysicalName from #logical open cur_logical fetch next from cur_logical into @m_strLogicalName , @m_strPhysicalName while @@fetch_status <> -1 begin set @m_strPhysicalName_New = right( @m_strPhysicalName , charindex('\',reverse(@m_strPhysicalName)) - 1 ) --取得文件名 set @m_strSQL = @m_strSQL + ' MOVE ''' + @m_strLogicalName + ''' TO ''' + @m_strDestPath + @m_strDBName + '\' + @m_strPhysicalName_New + ''' ,' -- MOVE 'data_data' move 'c:\xx.dat , ' fetch next from cur_logical into @m_strLogicalName , @m_strPhysicalName end -- end while close cur_logical deallocate cur_logical set @m_strSQL = left(@m_strSQL , len(@m_strSQL) -1 ) exec (@m_strSQL) -- print @m_strSQL insert into FBMaster..db_register(db_name , db_createdate , db_type , db_name_cn , db_kind , db_year) values(@m_strDBName , @m_strYear + '-01-01' , 0 , @m_strDBName_cn , 1 , @m_strYear) set @m_dwCount = @m_dwCount + 1 ; fetch next from cur_file into @m_strFileName end -- end while close cur_file deallocate cur_file print '共完成 ' + cast(@m_dwCount as varchar(10) ) + ' 个数据库的恢复 ' end -- end procedure go |
| sp_batch_restore go select * from FBMaster..db_register go |