为了尝试自己解决这个问题,我进行了大量的搜索和故障排除。
我的情况是,我已经将主机从 Debian Lenny(5.0-ish)更新为 Debian Squeeze(MySQL 5.1.49),并且之前返回预期结果的工作查询现在返回一个空集。
所以这里继续介绍背景。为了查看数据是否有问题,我对数据库进行了mysqldump。然后我将其复制到我的开发机器(Mac OS X 10.6.8,通过 Homebrew 安装了 MySQL)并在那里设置数据库。查询返回了预期的结果!
该代码基于开源应用程序,因此我返回并在 Lenny 主机上进行了全新安装和数据库引导。我确认查询返回了预期的结果。
我还在 Squeeze 上全新安装了应用程序(未升级的主机)。开源应用程序 Squeeze 上的全新安装按预期工作。
我从 Lenny 上全新安装的应用程序中执行了 mysqldump。然后,我在干净的 Squeeze 主机上创建了一个新数据库并将 Lenny 转储加载到其中。查询不再返回预期的结果。与数据库升级到 Squeeze 的情况相同。
这里描述了数据的情况。
首先是表格:
mysql> describe roles;
+-------------------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------------+-------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(40) | YES | | NULL | |
| authorizable_type | varchar(30) | YES | | NULL | |
| authorizable_id | int(11) | YES | | NULL | |
| created_at | datetime | YES | | NULL | |
| updated_at | datetime | YES | | NULL | |
+-------------------+-------------+------+-----+---------+----------------+
mysql> describe roles_users;
+------------+----------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------+----------+------+-----+---------+-------+
| user_id | int(11) | YES | MUL | NULL | |
| role_id | int(11) | YES | MUL | NULL | |
| created_at | datetime | YES | | NULL | |
| updated_at | datetime | YES | | NULL | |
+------------+----------+------+-----+---------+-------+
4 rows in set (0.00 sec)
您猜对了,这些来自大约 Rails 2.1ish 的授权插件。现在由此时已升级到 Rails 2.3.5 的应用程序使用。
我已经验证了两台主机上的表描述是相同的。
下一个数据:
mysql> select * from roles where id = 1;
+----+------------+-------------------+-----------------+---------------------+---------------------+
| id | name | authorizable_type | authorizable_id | created_at | updated_at |
+----+------------+-------------------+-----------------+---------------------+---------------------+
| 1 | site_admin | Basket | 1 | 2009-05-27 00:14:22 | 2009-05-27 00:14:22 |
+----+------------+-------------------+-----------------+---------------------+---------------------+
1 row in set (0.00 sec)
mysql> select * from roles_users where role_id = 1 and user_id = 1;
+---------+---------+---------------------+---------------------+
| user_id | role_id | created_at | updated_at |
+---------+---------+---------------------+---------------------+
| 1 | 1 | 2009-05-27 00:14:22 | 2009-05-27 00:14:22 |
+---------+---------+---------------------+---------------------+
1 row in set (0.00 sec)
同样,两个主机返回相同的结果。
这是预期返回的查询(由授权插件构建以验证用户在系统中的正确对象上具有正确的角色):
mysql> SELECT `roles`.id FROM `roles` INNER JOIN `roles_users` ON `roles`.id = `roles_users`.role_id WHERE (`roles`.`id` = 1 ) AND ((`roles_users`.user_id = 1 )) LIMIT 1 ;
SELECT `roles`.id FROM `roles` INNER JOIN `roles_users` ON `roles`.id = `roles_users`.role_id WHERE (`roles`.`id` = 1 ) AND ((`roles_users`.user_id = 1 )) LIMIT 1 ;
+----+
| id |
+----+
| 1 |
+----+
1 row in set (0.00 sec)
又是在 Debian Squeeze 主机上,返回空集:
mysql> SELECT `roles`.id FROM `roles` INNER JOIN `roles_users` ON `roles`.id = `roles_users`.role_id WHERE (`roles`.`id` = 1 ) AND ((`roles_users`.user_id = 1 )) LIMIT 1 ;
Empty set (0.00 sec)
有什么想法吗?还有其他人遇到过这种情况吗?
更新评论请求的结果:
这里没有 LIMIT 1:
mysql> SELECT `roles`.id FROM `roles` INNER JOIN `roles_users` ON `roles`.id = `roles_users`.role_id WHERE (`roles`.`id` = 1 ) AND ((`roles_users`.user_id = 1 ));
Empty set (0.00 sec)
此处从 where 子句中删除 roles_users.user_id = 1:
mysql> SELECT `roles`.id FROM `roles` INNER JOIN `roles_users` ON `roles`.id = `roles_users`.role_id WHERE `roles`.`id` = 1 ;
+----+
| id |
+----+
| 1 |
...
3 rows in set (0.00 sec)
这是上面的查询,但在选择中显示了 roles_users.user_id:
mysql> SELECT `roles`.id, `roles_users`.user_id FROM `roles` INNER JOIN `roles_users` ON `roles`.id = `roles_users`.role_id WHERE `roles`.`id` = 1 ;
+----+---------+
| id | user_id |
+----+---------+
| 1 | 1 |
...
3 rows in set (0.00 sec
最后是从 where 子句中删除 roles.id,但保留 roles_users.user_id:
mysql> SELECT `roles`.id, `roles_users`.user_id FROM `roles` INNER JOIN `roles_users` ON `roles`.id = `roles_users`.role_id WHERE `roles_users`.user_id = 1;
+----+---------+
| id | user_id |
+----+---------+
...
| 1 | 1 |
...
9 rows...
最佳答案
我已经找到导致此问题发生在 Debian Squeeze MySQL 5.1.49 上的根本原因;当 roles_users 表的 role_id 有多个不同的 user_id 时,查询将返回一个空集。
即如果我有这个:
mysql> SELECT `roles_users`.role_id, `roles_users`.user_id FROM `roles` INNER JOIN `roles_users` ON `roles`.id = `roles_users`.role_id order by role_id;
+---------+---------+
| role_id | user_id |
+---------+---------+
| 1 | 1 |
| 2 | 1 |
| 3 | 1 |
| 4 | 1 |
| 5 | 1 |
| 6 | 2 |
+---------+---------+
6 rows in set (0.01 sec)
我得到了我所期望的:
mysql> SELECT `roles`.id FROM `roles` INNER JOIN `roles_users` ON `roles`.id = `roles_users`.role_id WHERE (`roles`.`id` = 1) AND ((`roles_users`.user_id = 1)) LIMIT 1;
+----+
| id |
+----+
| 1 |
+----+
1 row in set (0.00 sec)
但是当我有这个时(一个附加的 user_id 有 role_id 1):
mysql> SELECT `roles_users`.role_id, `roles_users`.user_id FROM `roles` INNER JOIN `roles_users` ON `roles`.id = `roles_users`.role_id order by role_id;
+---------+---------+
| role_id | user_id |
+---------+---------+
| 1 | 1 |
| 1 | 5 |
| 2 | 1 |
| 3 | 1 |
| 4 | 1 |
| 4 | 5 |
| 5 | 1 |
| 6 | 2 |
+---------+---------+
8 rows in set (0.00 sec)
我明白了:
mysql> SELECT `roles`.id FROM `roles` INNER JOIN `roles_users` ON `roles`.id = `roles_users`.role_id WHERE (`roles`.`id` = 1 ) AND ((`roles_users`.user_id = 1 )) LIMIT 1 ;
Empty set (0.00 sec)
所以有两种可能。
与该数据集(多个具有相同 role_id 的 user_id)一起工作的查询始终无效,并且 MySQL 5.0.51a-24+lenny4 无论如何都可以使用它,即使它不应该有或有一个MySQL 5.1.49-3 (Debian) 中的错误。
我将在论坛上报告 MySQl 的错误并查看我得到的响应。
关于sql - 查询返回空集 Mysql 5.1.49 但返回 5.0-ish 上的内容,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7102799/