奇怪的MySQL行为,似乎是一个SQL bug

Dan*_*ola 3 mysql

我在MySQL中遇到了一个非常奇怪的行为,看起来像某种奇怪的bug.我知道将这个经过试验和测试的工具归咎于一个人的错误是很常见的,但我已经讨论了一段时间了.

我有2个表,我有2797个记录,C有1429个.C引用I.
我想删除I中没有被C使用的所有记录,所以我正在做:

select * from i where id not in (select id_i from c);
Run Code Online (Sandbox Code Playgroud)

这会返回0条记录,考虑到每张表中的记录计数,这些记录在物理上是不可能的.我也很确定查询是正确的,因为它是我在过去2小时内使用的相同类型的查询,用于清理孤立记录的其他表.

让事情更奇怪......

select * from i where id in (select id_i from c);
Run Code Online (Sandbox Code Playgroud)

可以工作,并带给我1297条记录,我不想删除.
因此,IN工作,但不是IN.

更糟:

select * from i where id not in (
  select i.id from i inner join c ON i.id = c.id_i
);
Run Code Online (Sandbox Code Playgroud)

这可行,虽然它应该等同于第一个查询(我现在只是尝试疯狂的东西).
唉,我不能使用这个查询来删除,因为我正在使用我在子查询中删除的同一个表.

我假设我的数据库中的某些内容在此时已损坏.

如果它很重要,这些都是MyISAM表,没有任何外键,无论如何,我在我的开发机器和生产服务器中运行相同的查询,结果相同,所以无论什么腐败,都可能存在于mysqldump/source中周期,这听起来很奇怪.

关于可能出现什么问题的任何想法,或者更重要的是,我如何解决/解决这个问题?

谢谢!
丹尼尔

Mar*_*ers 9

我猜你有一行包含NULL值. IN并且NOT IN在存在NULL值时以您可能不期望的方式运行.从手册:

为了符合SQL标准,IN不仅在左侧的表达式为NULL时返回NULL,而且如果在列表中找不到匹配且列表中的一个表达式为NULL,则返回NULL.

价值NOT NULL仍然NULL如你所希望的那样真实.

以下是一个简化示例的行为演示:

CREATE TABLE c (id_i INT NULL);
INSERT INTO c (id_i) VALUES
(1),
(2),
(NULL);

CREATE TABLE i (id INT NOT NULL);
INSERT INTO i (id) VALUES
(1),
(2),
(3);

SELECT * FROM i WHERE id NOT IN (SELECT id_i FROM c); -- returns nothing
SELECT * FROM i WHERE id IN (SELECT id_i FROM c);     -- returns 1,2
SELECT * FROM i WHERE id NOT IN (                     -- returns 3
  SELECT i.id FROM i INNER JOIN c ON i.id = c.id_i
);
Run Code Online (Sandbox Code Playgroud)

  • @Daniel - `NOT IN(...,NULL)`总是不返回任何东西.要理解为什么会出现这种情况,请参阅此链接http://www.simple-talk.com/sql/learn-sql-server/sql-and-the-snare-of-three-valued-logic/ (2认同)