代码之家  ›  专栏  ›  技术社区  ›  DOOManiac

MySQL是否对if()函数短路?

  •  5
  • DOOManiac  · 技术社区  · 14 年前

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

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

    A、B和C条件几乎总是错误的,所以我认为子查询永远不会对结果集中的大多数行执行,因此比联接快得多。但只有当if()语句短路时,这才是正确的。

    是吗?

    谢谢你们提供的帮助。

    4 回复  |  直到 11 年前
        1
  •  8
  •   J Jorgenson    14 年前

    答案是肯定的。
    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”。

    这是因为在select 1中从未执行“true”表达式,也不是为select 2执行的false表达式。

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

    --乔根森--

        2
  •  2
  •   DOOManiac    14 年前

    在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的帮助!

        3
  •  0
  •   Scott Stafford    14 年前

    在SQL分析器中进行尝试。如果您希望站在安全的一边,并且不必相信数据库以一种方式工作(并且在新版本中不必更改这种行为),只需进行两次查询并以编程方式执行if。

        4
  •  0
  •   waded Mykola Yashchenko    11 年前

    这要看情况而定。

    如果没有短路,则可以使用它来避免使用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()
    

    这与使用较少的组concat表达式(如distinct key)以及完全不使用if时得到的警告相同。