【问题标题】:Query across multiple databases on same server跨同一服务器上的多个数据库查询
【发布时间】:2014-01-03 20:48:09
【问题描述】:

我正在寻找一种处理以下情况的方法:

  1. 我们有一个数据库服务器,上面有多个数据库(都具有相同的架构,不同的数据)。

  2. 我们正在寻找一种在所有数据库中进行查询的方法(并使其易于配置,因为可以随时添加更多数据库)。这种数据访问必须是实时的。

例如,您有一个插入订单的应用程序 - 每个应用程序都有自己的数据库等。然后我们正在寻找一种有效的方法,让单个应用程序可以访问所有其他数据库中的订单信息为了查询它并随后对其进行操作。

到目前为止,我的搜索并没有透露太多信息,但是我想我可能只是缺少适当的关键字才能找到正确的信息...

【问题讨论】:

  • 你可能想看看 Service Broker
  • 您想使用什么语言?使用 PHP,您可以独立连接到每个数据库
  • @ManoloSalsas - 我希望运行一个查询来从每个数据库中获取数据。寻找最干净的方式来做到这一点。单独访问每个数据库是行不通的。
  • @Sergio - 服务代理似乎是关于异步消息队列的,不知道这有什么关系?
  • 所有数据库中的表是否同名?

标签: sql sql-server


【解决方案1】:

您必须在任何数据库对象之前指定数据库名称。

单一数据库:

SELECT * FROM [dbo].[myTable]

多个数据库:

SELECT * FROM [DB01].[dbo].[myTable]
UNION ALL
SELECT * FROM [DB02].[dbo].[myTable]
UNION ALL
SELECT * FROM [DB03].[dbo].[myTable]

【讨论】:

  • 感谢您的回答,我知道三部分语法以及如何跨单个数据库进行查询,我只是希望有一种比这样的多个联合更优雅的方式。
  • 没有通用的内置方式,如何在多个数据库上执行一个脚本。您可以拥有一个存储过程,该过程将在一个大型 SQL 选择中动态连接字符串,然后使用 sp_sqlexec 执行 i。
【解决方案2】:

这不会是有史以来最干净的解决方案,但您可以在“主数据库”(如果您的各个数据库不会保持不变)上定义一个视图,其中包含来自各个数据库的数据,并允许您对单一来源执行查询。

例如...

CREATE VIEW vCombinedRecords AS
SELECT * FROM DB1.dbo.MyTable
UNION ALL
SELECT * FROM DB2.dbo.MyTable

这可以让你做...

SELECT * FROM vCombinedRecords WHERE....

当您的数据库发生变化时,您只需更新视图定义以包含新表。

【讨论】:

  • 请记住这一点,但这有点让人头疼(添加新数据库),而且我也会开始担心性能问题(可能在这里谈论数百个联合)。
  • 我不相信你会找到一个高性能、易于维护的解决方案来搜索多个数据库。索引用于任何高性能,并且这些只存在于数据库级别。
  • 我无法在同一台服务器上有 2 个数据库的 Azure SQL 服务器上使用它。此版本的 SQL Server 不支持引用“MyDatabaseNameHere”中的数据库和/或服务器名称。
【解决方案3】:

您可以动态构建联合:

select name from sys.databases

然后检查数据库是否有表:

select name from [dbname_from_above].sys.tables where name = 'YourTable'

这为您提供了工会的所有数据库。您可以构建查询客户端或动态 SQL。

【讨论】:

  • 有趣的方法,但我仍然对可扩展性有些担忧。
  • 表 sys.databases 在 MySQL 上不存在
  • @MUYBelgium 没错,这个问题是关于SQL Server,而不是MySQL
【解决方案4】:

注意 - 我在下面的回答收到了几票反对票,但只有一条评论给出了它可能被反对的任何理由。评论是这个答案与接受的答案非常相似,但性能更差。我不同意这种观点,并在此处复制我的回答 - 在实际答案中 - 以便其他阅读我的答案的人可能有更好的机会了解为什么这与接受的答案完全不同,实际上更好地解决了原始问题。

我对这个建议的回应类似于接受的答案:

相反 - 原始问题指出定期添加新数据库。每次添加新数据库时,公认的解决方案都需要维护。无论是否添加了任何新数据库,此处的解决方案都将起作用(与原始问题一致,即它们都具有相同的架构)。此外,接受的答案要求您为每个查询的数据库复制一次查询。如果查询很复杂,那会很快变得丑陋。此处的提议确保了查询中使用的逻辑的单一事实来源。

还有答案本身:

在这里从臀部射击。

use master;
go

create table #Temp (sourceDBName varchar(128), colA varchar(128), colB varchar(128));

exec sp_MSforeachDB ' USE [?];

insert into #Temp
SELECT DISTINCT
 ''?'',
tableA.colA,
tableB.colB
FROM tableA JOIN tableB on some_conditions
WHERE someCol LIKE ''%some_term%''
'

select sourceDBName, colA, colB from #Temp order by 1, 2, 3;

drop table #Temp;

此逻辑应允许您将单个查询应用于所有数据库。但是,要使用它,您将需要添加逻辑以过滤掉系统数据库,或者仅显式包含您指定的数据库。为此,您可能希望将此逻辑放入存储过程中,然后返回结果集,因此最后,您对该逻辑的调用是一个 select 语句,该语句返回您可以加入、过滤等的行集。

【讨论】:

  • 这似乎是一种非常相似的方法,如果性能稍差一点,就像在所选答案中一样(在主视图中定义的视图)。
  • @Paddy,相反-原始问题指出定期添加新数据库。每次添加新数据库时,公认的解决方案都需要维护。无论是否添加了任何新数据库,此处的解决方案都将起作用(与原始问题一致,即它们都具有相同的架构)。此外,接受的答案要求您为每个查询的数据库复制一次查询。如果查询很复杂,那会很快变得丑陋。此处的提议确保了查询中使用的逻辑的单一事实来源。
【解决方案5】:

查看https://www.mssqltips.com/sqlservertip/2855/sql-server-multi-database-query-with-registered-servers/

SELECT * FROM (
SELECT 
    @@SERVERNAME as [ServerName],
    @@version [Version],
    Format(@@CONNECTIONS,'N0') [Conections],
    Format(@@CPU_BUSY ,'N0')[CPUBusy]
) SQLInfo
LEFT JOIN (
    SELECT 
        @@SERVERNAME AS [ServerName],
        SERVERPROPERTY('ProductVersion') [Version Build],
        SERVERPROPERTY ('Edition') AS [Edition],
        SERVERPROPERTY('ProductLevel') AS [Service Pack],
        CASE SERVERPROPERTY('IsIntegratedSecurityOnly') 
         WHEN 0 THEN 'SQL Server and Windows Authentication mode'
         WHEN 1 THEN 'Windows Authentication mode'
        END AS [Server Authentication],
        CASE SERVERPROPERTY('IsClustered') 
         WHEN 0 THEN 'False'
         WHEN 1 THEN 'True'
        END AS [Is Clustered?],
        SERVERPROPERTY('ComputerNamePhysicalNetBIOS') AS [Current Node Name],
        SERVERPROPERTY('Collation') AS [ SQL Collation],
        [cpu_count] AS [CPUs],
        [physical_memory_kb]*0.00000095367432 AS [RAM (GB)]
    FROM [sys].[dm_os_sys_info]
) SQLInfo2 on SQLInfo.[ServerName]=SQLInfo2.[ServerName]
LEFT JOIN (
    SELECT 
        @@SERVERNAME as [ServerName],
        NodeName,
        Status_Description,
        is_Current_Owner
    FROM [MASTER].[sys].[fn_virtualservernodes]()
)Clusterinfo on SQLInfo.[ServerName]=Clusterinfo.[ServerName]

【讨论】:

    猜你喜欢
    • 2020-05-23
    • 2011-03-14
    • 1970-01-01
    • 2016-02-24
    • 1970-01-01
    • 2017-11-18
    • 1970-01-01
    • 2013-02-15
    • 1970-01-01
    相关资源
    最近更新 更多