sql - 使用动态查询字符串连接多个表

标签 sql join dynamic-sql

我的数据库中有 4 个不同的表,可找到数千个代码。我创建了一个临时表来插入所有代码以及可以找到该代码的相应表名称。作为示例,我展示了临时表的一小部分。

代码 | 表名

DA |加拿大人口普查统计局2011_1

DWAPT5L |加拿大人口普查统计局2011_3

DWAPT5O |加拿大人口普查统计局2011_3

DWDUP |加拿大人口普查统计局2011_3

DWMOVA |加拿大人口普查统计局2011_3

我正在尝试编写一个查询,当所选代码来自不同的表时,我可以动态选择代码并连接表。我可以轻松地为 2 张 table 做到这一点,但是当有 3 或 4 张 table 时,它就不起作用了。

下面将给出当需要连接 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 @strSQL=@strSQL + ' ' +  @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 @strSQL=@strSQL + ' 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 @strSQL=@strSQL + ' ' +  @tblname + ','
       set @strWhere=@strWhere + @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 @strSQL=@strSQL + @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

最佳答案

使用游标来组装和执行动态 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

对于 select 和 from 语句,我使用循环编号来确定是否需要在现有代码和新部分之间的连接之前添加逗号。对于 where 子句来说有点棘手,它需要是 where x = y 且 y = z。因此,我使用 mod 来获取循环编号的剩余部分,以确定一旦我们经过第一个循环(循环 0)后该循环是奇数还是偶数。如果它很奇怪(循环 1 这是第二个条目),我知道它们之间应该有一个 = 符号,例如:Loop0 = Loop1。如果是的话,我知道我们正在声明一个新的 where 条件,所以我需要使用 and 。无论如何,希望这对您有所帮助,如果您有任何疑问,请告诉我。

关于sql - 使用动态查询字符串连接多个表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33525428/

相关文章:

sql - 将行从一个表复制到另一个表,忽略重复项

mysql - 当我在两个表上执行 'select' 查询时,它会呈现表内的所有元素

java - Hiibernate : java. lang.ClassCastException : java. lang.String 无法转换为 java.lang.Integer

sql-server - 是否可以使用带参数的 sp_executesql 发出 CREATE 语句?

sql-server - 动态 SQL 有哪些危险以及可以避免吗?

Oracle、动态sql和命名参数

SQL 查询 : How to do multiple counts?(返回每个论坛的帖子数以及主题数)

mysql - 在 SQL 表之间加入

php - MySQL:在Join语句和Join语句顺序中使用列别名?

MySQL - 子查询/JOIN同表不同修订项