2 回答
TA贡献1946条经验 获得超4个赞
未定义聚合连接查询的正确行为。
为了实现聚合连接查询的预期结果,请将任何Transact-SQL函数或表达式应用于SELECT列表中的列,而不是ORDERBY子句中的列。
ORDER BY
出于向后兼容性的原因,SQLServer提供了对SELECT@p=@p+1类型赋值的支持.在最高的范围内订购。
[Expr1003] = Scalar Operator([@x]+[Expr1004])
@x = @x + [msg]
@x
我们不保证连接查询的正确性(比如使用变量赋值和特定顺序的数据检索)。SQL Server 2008中的查询输出可以根据计划选择、表中的数据等进行更改。即使语法允许您编写一个SELECT语句,将有序的行检索与变量赋值混合在一起,您也不应该一直依赖这种工作。
你所看到的行为是故意的。在带有ORDERBY子句的查询中使用赋值操作(在本例中为串联)具有未定义的行为。由于查询计划的更改,这可能在不同版本之间发生更改,甚至在特定的服务器版本中也会发生变化。即使有解决办法,也不能依赖这种行为。有关更多细节,请参见下面的KB文章: http://support.microsoft.com/kb/287515 唯一的保障机制如下:
使用游标按特定顺序遍历行,并将值连接起来。 用于带有Orderby的xml查询,以生成级联的值 使用CLR聚合(这不适用于ORDERBY子句)
你所看到的行为实际上是故意的。这与SQL是一种集操作语言有关。SELECT列表中的所有表达式(这也包括赋值)不能保证对每个输出行精确执行一次。实际上,SQL查询优化器试图尽可能少地执行它们。当您根据表中的某些数据计算变量的值时,这将给出预期的结果,但是当您要分配的值取决于同一变量的前一个值时,结果可能是非常出乎意料的。如果查询优化器将表达式移动到查询树中的不同位置,则可能会得到较少的计算次数(或者只得到一次,如您的一个示例所示)。这就是为什么我们不建议使用“迭代”类型赋值来计算聚合值的原因。我们发现基于XML的解决方案.通常为客户服务。
即使没有ORDERBY,我们也不能保证@var=@var+将为任何影响多行的语句生成级联值。表达式的右侧可以在查询执行期间计算一次或多次,而且正如我所说的行为依赖于计划。
带有SELECT语句的变量赋值是一种专有语法(仅为T-SQL),在这种语法中,行为是未定义的,如果产生多个行,则计划依赖。如果需要进行字符串连接,则使用SQLCLR聚合或用于基于XML查询的连接或其他关系方法。
添加回答
举报