2017-04-06 103 views
-1

下面的脚本的目的是从每台服务器收集数据库大小和数据库数量的总和,然后总计总和。动态SQL中的UNION - TSQL

DECLARE @LinkedServer VARCHAR(100) 
DECLARE @SQL1   NVARCHAR(MAX) 
DECLARE @SQL2   NVARCHAR(MAX) 
DECLARE @TotalDB  NVARCHAR(1000) 
DECLARE @TotalSize  NVARCHAR(1000) 
DECLARE @LineSpace  VARCHAR(100) 
DECLARE @Union1   VARCHAR(200) 
DECLARE @Union2   VARCHAR(200) 

SELECT @LinkedServer = MIN(name) 
    FROM ServerwithLinkedServers.master.sys.servers 
    WHERE name IN ('ServerName1', 
        'ServerName2', 
        'ServerName3') 

WHILE @LinkedServer IS NOT NULL 

    BEGIN 
     SET @TotalDB = 'SELECT COUNT(*) AS [Total Retailer Databases] FROM '+ @LinkedServer +'.master.sys.databases'; 
     SET @Union1 = @TotalDB + ' UNION ' + @TotalDB; 
     SET @TotalSize = 'SELECT CAST(SUM(size) * 8.00/1024.00/1024.00 AS DECIMAL(9,2)) AS [Total Size GB] FROM '+ @LinkedServer +'.master.sys.master_files'; 
     SET @Union2 = @TotalSize + ' UNION ' + @TotalSize; 

     EXEC (@Union1); 
     EXEC (@Union2); 

     SELECT @LinkedServer = MIN(name) 
      FROM ServerwithLinkedServers.master.sys.servers 
      WHERE name IN ('ServerName1', 
          'ServerName2', 
          'ServerName3') 
       AND name > @LinkedServer 
    END 

    print @union1 
    print @union2 

然而,当我执行我得到一个错误,说明代码:

Unclosed quotation mark after the character string 'T'. 
Incorrect syntax near 'T'. 

我缺少什么?或者我做错了什么?

+2

打印您的语句而不是执行 - 并检查它。错误信息清楚地表明 - 您在某处错过了引号。 –

+2

你为什么在这里循环?从远程系统提取数据有什么意义?无论如何,您已经硬编码了这些值,所以在阅读服务器列表时除了其中一个已经从远程服务器上删除以外,没有任何意义。然后你从每个服务器获得两次数据库的数量。这整个事情可以重写没有循环很容易,但我不明白它想要做什么。 –

+0

我需要硬编码的ServerNames,因为一些链接的服务器不再工作了(某些服务器已经退役)。该脚本假设检索每台服务器的数据库数量,同时获取大小。和所有联合在一起的总和。我将如何重写这个脚本而不使用循环? – AznDevil92

回答

1

下面介绍如何在不使用循环的情况下利用动态sql来处理这类事情。我还将您的查询重新编写为每个数据库的单个查询。这将返回每台服务器上的数据库数量以及这些文件使用的总空间量。我建议调整这一点,以排除像master,tempdb,模型等某些数据库...

这将仍然会返回整个列表,但不需要循环。一旦你熟悉它生成的动态sql,你可以注释掉该行并取消注释exec行。

DECLARE @SQL NVARCHAR(MAX) = '' 

SELECT @SQL = @SQL + 'select count(distinct d.database_id) as TotalRetailerDatabases 
    , CAST(SUM(size) * 8.00/1024.00/1024.00 AS DECIMAL(9,2)) TotalSizeGB 
from ' + name + '.sys.master_files mf 
join ' + name + '.master.sys.databases d on d.database_id = mf.database_id UNION ALL ' 
FROM ServerwithLinkedServers.master.sys.servers 
WHERE name IN 
(
    'ServerName1' 
    , 'ServerName2' 
    , 'ServerName3' 
) 

set @SQL = left(@SQL, len(@SQL) - 10) --remove the last UNION ALL 

select @SQL 
--exec sp_executesql @SQL1 
+0

删除最后一个UNION ALL是什么意思? – AznDevil92

+0

查看未删除最后10个字符而创建的字符串,它将有一个尾随UNION ALL。 :)很高兴这为你工作。 –

0

由于我在查询中没有看到T,所以我必须假设你有一个带有T的ServerName,后跟一个空格。

尝试在您的查询中使用QUOTENAME(@LinkedServer)无处不在@LinkedServer