MySQL关于exists的一个bug
今天碰到一个关于exists很奇怪的问题
第一个语句如下:
SELECT count(1) FROM APPLYt WHERE EXISTS( SELECT r.APPLY_ID FROM RECORDr WHERE t.APPLY_ID=r.APPLY_ID );
产生的结果是:89584
第二个语句如下:
SELECT count(1) FROM APPLYt WHERE EXISTS( SELECT max(r.FINISH_TIME) FROM RECORDr WHERE t.APPLY_ID=r.APPLY_ID );
产生的结果是:432382
确实相当奇怪,对于exist子句来说,其判断的是子查询的值是否存在,也就是说,列名,和对列名求最大值没什么区别啊。
包括MySQL官方文档中也提到
Traditionally,anEXISTSsubquerystartswithSELECT*,butitcouldbeginwithSELECT5orSELECTcolumn1oranythingatall.MySQLignorestheSELECTlistinsuchasubquery,soitmakesnodifference.
大意就是MySQL会自动忽略到SELECT的列表。
后来在自己的环境测试了一下,确实是MySQL的一个bug
测试环境:MySQL5.6.31,5.7.14
mysql>createtablet3(idint,tdatetime); QueryOK,0rowsaffected(0.44sec) mysql>insertintot3values(1,'20160812'); QueryOK,1rowaffected(0.16sec) mysql>select1fromdualwhereexists(selectidfromt3whereid=2); Emptyset(0.15sec) mysql>select1fromdualwhereexists(selectmax(id)fromt3whereid=2); +---+ |1| +---+ |1|
很明显,id等于2的列不存在,但是第二条语句还是当做TRUE来处理了。
也确认了下两条语句的执行计划和改写后的SQL
第一个语句
mysql>EXPLAINEXTENDEDselect1fromdualwhereexists(selectidfromt3whereid=2); +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+------------------+ |id|select_type|table|partitions|type|possible_keys|key|key_len|ref|rows|filtered|Extra| +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+------------------+ |1|PRIMARY|NULL|NULL|NULL|NULL|NULL|NULL|NULL|NULL|NULL|ImpossibleWHERE| |2|SUBQUERY|t3|NULL|ALL|NULL|NULL|NULL|NULL|1|100.00|Usingwhere| +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+------------------+ 2rowsinset,2warnings(0.00sec) mysql>showwarnings; +---------+------+-------------------------------------------------------------------+ |Level|Code|Message| +---------+------+-------------------------------------------------------------------+ |Warning|1681|'EXTENDED'isdeprecatedandwillberemovedinafuturerelease.| |Note|1003|/*select#1*/select1AS`1`fromDUALwhere0| +---------+------+-------------------------------------------------------------------+
第二个语句
mysql>EXPLAINEXTENDEDselect1fromdualwhereexists(selectmax(id)fromt3whereid=2); +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+----------------+ |id|select_type|table|partitions|type|possible_keys|key|key_len|ref|rows|filtered|Extra| +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+----------------+ |1|PRIMARY|NULL|NULL|NULL|NULL|NULL|NULL|NULL|NULL|NULL|Notablesused| |2|SUBQUERY|t3|NULL|ALL|NULL|NULL|NULL|NULL|1|100.00|Usingwhere| +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+----------------+ 2rowsinset,2warnings(0.00sec) mysql>showwarnings; +---------+------+-------------------------------------------------------------------+ |Level|Code|Message| +---------+------+-------------------------------------------------------------------+ |Warning|1681|'EXTENDED'isdeprecatedandwillberemovedinafuturerelease.| |Note|1003|/*select#1*/select1AS`1`fromDUALwhere1| +---------+------+-------------------------------------------------------------------+ 2rowsinset(0.00sec)
执行计划及改写后的SQL确实有所不同,看来,确实是MySQL的一个bug了。
于是,给官方提了个bug
http://bugs.mysql.com/bug.php?id=82562
总结
建议写exists语句时,子查询中直接用*,而不用对列进行任何函数操作,避免碰到官方bug,
事实上,对于abs,floor函数又没问题
mysql>select1fromdualwhereexists(selectabs(id)fromt3whereid=2); Emptyset(0.07sec) mysql>select1fromdualwhereexists(selectfloor(id)fromt3whereid=2); Emptyset(0.00sec)
以上所述是小编给大家介绍的MySQL关于exists的一个bug,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对毛票票网站的支持!