这是我可以重现问题的最简单的例子.因此它看起来有点做作,但请耐心等待.
declare @t table(number int)
insert into @t values (1), (2)
declare @sum bigint = 0
select @sum = @sum + number
from (select top 2 number from @t order by number) subquery
order by number desc
select @sum
Run Code Online (Sandbox Code Playgroud)
我希望这会返回3,即表中值的总和@t.相反,它返回1.
执行以下任何操作都会导致查询正确返回3:
@t.number与@sum具有相同类型的(通过使@sum一个int或@t.number一个bigint).order byorder byorder by通过添加desc到内部或从外部移除它来使两者在同一方向上排序from @t)这些事情都不会让我觉得应该改变这个查询的行为.
交换排序顺序(在子查询中降序,在外部升序)将使查询返回2而不是1.
类似的事情发生在字符串而不是数字上,所以这并不局限于int和bigint.
SQL Server 2014和2016都会发生这种情况,或者说准确
Microsoft SQL Server 2014 - 12.0.2000.8 (X64)
Feb 20 2014 20:04:26
Copyright (c) Microsoft Corporation
Developer Edition (64-bit) on Windows NT 6.3 <X64> (Build 10586: )
Run Code Online (Sandbox Code Playgroud)
和
Microsoft SQL Server 2016 (RTM-CU1) (KB3164674) - 13.0.2149.0 (X64)
Jul 11 2016 22:05:22
Copyright (c) Microsoft Corporation
Enterprise Edition: Core-based Licensing (64-bit) on Windows Server 2012 R2 Standard 6.3 <X64> (Build 9600: )
Run Code Online (Sandbox Code Playgroud)
(后者是数据浏览器).
这是怎么回事?
答案似乎是您正在/正在依赖 Sql Server 2012 中更改的未记录行为。
根据文档:
SELECT @local_variable 通常用于将单个值返回到变量中。但是,当表达式是列名时,它可以返回多个值。如果 SELECT 语句返回多个值,则为变量分配最后返回的值。
如果(要分配给的)目标变量是源表达式的一部分,则没有记录会发生什么情况。看来这种行为已经改变了。在早期版本中,将为每行分配一次变量,但这种情况似乎不再发生。
这对于“组连接”技巧不再起作用的许多函数来说最为明显:
SELECT @sentence = @sentence + ' ' + word from SENTENCE_WORDS order by position
Run Code Online (Sandbox Code Playgroud)
这些通常必须被 xml concat 技巧取代。
set @sentence = (
select word as "text()", ' ' as "text()"
from SENTENCE_WORDS
order by position
for xml path(''), root('root'), type
).value('(/root)[1]', 'nvarchar(max)')
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
85 次 |
| 最近记录: |