2017-04-06 6 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

なぜあなたはここでループしていますか?そして、リモートシステムからデータを引き出すポイントは何ですか?とにかく値をハードコーディングしているので、サーバーのリストを読むのは本当に意味がありません(そのうちの1つがリモートサーバーから削除されていない限り)。そして、各サーバーからデータベースの数を2回取得しています。このすべてのことは非常に簡単にループすることなく書き直すことができましたが、何をしようとしているのか分かりません。 –

+0

リンクされたサーバーの一部がもう動作しないため(一部のサーバーは廃止されているため)、ハードコードされたServerNamesを用意する必要があります。スクリプトは、サーバごとにデータベースの数を取得し、同時にサイズを取得すると仮定しています。そして、UNIONを一括して合計します。ループを使用せずにこのスクリプトを書き直すにはどうすればよいですか? – AznDevil92

答えて

1

ここでは、ループを使用せずにダイナミックSQLをこのようなものに利用する方法を示します。また、データベースごとに1つのクエリとしてクエリを書き直しました。これにより、各サーバー上のデータベースの数とファイルが使用する合計容量が返されます。 master、tempdb、modelなどの特定のデータベースを除外するためにこれを少し修正することをお勧めします。

これはリスト全体を返しますが、ループは必要ありません。生成した動的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が表示されないので、ServerNameにTとスペースがあると仮定する必要があります。

@LinkedServerがあるクエリのどこにでもQUOTENAME(@LinkedServer)を使用してみてください。