MySQL是否使IF()函数短路?

时间:2010-09-14 21:35:32

标签: mysql short-circuiting

我需要查询第二个表中的数据,但前提是满足主表中一组罕见的条件:

SELECT ..., IF(a AND b AND c AND (SELECT 1 FROM tableb ...)) FROM tablea ...

a,b和c条件几乎总是假的,所以我的想法是子查询永远不会对结果集中的大多数行执行,因此比连接更快。但只有当IF()语句短路时才会这样。

是吗?

感谢您提供任何帮助。

4 个答案:

答案 0 :(得分:8)

答案是肯定的 mysql查询中的IF(cond,expr_true,expr_false)被短路。

这是一个测试,使用@variables来证明这一事实:

SET @var:=5;  
SELECT IF(1 = 0, (@var:=@var + 1), @var ); -- using ':=' operator to modify 'true' expr @var 
SELECT IF(1 = 1, @var, (@var:=@var + 1) ); -- using ':=' operator to modify 'false' expr @var 
SELECT @var;

所有三个SELECT查询的结果都是'5'。

如果IF()函数没有短路,结果将是SELECT#1的'5'和SELECT#2的'6',以及最后一个'select @var'的'7'。

这是因为'true'表达式永远不会执行,在select#1中,也不是为select#2执行的false表达式。

注意':='运算符用于在SQL查询(select,from和where子句)中修改@var。你可以从中获得一些非常奇特/复杂的SQL。我已经使用@vars在SQL查询中应用'程序'逻辑。

- J Jorgenson -

答案 1 :(得分:2)

在J. Jorgenson的帮助下,我提出了自己的测试用例。他的例子不会尝试在条件评估中短路,但是使用他的想法我想出了我自己的测试并验证了MySQL确实使IF()条件检查短路。

SET @var:=5;
SELECT IF(1 = 0 AND (@var:=10), 123, @var); #Expected output: 5
SELECT IF(1 = 1 AND (@var:=10), @var, 123); #Expected output: 10

在第二个例子中,MySQL正确地短路:@var永远不会被设置为10。

感谢J. Jorgenson的帮助!

答案 2 :(得分:0)

在SQL分析器中尝试。如果你想要安全,不必信任数据库以单向工作(而不是在新版本中改变那种行为),只需进行两次查询并以编程方式执行IF。

答案 3 :(得分:0)

取决于。

IF不会短路,以便可以使用GROUP_CONCAT来避免截断警告,例如:

set @@group_concat_max_len = 5;

select if(true or @var:=group_concat('warns if evaluated'), 'actual result', @var);

结果将是'实际结果'但是你会收到警告:

Warning (Code 1260): Row 1 was cut by GROUP_CONCAT()

这与使用不那么简单的GROUP_CONCAT表达式(例如不同的键)以及根本没有IF的警告相同。