【问题标题】:Union of multiple sp_MSforeachdb result sets多个 sp_MSforeachdb 结果集的联合
【发布时间】:2014-02-05 13:05:10
【问题描述】:

我可以在多个数据库中成功查询同一张表如下:

DECLARE @command varchar(1000)
SELECT @command = 'select * from table'
EXEC sp_MSforeachdb @command

但是,正如预期的那样,所有这些结果都会在不同的结果窗口中返回。合并所有这些结果的最简单方法是什么?

【问题讨论】:

  • SELECT list, of, columns FROM database.schema.object UNION ALL SELECT list, of, columns FROM database2...
  • 数据库名称因我在哪个服务器上运行而异,因此使用 sp_MSforeachdb。
  • SELECT name FROM sys.databases ;)
  • 创建一个临时表,然后修改@command插入到临时表中。

标签: sql sql-server tsql


【解决方案1】:

请停止使用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;

这会忽略系统数据库并且不会尝试访问当前不是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;

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

【讨论】:

    【解决方案2】:

    给这只猫换皮的另一种方法是使用动态 SQL:

    DECLARE @sql varchar(max);
    
    SELECT @sql = Coalesce(@sql + ' UNION ALL ', '') + 'SELECT list, of, columns FROM ' + QuoteName(name) + '.schema.table'
    FROM   sys.databases
    ;
    
    PRINT @sql
    --EXEC (@sql);
    

    【讨论】:

      【解决方案3】:

      有一些整理问题,不得不使用

      AND COLLATION_NAME = 'SQL_Latin1_General_CP1_CI_AS'
      

      【讨论】:

        猜你喜欢
        • 2017-04-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-05-06
        • 1970-01-01
        • 2021-04-11
        • 1970-01-01
        • 2012-09-01
        相关资源
        最近更新 更多