为啥我可以从 NULL 列的左连接中选择一些东西?(用人为的例子在本地重现它,可能是一个错误!)
Posted
技术标签:
【中文标题】为啥我可以从 NULL 列的左连接中选择一些东西?(用人为的例子在本地重现它,可能是一个错误!)【英文标题】:Why can I select something out of left join on a NULL column?(with contrived example to reproduce it locally,probably a bug!)为什么我可以从 NULL 列的左连接中选择一些东西?(用人为的例子在本地重现它,可能是一个错误!) 【发布时间】:2009-10-04 15:15:02 【问题描述】:版本 我正在使用服务器版本:5.1.36-community-log mysql Community Server (GPL)
我终于设计了一个简单的例子来轻松重现它!
设置:
create table t1(id integer unsigned,link integer unsigned);
create table t2(id integer unsigned auto_increment,primary key(id));
create table t3(id integer unsigned,content varchar(30));
insert into t1 value(1,null);
insert into t2 value(1);
insert into t3 value(1,'test');
然后运行:
select t2.*,t3.*
from t1
left join t2 on t1.link=t2.id
left join t3 on t3.id=t2.id
where t1.id=1;
会弄错:
+------+------+---------+
| id | id | content |
+------+------+---------+
| NULL | 1 | test |
+------+------+---------+
但如果我们以这种方式创建 t2,它就不会发生:
create table t2(id integer unsigned);
所以,它与主键有关!
新发现
运行这个不会触发bug:
select t2.*,t3.*
from t1
left join t2 on t1.link=t2.id
left join t3 on t2.id=t3.id
where t1.id=1;
所以它也与加入方向有关!
【问题讨论】:
其余的表是什么样子的? 连接是否有可能被优化?对查询运行解释以查看会发生什么... 请不要显示您的查询结果,而是向我们展示您所有的表格及其各自的内容! 我太兴奋了,不能成功地设计一个例子! 你有一个错字 - 你已经创建了 t2 两次。此外,为了一致性和可读性,与 t3 的连接最好写为 t2.id = t3.id,而不是相反(在我看来) 【参考方案1】:我刚刚在 MySQL 5.0.58、5.0.82 和 5.1.35 上运行你创建、插入和选择,我收到了以下结果,我认为这是正确的:
+------+------+---------+
| id | id | content |
+------+------+---------+
| NULL | NULL | NULL |
+------+------+---------+
这正是我使用的:
CREATE TABLE `t1` (
`id` int(10) unsigned default NULL,
`link` int(10) unsigned default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
INSERT INTO `t1` VALUES (1, NULL);
CREATE TABLE `t2` (
`id` int(10) unsigned NOT NULL auto_increment,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 ;
INSERT INTO `t2` VALUES (1);
CREATE TABLE `t3` (
`id` int(10) unsigned default NULL,
`content` varchar(30) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
INSERT INTO `t3` VALUES (1, 'test');
SELECT t2.id, t3.id, t3.content
FROM t1
LEFT JOIN t2 ON t1.link = t2.id
LEFT JOIN t3 ON t2.id = t3.id
WHERE t1.id = 1;
【讨论】:
哦,那一定是服务器版本引入的bug:5.1.36-community-log MySQL Community Server (GPL) 我怀疑在 5.1.35 和 5.1.36 之间他们会引入那么大的错误。您是否确认您的 SQL 与您发布的内容(以及我发布的内容)相匹配? 太棒了!我进一步发现它是由连接方向引起的!请运行:select t2.*,t3.* from t1 left join t2 on t1.link=t2.id left join t3在 t3.id=t2.id 上 t1.id=1; 都不会为我产生错误。 你能在其他版本的 MySQL 上安装或测试吗?【参考方案2】:'fuinfo' 中的'fid' 行之一是否设置为 NULL? MySQL 可能会将其与左表中的 NULL 值连接起来。
【讨论】:
但它没有设置为NULL,这里设置为“Tiger”! fuinfo.name 设置为“Tiger”,但它可能与 lefId 为 NULL 的答案中的一行配对。 但我已将连接条件指定为:ON f.id = a.lefId 是的,但是否有任何 f.id 字段设置为 NULL?我在想 MySQL 可以将 NULL 与 NULL 匹配。 不,只有一行,id为1。【参考方案3】:非常有趣。这确实看起来像 MySQL 中的一个错误。查询结果取决于是否有主键。他们绝对不应该影响结果。作为参考,PostgreSQL 将返回带有主键的正确结果,所以我认为这不太可能是预期的行为。
【讨论】:
我可以因报告或发现错误而获得报酬吗?【参考方案4】:您的设置代码错误
create table t1(id integer unsigned,link integer unsigned);
create table t2(id integer unsigned auto_increment,primary key(id));
create table t2(id integer unsigned,content varchar(30));
^^ This is wrong. Should be t3
另外,请确保在每次测试后放下表格。你可能有一些错误的数据。
【讨论】:
打错了,请在本地尝试一下,你肯定会遇到同样的问题! 它在 MSSQL 中运行正常,也许您应该在标题或正文中指定您的 DBMS,而不仅仅是标签。 我不喜欢被重复! Alex,通常只在标签中指定它。放在体内是个好主意,但绝对没有必要。以上是关于为啥我可以从 NULL 列的左连接中选择一些东西?(用人为的例子在本地重现它,可能是一个错误!)的主要内容,如果未能解决你的问题,请参考以下文章
如何从访问数据库中的左连接中选择excel表 - EXCEL VBA