使用一个SELECT语句初始化多个变量

时间:2014-06-05 08:05:49

标签: tsql select sql-server-2012 variable-assignment

这是众所周知的做法:

DECLARE @A INT
       ,@B INT

SELECT @A = [Column01]
      ,@B = [Column02]
FROM [dbo].[data]

我想知道以下代码是否正确:

DECLARE @A INT
       ,@B INT

SELECT @A = [Column01]
      ,@B = @A + [Column02]
FROM [dbo].[data]

@A始终在@B之前获得价值?


在我的实际案例中,[Column01]Column02是一个包含许多列和T-SQL函数的表达式,并使用@A作为参考,简化了@B的初始化。

2 个答案:

答案 0 :(得分:3)

that @A is always getting value before @B?

答案是否定的。

引自Itzik Ben-Gan的Microsoft SQL Server 2012 T-SQL Fundamentals

  

SQL支持一种称为一次性操作的概念,这意味着出现在同一逻辑查询处理阶段的所有表达式都会在同一时间点进行逻辑评估。

请同时查看All-at-Once Operations in T-SQL

答案 1 :(得分:1)

根据我的经验到目前为止这对我来说一直是“自上而下”。然而,每当我写这样的东西时,我也会感到有些不安,并且当我有一个更偏执的日子时,我知道将它分成两个单独的命令,也许我应该有更多的那些=)

那就是说,问题可以扩展到这些语法,我根据经验假设它们是正确的,但又想知道是否有人对它有更明确的答案:

DECLARE @a int,
        @b int,
        @x int

SELECT @a = (CASE name WHEN 'A' THEN value ELSE @a END),
       @b = (CASE name WHEN 'B' THEN value ELSE @b END)
  FROM myTable
 WHERE name IN ('A', 'B')

给出了与下面相同的结果,但速度要快得多,特别是如果你需要获取其中的很多

SELECT @a = value FROM myTable WHERE name = 'A'
SELECT @b = value FROM myTable WHERE name = 'B'

或者,这个:

DECLARE @a int = 8,
        @b int = 5,
        @x int

UPDATE myTable
   SET @x = @a * leftField + @b * rightField,
       mySum = @x,
       mySquare = Power(@x, 2)
 WHERE ...

我使用@x计算给定记录的中间值,并稍后使用该值设置字段或再次作为公式的一部分。 (我同意这是一个愚蠢的例子,但现在却无法提出更明智的事情)

或者这个现在似乎被普遍认为是'好'的,但是我确实记得,如果你要添加一个ORDER BY,这通常是一个需要的日子。 / p>

DECLARE @a varchar(max)

SELECT @a = (CASE WHEN @a IS NULL THEN name ELSE @a + ',' + name END)
  FROM sys.objects
 WHERE type = 'S'

SELECT @a

更新:只要数据集很小,这些事情(可能)通常都可以正常工作,但是当数据大小增加并且QO决定使用不同的计划时,奇怪的事情就会发生多线程等...所以我试图通过设置一个不再适合记忆的大表来“破解”事情,然后看看会发生什么。我举了一个简单的例子,很容易被分成多个线程。可以找到结果 here,但是你需要将它调整到你的硬件上(请不要让sqlFiddle屈膝!)。到目前为止的结果是事情继续有效,但查询计划根据我们运行的查询而有所不同(有或没有@x和@y)!