2015-11-04 75 views
2

在我的数据库的4个不同表格中找到数以千计的代码。我已经创建了一个临时表来插入所有的代码和相应的表名,可以找到该代码。作为一个例子,我展示了临时表的一小部分。使用动态查询字符串连接多个表格

代码 | table_name

DA | StatsCanCensus2011_1

DWAPT5L | StatsCanCensus2011_3

DWAPT5O | StatsCanCensus2011_3

DWDUP | StatsCanCensus2011_3

DWMOVA | StatsCanCensus2011_3

我想写一个查询,我可以动态地选择代码,并在选择的代码来自不同的表格时加入表格。我能够轻松地为2张桌子做到这一点,但是当有3张或4张时,它无法工作。

下面将给出的结果,我需要时2个表需要被接合:

declare @code nvarchar(15), @tblname nvarchar(30), @strSQL nvarchar(max), @strWhere nvarchar(max) 

DECLARE db_cursor CURSOR FOR 
select code, table_name from tmpVarList2 

OPEN db_cursor 
FETCH NEXT FROM db_cursor INTO @code, @tblname 
set @strSQL='select' 
WHILE @@FETCH_STATUS = 0 
BEGIN 
     print @code + @tblname 
     set @[email protected] + ' ' + @code + ',' 
     FETCH NEXT FROM db_cursor INTO @code, @tblname 
END 

set @strSQL=left(@strSQL, len(@strSQL)-1) 

print @strSQL 
CLOSE db_cursor 
DEALLOCATE db_cursor 


set @[email protected] + ' from' 
set @strWhere=' where ' 
DECLARE db_cursor CURSOR FOR 
select distinct table_name from tmpVarList2 

OPEN db_cursor 
FETCH NEXT FROM db_cursor INTO @tblname 

WHILE @@FETCH_STATUS = 0 
BEGIN 
     print @code + @tblname 
     set @[email protected] + ' ' + @tblname + ',' 
     set @[email protected] + @tblname + '.da=' 
     FETCH NEXT FROM db_cursor INTO @tblname 
END 

set @strSQL=left(@strSQL, len(@strSQL)-1) 
set @strWhere=left(@strWhere, len(@strWhere)-1) 
set @[email protected] + @strWhere 


SELECT @strSQL 

CLOSE db_cursor 
DEALLOCATE db_cursor 

结果:

select DA, DWAPT5L, DWAPT5O, DWDUP, DWMOVA 
from StatsCanCensus2011_1, StatsCanCensus2011_3 
where StatsCanCensus2011_1.da=StatsCanCensus2011_3.da 

结果的实施例时,有3个表加入:

select DA, DWAPT5L, FMCLNOCH,FMCPINTO, FMCPSZAV, FMCPTIAV, FMCPTIME, FMHHTOT 
from StatsCanCensus2011_1, StatsCanCensus2011_3, StatsCanNHS2011_4 
where StatsCanCensus2011_1.da=StatsCanCensus2011_3.da=StatsCanNHS2011_4.da 
+1

我建议你重写使用'JOIN ... ON'而不是用逗号分隔表格。 –

回答

1

使用游标来组装和执行动态SQL查询是雄心勃勃的,但这意味着执行路径永远不会被缓存。此外,如果这些是大型表格(因为普查数据倾向于),您可能会遇到一些优化的实际挑战。随着标准DBA绊脚石,它实际上是一个非常有趣的想法,因为它听起来很糟糕,但实际上并不那么糟糕(因为光标从不触及数据)。

我认为你是正确的方法,但你试图让每个光标做得太多。有三个部分可以用于你想要的查询,一个带有列表的select语句,一个带有连接表列表的from语句,以及一个包含连接这些表的逻辑的where语句(隐式地加入它们而不是明确地这样做) 。那么为什么不三个光标,每个都专注于一个特定的区域。它允许每个游标的构造更简单,然后您可以组合最终结果。

declare @select_Code varchar(max) 
declare @Select_column varchar(max) 
declare @selectloop int 
declare @From_Code varchar(max) 
declare @From_Column varchar(max) 
declare @FromLoop int 
declare @Where_Code Varchar(max) 

create table #temp (columnname varchar(128), tablename Varchar(128)) 

insert into #temp 
select 'ColumnA', 'TableA' 
union 
select 'Columnb', 'TableB' 
union 
select 'Columnc', 'TableC' 

--drop table #temp 

set @select_Code = 'Select ' 
set @selectloop = 0 

declare select_cursor cursor for 
    select columnname from #temp 

Open select_cursor 

fetch next from select_cursor 
into @Select_column 


while @@FETCH_STATUS = 0 
begin 
set @select_Code = @select_Code + (select case when @selectloop > 0 then ', ' else '' end as CommaOrNot) + @Select_column 
set @selectloop = @selectloop + 1 

fetch next from select_cursor into @Select_column 
end 
close select_cursor 
deallocate select_cursor 

set @From_Code = ' From ' 
set @FromLoop = 0 

declare From_cursor cursor for 
    select tablename from #temp 

Open From_cursor 

fetch next from From_cursor 
into @from_column 


while @@FETCH_STATUS = 0 
begin 
set @From_Code = @From_Code + (select case when @FromLoop > 0 then ', ' else '' end as CommaOrNot) + @from_column 
set @FromLoop = @FromLoop + 1 

fetch next from From_cursor into @from_column 
end 
close From_cursor 
deallocate From_cursor 

select @select_Code + @From_Code 

我让你做的where子句,因为我不知道,如果你是菊花链连接它们,或者如果他们全部加入回到第一个表,无论是它遵循相同的模式,你只需要将案例陈述更新为类似的东西;

case when @whereloop > 0 and @whereloop % 2 = 0 then ' and ' 
    when @whereloop > 0 and @whereloop % 2 = 1 then ' = ' 
    else '' end as EqualsOrNewJoin 

对于选择和语句我使用循环数来确定,如果我需要在现有代码和新的部分之间的CONCAT前加逗号。对于where子句有点棘手,它需要在x = y和y = z的地方。所以我使用mod来获取循环数的其余部分,以确定循环是奇数还是一旦我们超过第一个循环(循环0)。如果它很奇怪(循环1是第二个条目),我知道它们之间应该有一个=符号,例如:Loop0 = loop1。如果甚至我知道我们正在建立一个新的条件,所以我需要使用和。无论如何,希望这有助于,并让我知道如果你有任何问题。

+0

感谢您的评论,它已经帮了很多。我正在通过一些纠结工作,并会让你知道它是怎么回事!通过将每个任务分解到不同的光标来简化事情使其更容易遵循。 –