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

T-SQL - Building Dynamic Query in While Loop

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

我 运行 在 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@tableSumwhile 循环之后。

另一方面,如果您评论那2行RAISERROR并且取消评论这对在 while 循环内,每次迭代都会显示变量!

我非常困惑并且已经搜索了互联网的深度以了解为什么会发生这种情况。请有人帮助我。

P.S。这将在存储过程中使用。它很长而且与这个问题无关,因为我已经能够将其隔离为我糟糕结果的原因。

为什么在最后一个循环中看不到任何内容 @currentTable 为空,因为最后一行已在倒数第二个循环中删除。由于 @currentTable 为 null,因此 @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

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

尼尔斯