【问题标题】:Select same table name from all databases in SQL Server从 SQL Server 中的所有数据库中选择相同的表名
【发布时间】:2022-03-29 02:54:53
【问题描述】:

我有这个动态查询,即从我所有的数据库(以“Db”开头)同一个表(“Tbl_SameTable”)联合起来。

DECLARE @tableName nvarchar(256) = 'Tbl_SameTable'
DECLARE @sql nvarchar(max) = ''

SELECT @sql = @sql + CASE WHEN @sql <> '' THEN 'UNION ALL ' ELSE '' END 
                   + 'SELECT * FROM [' + dbs.name + ']..[' + @tableName + '] '
FROM sys.sysdatabases dbs
WHERE left(dbs.name,2) = 'Db'

EXEC(@sql)

我想在这个查询中添加两件事:

  1. 添加一列数据库名称
  2. 将查询结果分配给“临时表”或“表变量”

我不知道这是否重要,但是“Tbl_SameTable”是一个 5 列的表(int、nvarchar、int、nvarchar、nvarchar)

【问题讨论】:

  • 警告'[' + @tableName + ']' 不适合注射。使用QUOTENAME 正确引用您的对象。
  • 什么版本的 SQL Server?请注意,不能保证聚合字符串连接 (@sql = @sql + ) 有效;在 SQL 2017+ 中使用 STRING_AGG 或在早期版本中使用 FOR XML
  • 如果您在多个数据库中拥有相同的表,具有相同的定义,那么老实说,这表明您存在设计缺陷。如果您需要在单个数据集中处理这些数据,那么数据应该在单个数据库(和表)中。
  • Dan Guzman,我的 SQL Server 版本是 2017

标签: sql-server tsql


【解决方案1】:

这是未经测试的,但是,你会想要这样的东西。由于这是伪 SQL,您需要将 {Columns} 替换为实际名称(而不是 *)才能正常工作。对于CREATE TABLE,您还需要定义所述列的数据类型。

DECLARE @SchemaName sysname = N'dbo',
        @TableName sysname = N'YourTable';

CREATE TABLE #Temp (DatabaseName sysname,
                    {Columns});

DECLARE @SQL nvarchar(MAX),
        @CRLF nchar(2) = NCHAR(13) + NCHAR(10);

SET @SQL = STUFF((SELECT @CRLF + N'UNION ALL' + @CRLF +
                         N'SELECT N' + QUOTENAME(d.[name],'''') + N' AS DatabaseName, {Columns}' + @CRLF +
                         N'FROM ' + QUOTENAME(d.[name]) + N'.' + QUOTENAME(@SchemaName) + N'.' + QUOTENAME(@TableName)
                  FROM sys.databases d
                  WHERE d.[name] LIKE 'Db%'
                  ORDER BY database_id
                  FOR XML PATH(N''),TYPE).value('(./text())[1]','nvarchar(MAX)'),1,13, N'') + N';'

--PRINT @SQL; --Your Best Friend

INSERT INTO #Temp(DatabaseName, {Columns})
EXEC sys.sp_executesql @SQL;

当然,如果它不起作用,你最好的朋友会在那里帮助你。

【讨论】:

  • 你可以直接选择它而不插入到#Temp,你也可以从sys.columns获取列名
  • Charlieface,你能发布你的解决方案吗?
  • 你可以,@Charlieface,但 OP 声明“我想......将查询结果分配给“临时表”或“表变量”对于后者,这需要动态动态 SQL ; 我今天真的不想写这些。:)
【解决方案2】:

如何使用 sp_MSforeachdb 并将结果添加到另一个表?

DROP TABLE IF EXISTS #tmp
CREATE TABLE #tmp (col1 INT, col2 INT,...)

DECLARE @command varchar(1000) 
SELECT @command = 'IF ''?'' LIKE ''Db%'' BEGIN USE ? 
   EXEC(''INSERT INTO #tmp (col1, col2,...) SELECT col1, col2,... from Tbl_SameTable'') END' 
EXEC sp_MSforeachdb @command 

SELECT * FROM #tmp

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-10-23
    • 2011-12-13
    • 2012-09-23
    相关资源
    最近更新 更多