MySQL两种WHERE语法执行差异疑问:为何子查询报错?
为什么
id=50 and (select 1 union select 2)会触发子查询报错? 这问题问得很到位!核心原因在于MySQL对两种不同条件的短路逻辑处理不一样,咱们一步步拆解来看:
先看语句1:select * from people where 0 and (select 1 union select 2)
这里的0是个确定的常量布尔值,MySQL在查询优化阶段一眼就能断定0 and 任何内容的结果都是false,所以直接跳过了后面的子查询,完全没执行它——这就是咱们常说的逻辑运算符短路的典型场景。
再看语句2:select * from people where id=50 and (select 1 union select 2)
这里的id=50虽然咱们知道表里没这条记录,但对MySQL的优化器来说,这不是一个能提前确定结果的常量条件:id是表中的列,优化器没办法在执行前就100%确定这个条件的结果是false,它需要走一遍条件判断的流程。
在这个过程中,MySQL不会直接触发短路跳过子查询,而是会尝试执行整个条件表达式,包括后面的(select 1 union select 2)。而这个子查询返回了两行数据,在and的条件语境下,MySQL要求子查询必须是标量子查询(只能返回单个值),所以就触发了ERROR 1242 (21000): Subquery returns more than 1 row的错误。
一句话总结:
- 当条件左边是确定的常量false时,MySQL优化器直接短路,不执行右边子查询
- 当条件左边是涉及表列的比较条件(哪怕实际结果是false),MySQL不会提前短路,会执行右边的子查询,进而触发报错
内容的提问来源于stack exchange,提问作者70M P0M
相关产品推荐
相关产品推荐

