在 SELECT 中分配变量是否执行 RBAR 操作?

Mar*_*ust 2 sql-server t-sql

所以,我发现了一些有趣的事情。我在玩 TOP 命令并在 select 语句中分配变量。我发出了以下查询,发现变量 (@a) 值是从 Top 命令返回的最后一个值。似乎对于每个返回的值,该值被分配给变量,然后结果集中的每一行随后被分配,几乎就像一个循环。

declare @a nvarchar(max)

select top 10 DisplayName
from dbo.Users

select top 10 @a = DisplayName
from dbo.Users

select @a as Results
Run Code Online (Sandbox Code Playgroud)

结果:

结果集 1

这让我很好奇。我修改了查询以再次测试并执行以下操作:

declare @a nvarchar(max)
declare @b int = 0

select TOP 10 @a = DisplayName, @b = @b + 1
from dbo.Users

select @a as DisplayName, @b as Number
Run Code Online (Sandbox Code Playgroud)

结果:

结果图 2

这真的很有趣。从这两个查询来看,由于@b 上发生的累积总和以及上面发生的分配,TOP 命令似乎正在执行某种循环。有人可以解释发生了什么吗?使用 TOP 命令时,SQL 是否会执行 RBAR 操作?

编辑:

我也在没有 TOP 命令的情况下执行此操作,并查看结果,因此它不仅仅是 TOP 命令。似乎在 SELECT 语句中分配变量执行 RBAR 命令?

declare @a nvarchar(max)
declare @b int = 0

select @a = DisplayName, @b = @b + 1
from dbo.Users

select @a as DisplayName, @b as Number
Run Code Online (Sandbox Code Playgroud)

结果:

结果图 3

Dav*_*oft 6

似乎对于每个返回的值,该值被分配给变量,然后结果集中的每一行随后被分配,几乎就像一个循环。

是的。这就是发生的事情。这是最初实现 SELECT 查询中的变量分配方式的副作用。但它被使用得足够多,以至于无法真正改变,甚至被记录在案:

如果 SELECT 语句返回多行并且该变量引用了一个非标量表达式,则该变量将设置为为结果集最后一行中的表达式返回的值。

变量 (Transact-SQL)

出于向后兼容性的原因,SQL Server 支持在最顶层范围内的 SELECT @p = @p + 1 ... ORDER BY 类型的赋值。

SQL Server 中的排序保证