使用SELECT在SQL Server变量赋值中执行的顺序

Tim*_*ner 8 sql t-sql sql-server variable-assignment operator-precedence

给出以下示例:

declare @i int
select @i = 1, @i = 2
select @i
Run Code Online (Sandbox Code Playgroud)

@i永远是2?

这是我能想到的最简单的例子,但我正在考虑使用它来交换变量中的值.我也相信这种赋值方法(select)不符合ANSI标准(无论多么有用),但在这种情况下并不真正关心可移植代码.

UPDATE

感谢@MichaelFredrickson,我们有@ MartinSmith的回答,并参考了MSDN.我现在正在努力解决本文档中的第二句话的确切含义(强调添加):

如果单个SELECT语句中有多个赋值子句,则SQL Server不保证表达式的计算顺序.请注意,只有在分配中有引用时才会显示效果.

然而,第一句话足以让我远离依赖这种行为.

Mic*_*son 6

对于变量赋值,Martin Smith在这里引用MSDN来回答这个问题:

如果单个SELECT语句中有多个赋值子句,则SQL Server不保证表达式的计算顺序.请注意,只有在分配中有引用时才会显示效果.

但...

如果我们处理的是表,而不是变量,那就是一个不同的故事.

在这种情况下,Sql Server使用All-At-Once操作,正如Itzik Ben-Gan在T-Sql Fundamentals中所讨论的那样.

该概念表明,在相同的逻辑阶段中的所有表达式都被评估为好像在相同的时间点......而不管它们从左到右的位置.

所以在处理相应的UPDATE声明时:

DECLARE @Test TABLE (
    i INT,
    j INT
)

INSERT INTO @Test VALUES (0, 0)

UPDATE @Test
SET
    i = i + 10,
    j = i

SELECT 
    i, 
    j 
FROM 
    @Test
Run Code Online (Sandbox Code Playgroud)

我们得到以下结果:

i           j
----------- -----------
10          0   
Run Code Online (Sandbox Code Playgroud)

通过在Sql Server中使用All-At-Once评估...,您可以在没有中间变量/列的表中交换列值.

据我所知,大多数RBDMS都以这种方式运行,但MySql是个例外.


编辑:

请注意,只有在分配中有引用时才会显示效果.

我理解这意味着如果您有SELECT如下声明:

SELECT
    @A = ColumnA,
    @B = ColumnB,
    @C = ColumnC
FROM MyTable
Run Code Online (Sandbox Code Playgroud)

那么分配的执行顺序并不重要......无论如何,你都会得到相同的结果.但如果你有类似......

SELECT
    @A = ColumnA,
    @B = @A,
    @C = ColumnC
FROM MyTable
Run Code Online (Sandbox Code Playgroud)

现在有一个工作分配中引用(@B = @A),以及顺序@A@B分配现在最重要的.