【问题标题】:SQL - Select from Multiple databasesSQL - 从多个数据库中选择
【发布时间】:2021-07-13 16:32:52
【问题描述】:

我有 10 个数据库,它们都在同一个实例和架构中,具有相同的表。

希望创建一个SELECT 查询,该查询可以使用数据库名称的变量并将所有记录返回到单个数据集中。

我一直在环顾四周并将以下内容放在一起作为测试(真正的 select 语句要大得多,有多个连接)

这个测试确实有效,但它返回两个结果集,每个数据库一个。

有没有办法将结果合并到一个集合中,还是我使用了错误的方法?

提前致谢

DECLARE @DB_NAME VARCHAR(6);

DECLARE CURSOR_ALLDB_NAMES CURSOR FOR 
    SELECT name
    FROM sys.databases
    WHERE name IN ('CN2DAT', 'AU1DAT') 

OPEN CURSOR_ALLDB_NAMES

FETCH NEXT FROM CURSOR_ALLDB_NAMES INTO @DB_NAME

WHILE @@Fetch_Status = 0
BEGIN
    EXEC ('SELECT * FROM ' + @DB_NAME + '.dbo.ICITEM')

    -- EXEC ('USE '+ @DB_NAME + ' SELECT * from dbo.ICITEM')

    FETCH NEXT FROM CURSOR_ALLDB_NAMES INTO @DB_NAME
END

CLOSE CURSOR_ALLDB_NAMES
DEALLOCATE CURSOR_ALLDB_NAMES

【问题讨论】:

标签: sql sql-server multiple-databases


【解决方案1】:

我会创建一个结合了选择语句的视图。例如

CREATE VIEW v_ICITEM
AS
SELECT * FROM CN2DAT.dbo.ICITEM
UNION ALL 
SELECT * FROM AU1DAT.dbo.ICITEM
go;

您也可以将源数据库作为一列包含:

CREATE VIEW v_ICITEM
AS
SELECT 'CN2DAT' AS Db, * FROM CN2DAT.dbo.ICITEM
UNION ALL 
SELECT 'AU1DAT', * FROM AU1DAT.dbo.ICITEM
go;

【讨论】:

  • 我刚刚在实际查询中尝试了使用 UNION ALL 的视图方法。它提供了预期的结果,但非常大,维护起来将是一场噩梦,尤其是在包含所有 10 个数据库时
  • @ColinA 不幸的是,您的情况很糟糕,因此不会有一个好的、易于维护的 T-SQL 解决方案。一般来说,应该避免跨数据库查询,如果你问我,你的问题更多的是设计问题。此解决方案是最简单的 T-SQL 解决方案。否则,您将获得动态 SQL 解决方案(如 OP),这是一个更糟糕的解决方案。 IMO 如果您需要查询多个数据库,那么这项工作应该在单独的应用程序中完成,而不是在单个 T-SQL 脚本中。
  • 您可以做的是创建生成视图的脚本。如果添加新数据库 - 重新生成视图。真正的问题是为什么需要这样做?
  • 大家好,感谢您的 cmets。我同意缺乏整体设计。该脚本的目的是为我们的各种实体收集销售数据以用于报告目的,理想情况下,我们将在单独的合并公司数据库中拥有这些数据。不幸的是,目前还不能进行适当的合并。回到绘图板。
  • 将 Zeph 的答案标记为正确,因为我将执行以下操作。在每个数据库中创建相同的视图,然后为所有下属创建一个父视图。这可行,但由于缺乏整合/糟糕的设计,这并不理想。至少我可以维护一个从属视图并复制它
【解决方案2】:

将结果存储到临时表中,例如:

CREATE TABLE #TempICITEM 
    ([DbName] [varchar](6) NOT NULL,
    [ICITEMId] [uniqueidentifier] NOT NULL,
    [Name] [varchar](100) NOT NULL,
    [Description] [varchar](1000) NOT NULL)

将您的 TSQL 选择更改为 Insert Into #TempTable Select,例如:

EXEC ('INSERT INTO #TempICITEM ([DbName],[ICITEMId],[Name],[Description]) SELECT ''' + @DB_NAME + ''' DbName,[DbName],[ICITEMId],[Name],[Description] FROM ' + @DB_NAME + '.dbo.ICITEM')

然后从临时表的组合结果中选择,例如:

SELECT * From #TempICITEM

一起来:

CREATE TABLE #TempICITEM 
    ([DbName] [varchar](6) NOT NULL,
    [ICITEMId] [uniqueidentifier] NOT NULL,
    [Name] [varchar](100) NOT NULL,
    [Description] [varchar](1000) NOT NULL)

DECLARE @DB_NAME VARCHAR(6);
DECLARE CURSOR_ALLDB_NAMES CURSOR FOR 
SELECT name
FROM sys.databases
WHERE name IN ('CN2DAT', 'AU1DAT') 

OPEN CURSOR_ALLDB_NAMES
FETCH NEXT FROM CURSOR_ALLDB_NAMES INTO @DB_NAME
WHILE @@Fetch_Status = 0
BEGIN
EXEC ('INSERT INTO #TempICITEM ([DbName],[ICITEMId],[Name],[Description]) SELECT ''' + @DB_NAME + ''' DbName,[DbName],[ICITEMId],[Name],[Description] FROM ' + @DB_NAME + '.dbo.ICITEM')
FETCH NEXT FROM CURSOR_ALLDB_NAMES INTO @DB_NAME
END

CLOSE CURSOR_ALLDB_NAMES
DEALLOCATE CURSOR_ALLDB_NAMES

SELECT * From #TempICITEM

【讨论】:

  • 请注意,它不一定是临时表。您也可以将其设为永久的,只是不要忘记将数据库名称添加为一列,以便您了解每条记录的源数据库。
猜你喜欢
  • 2010-10-15
  • 2021-02-06
  • 1970-01-01
  • 2017-11-04
  • 2019-02-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-06
相关资源
最近更新 更多