1

MySQL 手册中,不能保证以下查询的输出始终相同。

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

引用手册:

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

我想知道背后的故事。

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

4

3 回答 3

0

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

为什么?SQL 标准不要求计算的顺序,因此每个数据库都可以自由决定如何计算表达式。通常,此类决定留给优化器。

于 2016-08-12T17:46:26.933 回答
0

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


几乎所有你看到的和你一样的代码都有未定义的行为。一些明智的人通过运营商和优化的实现代码演示了特定实现的实际作用。但是下一个版本不能依赖这种行为。

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

于 2017-06-25T22:51:55.940 回答
-1

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

于 2016-08-12T18:38:16.357 回答