从多个服务器获取所有数据库名称

Get all database names from multiple servers

我们有多个 SQL 服务器,其中大部分是独立的。我需要创建一个存储过程/视图,将所有数据库名称插入到所有服务器的 table 中。

有没有办法通过存储过程或视图来做到这一点?我没有任何 powershell 或 .Net 经验。

这是我目前所拥有的。我只是不知道如何 'jump' 从一个服务器到另一个服务器并将我所有的结果添加到一个真正的 table.

CREATE TABLE ##temp 
(
DATABASE_NAME VARCHAR(100),
DATABASE_SIZE INT,
REMARKS VARCHAR(500)
)


INSERT into ##temp
EXEC [sp_databases] 

--doing this to also get ServerName along with the db name.  
--When I insert into a real table, I'll seperate it into two columns plus remove "@_!_@"
update ##temp
set DATABASE_NAME =   (select  @@SERVERNAME ) + '@_!_@ ' + DATABASE_NAME
where DATABASE_NAME not like '%@_!_@%' 

select DATABASE_NAME from ##temp

SQL Server Management Studio 允许您执行 query against multiple servers using the Registered Servers feature. This was added in SQL Server 2008 as this tutorial shows 所以您不必担心兼容性问题。

运行 多服务器查询很简单:

  1. View 菜单中,select `注册服务器。这将打开一个新的 window,类似于显示单个服务器对象的对象资源管理器。
  2. Local Server Groups 文件夹
  3. 中添加所有服务器的连接详细信息
  4. 右键单击“本地服务器组”文件​​夹,然后 select New Query。您在此处输入的查询将 运行 所有已注册的服务器。
  5. 查找所有数据库 运行 select * from sys.databases 或仅 sp_databases

SSMS 将从所有服务器收集结果并将它们显示在网格中。但是,如果您希望结果转到单个服务器的 table,则必须将目标服务器添加为所有其他服务器的链接服务器,并使用由四部分组成的名称来定位目标 table , 例如 INSERT INTO myManagementServer.MyDb.dbo.ThatTable...

SQL 服务器具有更强大的功能来管理多个服务器。您可以通过 Central Management Server 管理多台服务器,并通过策略将设置应用于多台服务器。该功能也是在 2008 年添加的。

在 SQL Server 2008 R2 中添加了 SQL Server Utility,它更进一步,从多个服务器收集诊断、指标、性能数据,并将其存储在管理仓库中以供报告。想象一下能够查看例如多个服务器的存储和查询性能,或者最近 X 个月的免费 space 趋势。

缺点是历史数据需要space。收集它还需要向所有受监控的服务器添加一些存储过程,尽管这是自动完成的。

对于这种事情,最好至少有一台服务器与您需要信息的所有服务器有链接连接。如果你这样做,那么你可以使用我刚刚写的这个小脚本:

-- (1) Create global temp table used to store results
IF OBJECT_ID('tempdb..##databases') IS NOT NULL DROP TABLE ##databases;
CREATE TABLE ##databases 
(
  serverDBID   int identity,
  serverName   varchar(100),
  databaseName varchar(100),
  databaseSize decimal(20,6)
);

-- (2) Create and populate table variable used to collect server names
DECLARE @servers TABLE(id int identity, serverName varchar(100));
INSERT @servers(serverName)
SELECT name FROM sys.servers;

-- (3) loop through each DB and collect database names into ##databases
DECLARE @i int = 1, @serverName varchar(100), @db varchar(100), @sql varchar(8000);
WHILE @i <= (SELECT COUNT(*) FROM @servers)
BEGIN
  SELECT @serverName = serverName FROM @servers WHERE id = @i;

  SET @sql = 'INSERT ##databases(serverName, databaseName) SELECT '''+@serverName+
             ''', name FROM master.sys.databases';
  EXEC (@sql);

  SET @i += 1;
END;

-- (4) Collect database sizes
SET @i = 1; -- reset/re-use @i;
WHILE @i <= (SELECT COUNT(*) FROM ##databases)
BEGIN
  SELECT @serverName = serverName, @db = databaseName
  FROM ##databases
  WHERE serverDBID = @i;

  SET @sql = 
  'UPDATE ##databases
   SET databaseSize = 
   (SELECT sum(size)/128. FROM ['+@serverName+'].['+@db+'].sys.database_files)
   WHERE serverDBID = '+CAST(@i AS varchar(4))+';'

  BEGIN TRY 
    EXEC (@sql);
  END TRY
  BEGIN CATCH
    PRINT 'There was an error getting dbsize info for '+@serverName+' > '+@db;
  END CATCH;

  SET @i += 1;
END;

-- Final Output
SELECT * FROM ##databases;