我的SQL Server设置中有9个数据库。让我们称它们为ONE_DB,TWO_DB等。我发现自己正在做的一个非常常见的任务是从所有九个实例(通常是非常小的表,如配置等)中提取一些数据,对同一个表但在所有数据库中使用相同的查询。我想要一个union all select interesting_col from *.dbo.tableX
基于SO上的其他问题,我提出了一种方法来做到这一点,但我对此解决方案并不满意。可以说我只想要一个表中的一列,我首先运行下面的SQL查询...
declare @db varchar(30)
declare @db_list varchar(200)
set @db = ''
set @db_list = 'ONE_DB,TWO_DB,THREE_DB,FOUR_DB,FIVE_DB,SIX_DB,SEVEN_DB,EIGHT_DB,NINE_DB'
while len(@db_list) > 0
begin
set @db = left(@db_list, charindex(',', @db_list+',')-1);
set @db_list = stuff(@db_list, 1, charindex(',', @db_list+','), '');
exec ( 'use '+@db+'; select tx.interesting_columns from dbo.TableX as tx;')
end
...然后我手动将9个结果集复制粘贴到Excel。当然我通常在select语句中做一些处理,比如不同的连接,聚合,case-clause等。但我想你明白了。
这个过程非常好,但是当有更复杂的select语句时,代码不是很容易阅读。由于语法highlighter将所有有趣的东西(select语句)解释为字符串,因此新人阅读此代码也很困难。
什么是"好"处理这个的方法?
答案 0 :(得分:2)
借助Parse / Spit功能并使用“令牌”作为数据库名称
Declare @db_list varchar(max) = 'ONE_DB,TWO_DB,THREE_DB,FOUR_DB,FIVE_DB,SIX_DB,SEVEN_DB,EIGHT_DB,NINE_DB'
Declare @cmd varchar(max) = ';Use <<dbname>>; select interesting_col from dbo.tableX'
Declare @SQL varchar(max) = '>>>'
Select @SQL = Replace(Replace(@SQL+replace(@cmd,'<<dbname>>',QuoteName(RetVal))+char(13),'>>>Union All',''),'>>>','')
From [dbo].[udf-Str-Parse](@db_list,',')
Exec(@SQL)
示例1
Declare @cmd varchar(max) = ';Use <<dbname>>; select interesting_col
SQL Generated是
;Use [ONE_DB];select interesting_col from *.dbo.tableX
;Use [TWO_DB];select interesting_col from *.dbo.tableX
;Use [THREE_DB];select interesting_col from *.dbo.tableX
;Use [FOUR_DB];select interesting_col from *.dbo.tableX
;Use [FIVE_DB];select interesting_col from *.dbo.tableX
;Use [SIX_DB];select interesting_col from *.dbo.tableX
;Use [SEVEN_DB];select interesting_col from *.dbo.tableX
;Use [EIGHT_DB];select interesting_col from *.dbo.tableX
;Use [NINE_DB];select interesting_col from *.dbo.tableX
示例2 - 合并结果
Declare @cmd varchar(max) = 'Union All select DBName=''<<dbname>>'',interesting_col from <<dbname>>.dbo.tableX'
SQL Generated
select DBName='[ONE_DB]',interesting_col from [ONE_DB].dbo.tableX
Union All select DBName='[TWO_DB]',interesting_col from [TWO_DB].dbo.tableX
Union All select DBName='[THREE_DB]',interesting_col from [THREE_DB].dbo.tableX
Union All select DBName='[FOUR_DB]',interesting_col from [FOUR_DB].dbo.tableX
Union All select DBName='[FIVE_DB]',interesting_col from [FIVE_DB].dbo.tableX
Union All select DBName='[SIX_DB]',interesting_col from [SIX_DB].dbo.tableX
Union All select DBName='[SEVEN_DB]',interesting_col from [SEVEN_DB].dbo.tableX
Union All select DBName='[EIGHT_DB]',interesting_col from [EIGHT_DB].dbo.tableX
Union All select DBName='[NINE_DB]',interesting_col from [NINE_DB].dbo.tableX
示例3 - 执行存储过程
Declare @cmd varchar(max) = ';Use <<dbname>>; exec SomeStoredProcedure'
SQL Generated
;Use [ONE_DB]; exec SomeStoredProcedure
;Use [TWO_DB]; exec SomeStoredProcedure
;Use [THREE_DB]; exec SomeStoredProcedure
;Use [FOUR_DB]; exec SomeStoredProcedure
;Use [FIVE_DB]; exec SomeStoredProcedure
;Use [SIX_DB]; exec SomeStoredProcedure
;Use [SEVEN_DB]; exec SomeStoredProcedure
;Use [EIGHT_DB]; exec SomeStoredProcedure
;Use [NINE_DB]; exec SomeStoredProcedure
UDF(如果需要)
CREATE FUNCTION [dbo].[udf-Str-Parse] (@String varchar(max),@Delimiter varchar(10))
Returns Table
As
Return (
Select RetSeq = Row_Number() over (Order By (Select null))
,RetVal = LTrim(RTrim(B.i.value('(./text())[1]', 'varchar(max)')))
From (Select x = Cast('<x>'+ Replace(@String,@Delimiter,'</x><x>')+'</x>' as xml).query('.')) as A
Cross Apply x.nodes('x') AS B(i)
);
--Select * from [dbo].[udf-Str-Parse]('Dog,Cat,House,Car',',')
--Select * from [dbo].[udf-Str-Parse]('John Cappelletti was here',' ')
答案 1 :(得分:2)
考虑使用SQL Server Management Studio的服务器组功能对多个服务器(或您的案例中同一服务器上的多个数据库)执行即席查询,并自动联合结果。这可以按如下方式完成。
1)右键单击SSMS对象资源管理器中的“本地服务器组”节点,选择“新建服务器组”,并为其指定一个助记符名称(例如DevServerDatabases)。
2)右键单击新组名,选择New Server Registration,指定:
将所有数据库添加到组后,右键单击组名称并选择“新建查询”。在窗口中输入临时查询并执行。结果集将包含所有查询结果的联合以及数据库名称(Server Name
列),可以打开或关闭((工具 - &gt;选项 - &gt;查询结果 - &gt; SQL Server - &gt;多服务器结果)。
答案 2 :(得分:0)
使用SSIS从多个数据库中提取数据。在SSIS中,您可以合并并以其他方式转换数据并将其输出为excel。您还可以安排SSIS自动运行。