多个sp_MSforeachdb结果集的并集

Dan*_*Dan 1 sql t-sql sql-server

我可以成功查询多个数据库中的同一表,如下所示:

DECLARE @command varchar(1000)
SELECT @command = 'select * from table'
EXEC sp_MSforeachdb @command
Run Code Online (Sandbox Code Playgroud)

但是,所有这些结果都按预期方式在不同的结果窗口中返回。对所有这些结果进行合并的最简单方法是什么?

Aar*_*and 5

请停止使用sp_MSforeachdb。为了任何东西。说真的 它是无证的,不受支持的,而且非常破损:

如果您知道所有数据库都具有相同的表(并且它们都具有相同的结构!),则可以执行以下操作:

DECLARE @sql NVARCHAR(MAX);

SET @sql = N'';

SELECT @sql = @sql + N'UNION ALL SELECT col1,col2 /*, etc. */
  FROM ' + QUOTENAME(name) + '.dbo.tablename'
FROM sys.databases WHERE database_id > 4 AND state = 0;

SET @sql = STUFF(@sql, 1, 10, '');

EXEC sp_executesql @sql;
Run Code Online (Sandbox Code Playgroud)

这将忽略系统数据库,并且不会尝试访问当前不存在的任何数据库ONLINE

现在,您可能需要进一步过滤,例如,不包括没有名为的表的任何数据库tablename。在这种情况下,您将需要嵌套动态SQL,例如:

DECLARE @sql NVARCHAR(MAX);

SET @sql = N'DECLARE @cmd NVARCHAR(MAX);

SET @cmd = N'''';';

SELECT @sql = @sql + N'

SELECT @cmd = @cmd + N''UNION ALL
SELECT col1,col2 /*, etc. */ FROM ' 
  + QUOTENAME(name) + '.dbo.tablename ''
WHERE EXISTS (SELECT 1 FROM ' + QUOTENAME(name) 
 + '.sys.tables AS t
 INNER JOIN ' + QUOTENAME(name) + '.sys.schemas AS s
 ON t.[schema_id] = s.[schema_id]
 WHERE t.name = N''tablename''
 AND s.name = N''dbo'');'
FROM sys.databases WHERE database_id > 4 AND state = 0;

SET @sql = @sql + N';

SET @cmd = STUFF(@cmd, 1, 10, '''');

PRINT @cmd;
--EXEC sp_executesql @cmd;';

PRINT @sql;
EXEC sp_executesql @sql;
Run Code Online (Sandbox Code Playgroud)

这不能验证列结构是否兼容,但是您会很快发现这一点。