• 批量附加数据库


    背景

    最近我们在替换生产环境的数据库服务器的时候,因该实例下库比较多,差不多有近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 FilesMicrosoft SQL ServerMSSQL13.MSSQLSERVERMSSQLDATA',  --数据库文件存放路径,如有多个路径类似。
     23     1,
     24     1;
     25 --SELECT *
     26 --FROM #DirectoryTree;
     27 ---生成附加代码
     28 DECLARE @file VARCHAR(MAX);
     29 SET @file
     30     = 'D:Program FilesMicrosoft SQL ServerMSSQL13.MSSQLSERVERMSSQLDATA'; ---具体数据文件存放的路径
     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折腾一下。
  • 相关阅读:
    用call/apply实现bind
    FED1 修改 this 指向(中等)
    46. 全排列(中等)
    JavaScript 用七种方式教你判断一个变量是否为数组类型(转)
    179. 最大数(中等)
    125. 验证回文串(简单)
    执行git pull命令时出错
    前端修改滚动条样式
    js实现每日定时任务
    Vue实现验证码控件
  • 原文地址:https://www.cnblogs.com/jil-wen/p/7226249.html
Copyright © 2020-2023  润新知