# SQLSERVER批量备份和恢复数据库
一个代账的客户有800多个客户,在一个数据库实例中有800多个数据库,需要进行批量迁移
- 开启在SQL中执行shell命令配置
USE master
GO
RECONFIGURE --先执行一次刷新,处理上次的配置
GO
EXEC sp_configure 'show advanced options',1 --启用xp_cmdshell的高级配置
GO
RECONFIGURE --刷新配置
GO
EXEC sp_configure 'xp_cmdshell',1 --打开xp_cmdshell,可以调用SQL系统之外的命令
GO
RECONFIGURE
GO
- 备份
DECLARE
@FileName VARCHAR(200),
@CurrentTime VARCHAR(50),
@DBName VARCHAR(100),
@BAKSQL VARCHAR(1000)
SET @CurrentTime = CONVERT(CHAR(8),GETDATE(),112) + CAST(DATEPART(hh, GETDATE()) AS VARCHAR) + CAST(DATEPART(mi, GETDATE()) AS VARCHAR)
DECLARE CurDBName CURSOR FOR
SELECT NAME FROM Master..SysDatabases where dbid>4
OPEN CurDBName
FETCH NEXT FROM CurDBName INTO @DBName
WHILE @@FETCH_STATUS = 0
BEGIN
--Execute Backup
SET @FileName = 'E:\BAK\' + @DBName + '_' + @CurrentTime
SET @BAKSQL = 'BACKUP DATABASE ['+ @DBName +'] TO DISK = ''' + @FileName + '.bak' +
''' WITH NOINIT, NOUNLOAD, NAME = N''' + @DBName + '_backup'', NOSKIP, STATS = 10, NOFORMAT'
EXEC(@BAKSQL)
--Get Next DataBase
FETCH NEXT FROM CurDBName INTO @DBName
END
CLOSE CurDBName
DEALLOCATE CurDBName
- 恢复
declare
@backpath varchar(2000),
@execsql varchar(2000),
@datapath varchar(2000),
@lgname varchar(64),
@lgtype varchar(12),
@lgfilename varchar(64),
@i int
begin
set @backpath='E:\BAK\';
set @execsql='dir /b '+ @backpath +'\*.BAK';
set @datapath='E:\DATA';
begin
if not exists (select * from sysobjects where name='backfiles')
create table backfiles(name varchar(2000));
end
truncate table backfiles
insert into backfiles exec xp_cmdshell @execsql
DELETE backfiles WHERE upper(right(name,3))<>'BAK' OR NAME IS NULL
declare @fileName varchar(100),
@dbName varchar(100)
declare file_cur cursor for select name from backfiles;
open file_cur
fetch next from file_cur into @fileName
while @@fetch_status=0
begin
select @dbName=substring(@fileName,1,charindex('.bak',@filename)-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,
[IsReadOnly] BIT,
[IsPresent] BIT,
[TDEThumbprint] VARBINARY(32) -- remove this column if using SQL 2005
)
INSERT INTO @fileListTable EXEC('RESTORE FILELISTONLY FROM DISK = '''+@backpath+@fileName+'''')
set @execsql = '';
set @execsql ='restore database '+'"'+@dbName+'"' + ' from disk='+CHAR(39)+@backpath+@fileName+CHAR(39) +' with ' ;
-----------------
set @i = 1
declare bak_cur cursor for select
[LogicalName]
,reverse(substring(reverse([PhysicalName]),0,charindex('\',reverse([PhysicalName])))) as filen_ame
,[Type]
from @fileListTable
open bak_cur
fetch next from bak_cur into @lgname,@lgfilename,@lgtype
while @@FETCH_STATUS = 0
begin
/*
不考虑文件重名的情况,统一恢复到同一目录下
*/
set @execsql = @execsql + (case when @i = 1 then ' ' else ', ' end) + ' move '+CHAR(39)+@lgname+CHAR(39)+' to '+CHAR(39)+@datapath+'\'+ @lgfilename +CHAR(39)
set @i = @i + 1
fetch next from bak_cur into @lgname,@lgfilename,@lgtype
end
close bak_cur
deallocate bak_cur
----------------------------
print @execsql
exec (@execsql)
delete from @fileListTable
fetch next from file_cur into @fileName
end
close file_cur
deallocate file_cur
end