关于mysql的IN和NOT IN的危险

时间:2018-08-29 14:53:44

标签: mysql

我已经阅读了有关mysql的INNULL的文档。看这里: Subqueries with ANY, IN, or SOMESubqueries with ALL

我做了一些实验。

创建表(MySQL 5.6)

CREATE TABLE `test` (
  `uid` bigint(20) NOT NULL,
  PRIMARY KEY (`uid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO  test(uid) values (1),(2),(3),(4),(5);

statement1.1:

select 2 union all (select null);
+------+
|      |
+------+
|    2 |
| NULL |
+------+

statement1.2:

select uid from `test` where uid not in (select 2 union all (select null));  
+------+
|      |
+------+
|      |
+------+

statement1.3:

select uid from `test` where 1 not in (select 2 union all (select null));  
+------+
|      |
+------+
|      |
+------+

到目前为止,一切都已按计划完成。但是现在我们修改了该语句,发生了令人困惑的事情。

statement2.1:

select 2 union all (select null from test);
+------+
|      |
+------+
|   2  |
+------+
| NULL |
+------+
| NULL |
+------+
| NULL |
+------+
| NULL |
+------+
| NULL |
+------+

statement2.2:

select uid from `test` where uid not in (select 2 union all (select null from test));
+------+
|      |
+------+
|  3   |
+------+
|  4   |
+------+
|  5   |
+------+

statement2.3:

select uid from `test` where 1 not in (select 2 union all (select null from test)); 
+------+
|      |
+------+
|      |
+------+

statement2.4:

select uid from `test` where uid not in (select 3 union all (select null from test));
+------+
|      |
+------+
|  2   |
+------+
|  4   |
+------+
|  5   |
+------+

statement2.5:

select uid from `test` where 1 not in (select 3 union all (select null from test)); 
+------+
|      |
+------+
|      |
+------+

有人可以解释2.2、2.4吗?当我们使用表达式或常量作为操作数时,结果不一致?为什么1没有出现在2.2和2.4的结果中?看来2.3和2.5应该是正确的,如mysql的文档所述。

1 个答案:

答案 0 :(得分:0)

NOT IN带有返回NULL的子查询应始终返回0行。

相关:NOT IN clause and NULL values


它看起来像是个错误,在MySQL 8.0上无法重现。

查询:

select uid from test where uid not in (select 2 union all (select null));
select uid from test where 1 not in (select 2 union all (select null));
select uid from test where uid not in(select 2 union all (select null from test));
select uid from test where uid not in(select 3 union all (select null from test));
select uid from test where 1 not in (select 3 union all (select null from test));
-- 0 rows selected 

DBFiddle Demo