仅在数据库存在时联合

时间:2014-02-26 04:14:00

标签: sql sql-server

我有多个具有相同表格的数据库。我有一张名为Invoices的桌子。我现在正在进行查询的方式如下:

Select * from [Db1].dbo.Invoices where [Id] = 'someId'
UNION ALL Select * from [Db2].dbo.Invoices where [Id] = 'someId'
UNION ALL Select * from [Db3].dbo.Invoices where [Id] = 'someId'

例如,如果Db3不存在,该查询将引发错误。我正在努力创造像

这样的东西
IF db_id('Db1') is not null  -- if database Db1 exists
    Select * from [Db1].dbo.Invoices where [Id] = 'someId'
IF db_id('Db2') is not null
    UNION ALL Select * from [Db2].dbo.Invoices where [Id] = 'someId'
IF db_id('Db3') is not null
    UNION ALL Select * from [Db3].dbo.Invoices where [Id] = 'someId'

该查询不起作用,但希望我说明我想要完成的任务

修改

非常感谢您的帮助!如果找不到第一个数据库,我的查询将以UNION ALL开头,从而产生错误。我该如何防止这种情况?

4 个答案:

答案 0 :(得分:1)

您无法执行此操作,因为SQL Server会在执行前解析查询并尝试验证select脚本中的dbs / tables。所以你能做到这一点的唯一方法就是使用动态SQL:

DECLARE @sql NVARCHAR(MAX)

SET @sql = ''

IF db_id('Db1') is not null  -- if database Db1 exists
    SET @sql+='Select * from [Db1].dbo.Invoices where [Id] = ''someId'''
IF db_id('Db2') is not null
    SET @sql+='UNION ALL Select * from [Db2].dbo.Invoices where [Id] = ''someId'''
IF db_id('Db3') is not null
    SET @sql+='UNION ALL Select * from [Db3].dbo.Invoices where [Id] = ''someId'''

EXEC (@sql)

斯图。

答案 1 :(得分:1)

您可以使用动态SQL

DECLARE @sql NVARCHAR(MAX) = ''

IF db_id('Db1') is not null  -- if database Db1 exists
    SET @sql = @sql + 'Select * from [Db1].dbo.Invoices where [Id] = ''someId'''
IF db_id('Db2') is not null
BEGIN
    IF LEN(@sql) > 0
        SET @sql = @sql + N' UNION ALL '
    SET @sql = @sql + 'Select * from [Db2].dbo.Invoices where [Id] = ''someId'''
END
IF db_id('Db3') is not null
BEGIN
    IF LEN(@sql) > 0
        SET @sql = @sql + N' UNION ALL '
    SET @sql = @sql + 'Select * from [Db3].dbo.Invoices where [Id] = ''someId'''
END

exec sp_executesql @sql

答案 2 :(得分:1)

这里需要动态SQL

declare @qry varchar(max)=''
IF db_id('Db1') is not null  -- if database Db1 exists
        set @qry='Select * from [Db1].dbo.Invoices where [Id] = ''someId'''
IF db_id('Db2') is not null
    begin 
        set @qry=@qry + case when @qry<>'' then ' UNION ' ELSE '' end
        set @qry=@qry +' UNION ALL Select * from [Db2].dbo.Invoices where [Id] = ''someId'''
    end

IF db_id('Db3') is not null
    begin 
        set @qry=@qry + case when @qry<>'' then ' UNION ' ELSE '' end
        set @qry=@qry +' UNION ALL Select * from [Db3].dbo.Invoices where [Id] = ''someId'''
    end

if @qry<>'' 
EXEC(@qry)

答案 3 :(得分:1)

这里最短的版本

这将打印您需要的声明。只需将输出设置为文本并运行以下命令。

EXEC sp_MSForeachDB ' DECLARE @cmd VARCHAR(MAX)
SET @cmd = ''SELECT * FROM [?].dbo.Invoices WHERE ID=''''Something'''' UNION ALL''
PRINT @CMD
'

我相信你可以修改代码来执行而不是打印。它还不完美,但你应该能够使用它。

更新确定,以便缩短版本不会轻松工作。但是,通过应用此技术,您可以获得相同的结果。

CREATE TABLE #Tables
(
    TABLE_NAME SYSNAME NOT NULL
);

EXEC sp_MSForeachDB ' DECLARE @cmd VARCHAR(MAX)
INSERT INTO #TABLES SELECT TABLE_NAME FROM [?].INFORMATION_SCHEMA.TABLES'
SELECT * FROM #Tables
DROP TABLE #Tables

这将获得与union相同的结果,您无需提前知道所有数据库。因此,如果您添加DB2000,它将按原样工作。您永远不必再次编辑查询。