如果我在MySQL 5.7.16上执行以下查询,那么结果集包含一行值为2
的行,这是预期的:
SELECT *
FROM (SELECT 1 as x UNION SELECT 2 UNION SELECT 3) AS t
WHERE ( 2 IS NULL OR t.x = 2 )
;
-- Resultset: 1 row, x = 2
现在,我想在准备好的语句中使用这个逻辑,比如? IS NULL OR t.x = ?
。所以你看到相同的参数出现两次。因此,我应用了我在SO上找到的建议(我不记得确切位置):将参数放在MySQL会话变量中,然后使用它:
SELECT *
FROM (SELECT 1 as x UNION SELECT 2 UNION SELECT 3) AS t
WHERE ( (@x := 2) IS NULL OR t.x = @x )
;
-- Resultset: 0 row
但是失败了:没有返回任何行。当我还选择@x
变量时,为了查看正在进行的操作,我得到NULL
的{{1}}值:
@x
因此,当放入SELECT @x
FROM (SELECT 1 as x UNION SELECT 2 UNION SELECT 3) AS t
WHERE ( (@x := 2) IS NULL OR t.x = 2 )
;
-- Resultset: 1 row, @x = NULL
时,似乎没有设置变量?到底是怎么回事?
我可以在WHERE
内制作INNER JOIN (SELECT 2 AS x) AS params
并使用params.x
,但我想了解WHERE
中发生了什么。
答案 0 :(得分:1)
这里发生的事情是WHERE
内的执行顺序是任意。这意味着使用
(@x := 2) IS NULL OR t.x = 2
无法保证首先执行@x := 2
。
要正确初始化变量,请使用CROSS JOIN
:
SELECT *
FROM (SELECT 1 as x UNION SELECT 2 UNION SELECT 3) AS t
CROSS JOIN (SELECT @x := 2) AS v
WHERE ( @x IS NULL OR t.x = @x )