创建从服务器上所有数据库的相同表中选择的视图,并且可以在任何时候将新数据库添加到服务器时进行处理

Create view that selects from identical tables from all databases on the server and can handle any time a new database is added to the server

我有一个系统可以接收 Revit 模型并将模型中的所有数据加载到 2016 SQL 服务器。不幸的是,系统的工作方式为加载的每个模型创建了一个新数据库。所有数据库都以相同的架构开头,因为系统使用模板数据库来构建任何新数据库。

我需要构建一个视图,该视图可以从服务器上的所有数据库中查询数据,但可以在创建新数据库时自动添加它们。 table 名称和关联的列在所有数据库中都是相同的,包括数据类型。

有没有办法使用以下方法提取当前数据库名称的列表:

SELECT [name] FROM sys.databases

然后使用结果 UNION 来自基本 SELECT 查询的结果,如下所示:

SELECT 
    [col1]
    ,[col2]
    ,[col3]
FROM [database].[dbo].[table]

如何用 sys.databases 查询的结果替换 [database] 部分?

目标是让结果看起来像我这样做的:

SELECT 
    [col1]
    ,[col2]
    ,[col3]   
FROM [database1].[dbo].[table]
UNION
SELECT 
    [col1]
    ,[col2]
    ,[col3]    
FROM [database2].[dbo].[table]

但对服务器上的所有数据库都是动态的,以后无需我进行管理。

在此先感谢您的协助!

*** 添加信息:已提出一些使用 STRING_AGG 的建议,但该功能在 2016 年不可用。

试试这个。它将自动检测并包含具有指定 table 名称的新数据库。如果数据库被删除,它会自动排除它。

我更新了 TSQL。 STRING_AGG 将字符串与每个数据库连接起来。没有它它只有 returns 最后一个数据库。 STRING_AGG 比 += 更安全,后者也是串联的。我更改了代码,以便它生成并执行查询。在 SQL 2019 年,查询全部使用 += 在一行中进行。我没有 SQL 2016。它可能会在 SQL 2016 中更好地格式化它。您可以取消注释 --SELECT @SQL3 以查看查询的外观。如果这是您需要的,请标记为答案。

DECLARE @TblName TABLE
(
  TblName VARCHAR(100)
)

Declare @SQL VARCHAR(MAX),
@SQL3 VARCHAR(MAX),
@DBName VARCHAR(50),
@Count Int, 
@LoopCount Int 
Declare @SQL2 VARCHAR(MAX) = ''

Select Identity(int,1,1) ID, name AS DBName  into #Temp from sys.databases 
Select @Count = @@RowCount 
Set @LoopCount = 1 

While @LoopCount <= @Count 
Begin 
    SET @DBName = (SELECT DBName FROM #Temp Where ID = @LoopCount)
    SET @SQL =
    ' USE ' + @DBName + 
    ' SELECT TABLE_CATALOG FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = ''table'''

    INSERT INTO @TblName (TblName)
    EXEC (@SQL)

    Set @LoopCount=@LoopCount + 1 
End 

SELECT @SQL2 +=
' SELECT ' + char(10) + 
'    [col1] ' + char(10) + 
'    ,[col2] ' + char(10) + 
'    ,[col3] ' + char(10) + 
' FROM [' + TblName + '].[dbo].[table] ' + char(10) + 
' UNION '
FROM @TblName

DROP TABLE #Temp

SET @SQL3 = (SELECT SUBSTRING(@SQL2, 1, LEN(@SQL2) - 5))
--SELECT @SQL3
EXEC (@SQL3)