批量附加数据库

背景

最近我们在替换生产环境的数据库服务器的时候,因该实例下库比较多,差不多有近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折腾一下。
posted @ 2017-07-31 08:58  jil.wen  阅读(2382)  评论(0编辑  收藏  举报