T-SQL - 在While循环中构建动态查询

时间:2018-04-11 21:15:12

标签: sql-server stored-procedures sql-server-2016 dynamic-sql

我正在尝试构建一个连接到可变数量的表的动态查询。这些表作为参数@airflowTablesToSum提供,用逗号分隔,添加到表中并迭代以在@joinClauses中创建多个连接。

我在连接while循环中的字符串时遇到了问题,并且使用以下代码可以观察到它:

declare @airflowTablesToSum as varchar(max) = 'FP_1_01RM109CSA_F,FP_1_02RM109ASA_F,FP_1_03RM109DSA_F,FP_1_04RM110SA_F,FP_1_05RM111ASA_F,FP_1_06RM112SA_F,FP_1_07RM108SA_F,FP_1_08MAUTSA_F,FP_1_09SAUTSA_F,FP_1_10SAUTSA_F,FP_1_11MAUTSA_F,FP_1_12RM104SA_F,FP_2_01RM208SA_F,FP_2_02RM207SA_F,FP_2_03RM206SA_F,FP_2_04RM208BSA_F,FP_2_05RM209SA_F,FP_2_06RM209ASA_F,FP_2_07RM205SA_F,FP_2_08RM205ASA_F,FP_2_09RM224SA_F,FP_2_10RM232SA_F,TECHEDFP211RM239SAF,TECHEDFP212RM239ASAF,TECHEDFP213RM204SAF,TECHEDFP214RM213SAF,TECHEDFP215RM215SAF,TECHEDFP216RM219SAF,TECHEDFP217ARM241SAF,TECHEDFP217RM240SAF,TECHEDTU201RM205ESAF,TECHEDTU202RM209BSAF,TECHEDVMA11RM101VSUPFLOW,TECHEDVMA12RM101SSUPFLOW,TECHEDVMA13RM101RSUPFLOW,TECHEDVMA14RM101QBSUPFLOW,TECHEDVMA15RM101PSUPFLOW,TECHEDVMA29RM101ESUPFLOW,TECHEDVMA30RM101KSUPFLOW,TECHEDVMA31RM101JSUPFLOW,TECHEDVMA32RM101SUPFLOW,TU001SAF';

CREATE TABLE #tableNames (id int identity(1,1), tname varchar(max));
insert into #tableNames select value from string_split(@airflowTablesToSum,',');

declare @previousTable varchar(max) = (select tName from #tableNames where id=1);
DELETE FROM #tableNames WHERE tname = @previousTable;

declare @joinClauses varchar(max) = ' ' + @previousTable + ' a ';
declare @tableSum varchar(max) = 'a.[VALUE]';
set @previousTable = 'a';

select * from #tableNames;

WHILE @@ROWCOUNT <> 0
BEGIN
    declare @currentTable varchar(max) = (select top 1 tname from #tableNames);

    set @joinClauses += ('join ' + @currentTable + ' on cast(' + @currentTable + '.[TIMESTAMP] as smalldatetime) = cast(' + @previousTable + '.[TIMESTAMP] as smalldatetime) ');
    set @tableSum += (' + ' + @currentTable + '.[VALUE]');

    --RAISERROR(@joinClauses,0,1);
    --RAISERROR(@tableSum,0,1);

    set @previousTable = @currentTable;
    DELETE FROM #tableNames WHERE tname = @currentTable;
END
    RAISERROR(@joinClauses,0,1);
    RAISERROR(@tableSum,0,1);

drop TABLE #tableNames;

执行时的输出消息按预期显示要删除的行FROM #tableNames但{{>>之后没有打印变量 @joinClauses@tableSum 1}}循环。

另一方面,如果您评论那两条while行并且取消注释while循环中的对,变量显示每次迭代!

我非常困惑,并且已经深入研究了为什么会发生这种情况的互联网深度。有人帮帮我。

P.S。这将用于存储过程。这个问题很长并且无关紧要,因为我已经把这个问题看作是导致我不良结果的原因。

1 个答案:

答案 0 :(得分:1)

为什么在最后一个循环中没有看到任何内容@currentTable为空,因为在倒数第二个循环中删除了最后一行。由于@currentTable为空,您@joinclauses@tableSum的串联会产生NULL值,并且不会打印。

我会将您的代码更改为:

declare @airflowTablesToSum as varchar(max) = 'FP_1_01RM109CSA_F,FP_1_02RM109ASA_F,FP_1_03RM109DSA_F,FP_1_04RM110SA_F,FP_1_05RM111ASA_F,FP_1_06RM112SA_F,FP_1_07RM108SA_F,FP_1_08MAUTSA_F,FP_1_09SAUTSA_F,FP_1_10SAUTSA_F,FP_1_11MAUTSA_F,FP_1_12RM104SA_F,FP_2_01RM208SA_F,FP_2_02RM207SA_F,FP_2_03RM206SA_F,FP_2_04RM208BSA_F,FP_2_05RM209SA_F,FP_2_06RM209ASA_F,FP_2_07RM205SA_F,FP_2_08RM205ASA_F,FP_2_09RM224SA_F,FP_2_10RM232SA_F,TECHEDFP211RM239SAF,TECHEDFP212RM239ASAF,TECHEDFP213RM204SAF,TECHEDFP214RM213SAF,TECHEDFP215RM215SAF,TECHEDFP216RM219SAF,TECHEDFP217ARM241SAF,TECHEDFP217RM240SAF,TECHEDTU201RM205ESAF,TECHEDTU202RM209BSAF,TECHEDVMA11RM101VSUPFLOW,TECHEDVMA12RM101SSUPFLOW,TECHEDVMA13RM101RSUPFLOW,TECHEDVMA14RM101QBSUPFLOW,TECHEDVMA15RM101PSUPFLOW,TECHEDVMA29RM101ESUPFLOW,TECHEDVMA30RM101KSUPFLOW,TECHEDVMA31RM101JSUPFLOW,TECHEDVMA32RM101SUPFLOW,TU001SAF';

CREATE TABLE #tableNames (id int identity(1,1), tname varchar(max));
insert into #tableNames select value from string_split(@airflowTablesToSum,',');

declare @previousTable varchar(max) = (select tName from #tableNames where id=1);
DELETE FROM #tableNames WHERE tname = @previousTable;

declare @joinClauses varchar(max) = ' ' + @previousTable + ' a ';
declare @tableSum varchar(max) = 'a.[VALUE]';
set @previousTable = 'a';

select * from #tableNames;

declare @currentTable varchar(max);

SELECT TOP(1) @currentTable =  tname FROM #tableNames

WHILE @@ROWCOUNT <> 0
BEGIN

    set @joinClauses += ('join ' + @currentTable + ' on cast(' + @currentTable + '.[TIMESTAMP] as smalldatetime) = cast(' + @previousTable + '.[TIMESTAMP] as smalldatetime) ');
    set @tableSum += (' + ' + @currentTable + '.[VALUE]');

    set @previousTable = @currentTable;
    DELETE FROM #tableNames WHERE tname = @currentTable;

    SELECT TOP(1) @currentTable =  tname FROM #tableNames

END
    RAISERROR(@joinClauses,0,1);
    RAISERROR(@tableSum,0,1);

drop TABLE #tableNames;

另外,为什么你在RAISERROR本质上使用PRINT

无论如何,希望这有帮助!

尼尔斯