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不保证表达式的计算顺序.请注意,只有在分配中有引用时才会显示效果.
然而,第一句话足以让我远离依赖这种行为.
对于变量赋值,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分配现在最重要的.