+ =在SELECT子句中;常数vs列[重复]

问题描述 投票:9回答:3

这个问题在这里已有答案:

我在MS SQL Server 2017中观察到了一些奇怪的行为。

  • 当右侧是常量时,select中的+=充当聚合器('连接所有行的值')。
  • select中的+=在右侧是列名称时仅用作“设置值”。 (另外,这会改变其他列的聚合行为)

所以我的问题是:

  1. 为什么@c1结果只包含最后一行的值,即使使用+=
  2. 为什么@c2受到+=的变化=-> @c1的影响?

版本1:

BEGIN
    DECLARE
        @c1 NVARCHAR(MAX) = N'',
        @c2 NVARCHAR(MAX) = N'';

    SELECT
        @c1 = constraint_name, -- version-1
        @c2 += '+'
    FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS
    ORDER BY 1 DESC
    ;

    PRINT '@c1=' + @c1;
    PRINT '@c2=' + @c2;
END
;

版本1结果:

@c1 = fk_abcde
@c2 = ++++++++++++++++++++++++++++++++++++++++++
(`@c2` result is aggregation of many rows; one plus for each row)

版本2:

BEGIN
    DECLARE
        @c1 NVARCHAR(MAX) = N'',
        @c2 NVARCHAR(MAX) = N'';

    SELECT
        @c1 += constraint_name, -- version-2
        @c2 += '+'
    FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS
    ORDER BY 1 DESC
    ;

    PRINT '@c1=' + @c1;
    PRINT '@c2=' + @c2;
END
;

版本2结果:

@c1 = fk_abcde
@c2 = +
(`@c2` is just value assigned from last processed row)

这感觉很奇怪 - 有点像虫子。我没有找到任何关于此的文档。 doc on '+= string'根本没有在+=查询中提及select用法。

(目前我的目标是完全理解这种行为,所以我不会不小心踩到它。任何提示正确的文档/关键字搜索都会有所帮助)

sql sql-server tsql sql-server-2017
3个回答
1
投票

这是在wrong place in the documentation,所以你没有找到它并不奇怪:

不要在SELECT语句中使用变量来连接值(即,计算聚合值)。可能会发生意外的查询结果。因为,SELECT列表中的所有表达式(包括赋值)不一定只为每个输出行运行一次

最好寻找不同的字符串连接方式。如果您的版本支持它,请选择使用STRING_AGG。对于早期版本,Aaron Bertrand提供了good set of options(帽子提示给Panagiotis Kanavos for providing the link


0
投票

好吧,我发现非常有趣:没有ORDER BY查询一致和预期运行。

但是当添加qazxsw poi子句时,我会得到与你相同的结果。

我建议使用CTE和排序 - 遗憾的是CTE或子查询中不允许排序,但解决方法是使用ORDER BY关键字,这允许我们在这种情况下订购。

见下面的脚本:

TOP

-1
投票

您应该使用;with cte as ( select top 100 percent table_schema from information_schema.columns order by 1 ) -- This is more reliable select @c1 = table_schema, @c2 += '+' from cte 而不是Order by constraint_name,因为您将值分配给变量。它不是选择声明。

© www.soinside.com 2019 - 2024. All rights reserved.