批量附加数据库
背景
最近我们在替换生产环境的数据库服务器的时候,因该实例下库比较多,差不多有近200个库,加上维护窗口的时间有限,所以我们有必要写段脚本快速批量附加所有的库,并确保所有的库都附加成功。当前的情况是所有的库名都是唯一且不存在库名相似的情形,如 db_1 和 db_12 不存在这种库名相似的情况。
环境
Microsoft SQL Server 2012 (SP3-CU2) (KB3137746) - 11.0.6523.0 (X64)
Mar 2 2016 21:29:16
Copyright (c) Microsoft Corporation
Web Edition (64-bit) on Windows NT 6.3 <X64> (Build 9600: ) (Hypervisor)
过程
第一步 在旧生产环境上执行,获取所有正式在用的库名信息
为了确保需附加的库名,以及为后续附加成功之后检验核对是否存在数据库文件缺少或未成功附加。提前在旧的生产运行如下代码,并且成功导出结构和数据,再拷贝导出的文件至新的服务器上执行。
1 ---读取源数据库信息 先用从源数据库读取数据库信息 2 use master 3 IF OBJECT_ID('sourcetable') IS NOT NULL 4 DROP TABLE sourcetable; 5 SELECT name, 6 database_id, 7 0 AS okflag 8 INTO sourcetable 9 FROM sys.databases 10 WHERE database_id > 4 11 ORDER BY name;
将导出至桌面的wen.sql文件拷至新的服务器上,并在ssms中成功执行。
第二步 生成批量附加代码并执行
默认场景是数据库文件已全部拷贝至新的生产环境,也不存在权限限制访问之类的问题。在新的生产环境执行如下代码
1 /******** 2 Just for a quick review, xp_dirtree has three parameters: 3 1 directory - This is the directory you pass when you call the stored procedure; for example 'D:\Backup'. 4 2 depth - This tells the stored procedure how many subfolder levels to display. The default of 0 will display all subfolders. 5 3 isfile - This will either display files as well as each folder. The default of 0 will not display any files. 6 *********/ 7 ---读取数据库文件 8 IF OBJECT_ID('tempdb..#DirectoryTree') IS NOT NULL 9 DROP TABLE #DirectoryTree; 10 CREATE TABLE #DirectoryTree 11 ( 12 id INT IDENTITY(1, 1), 13 subdirectory NVARCHAR(512), 14 depth INT, 15 isfile BIT 16 ); 17 INSERT #DirectoryTree 18 ( subdirectory, 19 depth, 20 isfile 21 ) 22 EXEC master..xp_dirtree 'D:\Program Files\Microsoft SQL Server\MSSQL13.MSSQLSERVER\MSSQL\DATA', --数据库文件存放路径,如有多个路径类似。 23 1, 24 1; 25 --SELECT * 26 --FROM #DirectoryTree; 27 ---生成附加代码 28 DECLARE @file VARCHAR(MAX); 29 SET @file 30 = 'D:\Program Files\Microsoft SQL Server\MSSQL13.MSSQLSERVER\MSSQL\DATA\'; ---具体数据文件存放的路径 31 DECLARE @name VARCHAR(500), --数据库名 32 @database_id INT, --数据库ID 33 @temp VARCHAR(MAX); --存放附加代码 34 SET @temp = ''; 35 DECLARE c_wen CURSOR FAST_FORWARD 36 FOR 37 SELECT name, 38 database_id 39 FROM sourcetable 40 ORDER BY name; 41 OPEN c_wen; 42 FETCH NEXT FROM c_wen 43 INTO @name, 44 @database_id; 45 WHILE @@FETCH_STATUS = 0 46 BEGIN 47 DECLARE @id INT, --存放附加文件个数值 48 @temp_id INT, --存放最大附加文件个数值 49 @subdirectory VARCHAR(MAX), --待附加的文件名 50 @t VARCHAR(MAX); --存放单个库附加的代码 51 SET @t = ''; 52 SELECT @id = COUNT(1) 53 FROM #DirectoryTree 54 WHERE subdirectory LIKE '%' + @name + '%'; 55 SELECT @temp_id = COUNT(1) 56 FROM #DirectoryTree 57 WHERE subdirectory LIKE '%' + @name + '%'; 58 SELECT ROW_NUMBER() OVER (ORDER BY subdirectory) id, 59 subdirectory 60 FROM #DirectoryTree 61 WHERE subdirectory LIKE '%' + @name + '%'; 62 WHILE (@id) >= 1 --存在多个需附加的文件 63 BEGIN 64 SELECT @subdirectory = subdirectory 65 FROM 66 ( 67 SELECT ROW_NUMBER() OVER (ORDER BY subdirectory) id, 68 subdirectory 69 FROM #DirectoryTree 70 WHERE subdirectory LIKE '%' + @name + '%' 71 ) a 72 WHERE a.id = @id; 73 SELECT @t 74 = @t + '''' + @file + @subdirectory + '''' 75 + CASE 76 WHEN @id > 1 THEN 77 ',' 78 ELSE 79 '; ' + CHAR(10) + CHAR(13) + 'GO' 80 END + CHAR(10) + CHAR(13); 81 SET @id = @id - 1; 82 END; 83 IF ( 84 @temp_id = 0 --只有库名,不存在附加文件 85 ) 86 BEGIN 87 SELECT @t = ''; 88 END; 89 ELSE 90 BEGIN 91 SELECT @t 92 = 'EXEC sys.sp_attach_db ' + '''' + @name + '''' + ',' + CHAR(10) 93 + CHAR(13) + @t; 94 END; 95 FETCH NEXT FROM c_wen 96 INTO @name, 97 @database_id; 98 SELECT @temp = @temp + @t; 99 END; 100 SELECT @temp 101 FOR XML PATH(''); 102 CLOSE c_wen; 103 DEALLOCATE c_wen;
复制xml文件中批量附加代码在新窗口执行。
第三步 验证在新的生产环境执行
附加完毕需验证是否存在失败或遗漏的情况;
1 use master 2 --计算原来生产环境的库合计 3 select count(1) from [dbo].[sourcetable] 4 ---缺失或失败的库名 5 select 6 a.name 7 from [sourcetable] a left join 8 sys.databases b 9 on a.name=b.name 10 where b.name is null
参考
后记
有兴趣的同学可以考虑使用PowerShell,如foreach折腾一下。