ICode9

精准搜索请尝试: 精确搜索
首页 > 数据库> 文章详细

MySQL返回不正确的数据?

2019-06-10 12:13:33  阅读:141  来源: 互联网

标签:mysql sql myisam


最近,Django社区出现了一个关于MySQL测试的问题(使用MyISAM).

这是django门票:http://code.djangoproject.com/ticket/14661

其中一个Django核心开发人员提出了这个测试,我们中的许多人都能够复制它.任何人都猜到我们在这里遇到了什么?它只是MySQL中的一个错误还是我错过了什么?

这是测试代码和查询:

DROP TABLE IF EXISTS `testapp_tag`;
CREATE TABLE `testapp_tag` (
    `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
    `name` varchar(10) NOT NULL,
    `parent_id` integer
);
INSERT INTO `testapp_tag` (`name`, `parent_id`) VALUES ("t1", NULL);
INSERT INTO `testapp_tag` (`name`, `parent_id`) VALUES ("t2", 1);
INSERT INTO `testapp_tag` (`name`, `parent_id`) VALUES ("t3", 1);
INSERT INTO `testapp_tag` (`name`, `parent_id`) VALUES ("t4", 3);
INSERT INTO `testapp_tag` (`name`, `parent_id`) VALUES ("t5", 3);
SELECT `testapp_tag`.`id`, `testapp_tag`.`name`, `testapp_tag`.`parent_id` FROM `testapp_tag` WHERE NOT ((`testapp_tag`.`id` IN (SELECT U0.`id` FROM `testapp_tag` U0 LEFT OUTER JOIN `testapp_tag` U1 ON (U0.`id` = U1.`parent_id`) WHERE U1.`id` IS NULL) AND `testapp_tag`.`id` IS NOT NULL)) ORDER BY `testapp_tag`.`name` ASC;
SELECT `testapp_tag`.`id`, `testapp_tag`.`name`, `testapp_tag`.`parent_id` FROM `testapp_tag` WHERE NOT ((`testapp_tag`.`id` IN (SELECT U0.`id` FROM `testapp_tag` U0 LEFT OUTER JOIN `testapp_tag` U1 ON (U0.`id` = U1.`parent_id`) WHERE U1.`id` IS NULL) AND `testapp_tag`.`id` IS NOT NULL)) ORDER BY `testapp_tag`.`name` ASC;

这是输出:

mysql> SELECT `testapp_tag`.`id`, `testapp_tag`.`name`, `testapp_tag`.`parent_id` FROM `testapp_tag` WHERE NOT ((`testapp_tag` .`id` IN (SELECT U0.`id` FROM `testapp_tag` U0 LEFT OUTER JOIN `testapp_tag` U1 ON (U0.`id` = U1.`parent_id`) WHERE U1.`id` IS  NULL) AND `testapp_tag`.`id` IS NOT NULL)) ORDER BY `testapp_tag`.`name` ASC;
+----+------+-----------+
| id | name | parent_id |
+----+------+-----------+
|  1 | t1   |      NULL |
|  3 | t3   |         1 |
|  5 | t5   |         3 |
+----+------+-----------+
3 rows in set (0.00 sec)

mysql> SELECT `testapp_tag`.`id`, `testapp_tag`.`name`, `testapp_tag`.`parent_id` FROM `testapp_tag` WHERE NOT ((`testapp_tag` .`id` IN (SELECT U0.`id` FROM `testapp_tag` U0 LEFT OUTER JOIN `testapp_tag` U1 ON (U0.`id` = U1.`parent_id`) WHERE U1.`id` IS NULL) AND `testapp_tag`.`id` IS NOT NULL)) ORDER BY `testapp_tag`.`name` ASC;
+----+------+-----------+
| id | name | parent_id |
+----+------+-----------+
|  1 | t1   |      NULL |
|  3 | t3   |         1 |
+----+------+-----------+
2 rows in set (0.01 sec)

解决方法:

看起来非常有趣,看起来像是MySql查询优化器中的一个bug.

如果你运行它而不是普通选择:

EXPLAIN EXTENDED SELECT `testapp_tag`.`id`, ....;
SHOW WARNINGS;
EXPLAIN EXTENDED SELECT `testapp_tag`.`id`, ...;
SHOW WARNINGS;

然后,比较EXPLAIN EXTENDED警告的输出,您可以看到第一次,优化器添加到选择:

or (`test`.`testapp_tag`.`id` = 5)

另外,请注意从WHERE中删除AND testapp_tag.id IS NOT NULL,因为该字段被标记为NOT NULL,它什么都不做,似乎可以解决这个问题.

标签:mysql,sql,myisam
来源: https://codeday.me/bug/20190610/1211864.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有