我在MS SQL Server 2017中观察到一些奇怪的行为。
+=
充当聚合器(“连接所有行中的值”),当右边是常数时。+=
充当“只是设置值”。 (同样,这将导致其他列的汇总行为)所以我的问题是:
@c1
时,为什么+=
结果仅在最后一行包含值?@c2
的更改+=
-> =
为什么@c1
受其影响?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)
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)
这感觉很奇怪-有点像bug。
我找不到有关此的任何文档。
doc on '+= string'在+=
查询中根本没有提到select
的用法。
(目前,我的目标是完全了解这种行为,所以我不会无意间踩到它。任何有关搜索正确文档/关键字的提示都会有所帮助)
答案 0 :(得分:1)
它位于wrong place in the documentation中,所以您没有找到它就不足为奇了:
请勿在SELECT语句中使用变量来连接值(即,计算聚合值)。可能会出现意外的查询结果。因为,SELECT列表中的所有表达式(包括赋值)不一定对每个输出行只运行一次
最好寻找不同的字符串连接方式。如果您的版本支持它,请选择使用STRING_AGG
。对于早期版本,Aaron Bertrand提供了good set of options(向Panagiotis Kanavos推荐了providing the link的技巧)
答案 1 :(得分:0)
好吧,我发现的发现很有趣:没有ORDER BY
查询可以一致且预期地运行。
但是当添加ORDER BY
日历时,我得到的结果与您相同。
我建议在订购时使用CTE-不幸的是,在CTE或子查询中不允许订购,但是解决方法是使用TOP
关键字,这使我们可以在这种情况下进行订购。
请参见以下脚本:
;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
答案 2 :(得分:-1)
您应该使用Order by constraint_name
而不是Order by 1
,因为您正在将值分配给变量。它不是select语句。