由于mysql是一种声明性语言,我找不到一种方法来强制赋值变量顺序。
以这个查询为例:
SET @v1=0;
SET @v2=0;
SELECT @v1, @v2
FROM MyTable table
WHERE (@v1:=@v2) is not null
AND (@v2:=2) is not null;结果是:
@v1 | @v2
---------
2 | 2这是因为mysql引擎在@v1之前解析了@v2。
如何强制赋值顺序产生此结果:
@v1 | @v2
---------
0 | 2编辑:这与以下问题不同:Variable assignment with mysql
这是一个关于强制赋值顺序的问题,而不是为什么结果不是预期的结果。
更新:使用left outer join时,结果也很奇怪:
SET @v1=0;
SELECT @v1
FROM Account other
LEFT OUTER JOIN SimpleValue f_PC ON f_PC.accountId=other.id AND f_PC.refShortcut='PC'
WHERE CASE WHEN (other.context='44') THEN (@v1:=@v1+1) ELSE null END
ORDER BY @v1 ASC在本例中,查询返回60个结果,但@v1值为120。
如果删除左外部连接,则v1值为60。为什么?
发布于 2011-02-08 04:21:25
在select语句中,子句从左到右,从上到下,因此它的工作方式与预期一致(MS Access使用相同的策略)。然而,在WHERE子句中,所有的投注都是关闭的,并选择最佳的过滤器。您可以通过利用CASE语句需要从左到右求值(保持表示顺序)这一事实来强制它。
WHERE CASE WHEN (@v1:=@v2) is not null THEN (@v2:=2) ELSE (@v2:=2) = 0 END此强制在任一分支中求值(并将2赋值给@v2),但仅在第一次运行时,@v1:=@v2返回null,并且@v2变为2,与总体FALSE的0进行比较。第二次,@v1 := @v2 [= 2]和(@v2:=2)的结果是2(即true)。
发布于 2011-02-08 01:51:24
正如在回答你的另一个问题时所解释的那样,没有什么是可以保证工作的。
在您的特定情况下,将赋值移动到查询的选择部分似乎是可行的:
SET @v1=0;
SET @v2=0;
SELECT (@v1:=@v2), (@v2:=2)
FROM DUAL发布于 2019-12-31 21:49:40
关于你的例子的。
在WHERE子句的逻辑运算符中,常量操作可能具有最高的优先级。
SET @v1=10;
SET @v2=20;
SELECT @v1, @v2
FROM dual
WHERE (@v2:=2) is not NULL AND (@v1:=@v2) is not NULL;
=======
@v1 @v2
2 2
SET @v1=30;
SET @v2=40;
SELECT @v1, @v2
FROM dual
WHERE (@v1:=@v2) is not NULL AND (@v2:=2) is not NULL;
========
@v1 @v2
2 2下面的例子清楚地证明了这一点。OR语句不是按照建议的从左到右执行的。OR运算符首先执行常量赋值操作。
SET @v1=10;
SET @v2=20;
SELECT @v1, @v2
FROM dual
WHERE (@v2:=3) is not NULL OR (@v1:=@v2+1) is not NULL;
=========
@v1 @v2
10 3
SET @v1=30;
SET @v2=40;
SELECT @v1, @v2
FROM dual
WHERE (@v1:=@v2+2) is not NULL OR (@v2:=4) is not NULL;
=========
@v1 @v2
30 4关于赋值运算符和关于问题
在本例中,查询返回60个结果,但@v1的值为120。如果删除左外部连接,则v1值为60。为什么?
WHERE子句中的赋值操作符":=“是为查询中使用的数据集的每一行计算出来的!反之亦然,在SELECT子句中,计算出了结果行的赋值运算符,这肯定地验证了JOIN和WHERE子句中的检查。
Recommendation.尝试不要在WHERE子句中使用赋值运算符":=“。在SELECT子句中使用赋值运算符。
https://stackoverflow.com/questions/4924353
复制相似问题