创建从服务器上所有数据库的相同表中选择的视图,并且可以在任何时候将新数据库添加到服务器时进行处理
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)
我有一个系统可以接收 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)