为什么涉及用户变量的表达式的评估顺序未定义?

时间:2016-08-12 17:39:37

标签: mysql sql operator-precedence mysql-variables

MySQL Manual开始,以下查询的输出不能保证始终相同。

SET @a := 0;

SELECT 
@a AS first,
@a := @a + 1 AS second,
@a := @a + 1 AS third,
@a := @a + 1 AS fourth,
@a := @a + 1 AS fifth,
@a := @a + 1 AS sixth;

输出:

first second third fourth fifth sixth 
  0     1      2     3     4      5

引自手册:

  

但是,涉及用户的表达式的评估顺序   变量未定义;

我想知道背后的故事。

所以我的问题是: 为什么涉及用户变量的表达式的评估顺序是未定义的?

3 个答案:

答案 0 :(得分:0)

select中表达式的评估顺序未定义。在大多数情况下,只有在有变量时才会注意到这一点,因为错误会导致错误的信息。

为什么呢? SQL标准不需要评估顺序,因此每个数据库都可以自由决定如何评估表达式。通常,此类决策由优化程序决定。

答案 1 :(得分:0)

这取决于数据库的优化程序的决定。这就是为什么它不确定的原因。但大多数优化器决定了我们预测结果的方式。

答案 2 :(得分:0)

TL; DR MySQL用户定义的变量不打算以这种方式使用。 SQL语句描述结果集,而不是一系列操作。文档不清楚变量赋值甚至意味着什么。但是你不能同时读写变量。并且未定义SELECT子句中的赋值顺序。您可以假设,外部SELECT子句中的赋值是针对某个输出行完成的。

您看到的几乎所有代码都有未定义的行为。一些明智的人通过运营商的实施代码证明了这一点。优化特定实现的实际功能。但是下一个版本不能依赖这种行为。

阅读documentation。读取和写入相同的变量是不确定的。当它没有完成时,任何变量读取都在一个语句中修复。没有命令分配。对于仅具有DETERMINISTIC函数的SELECT(其值由参数值确定),结果由概念评估执行定义。但是它与用户变量之间没有联系。分配永远的含义并不明确:文档说“每个选择表达式仅在发送给客户端时才会被评估”。这似乎是说除了在每个最外层的SELECT子句中将放入结果集之外,不能保证行被“选中”。未定义SELECT中的赋值顺序。甚至如果如果分配在概念上为每一行完成,那么它们只能依赖于行值,因此相同表示赋值仅执行一次,对于某些行。由于未定义赋值顺序,因此该行可以是任何行。因此,假设这就是文档的含义,您可以期待的是,如果您不在SELECT语句中读取和写入相同的变量,那么最外层SELECT中的每个变量赋值都会以某种顺序发生在一个输出行中