了解具有 NULL 值的 SQL IN 子句
Understanding SQL IN clause with NULL values
假设以下 tables:
CREATE TABLE X (x_name VARCHAR(100));
CREATE TABLE Y (y_name VARCHAR(100));
INSERT INTO X VALUES ('blue');
INSERT INTO X VALUES ('red');
INSERT INTO Y VALUES ('blue');
导致:
+---------+ +---------+
| Table X | | Table Y |
+---------+ +---------+
| x_name | | y_name |
+---------+ +---------+
| 'blue' | | 'blue' |
| 'red' | +---------+
+---------+
以下查询的结果符合预期:
SELECT * FROM X WHERE x_name IN (SELECT y_name FROM Y);
将 return 一行 | 'blue' |
.
SELECT * FROM X WHERE x_name NOT IN (SELECT y_name FROM Y);
将 return 一行 | 'red' |
.
让我们将 NULL
插入 table Y:
INSERT INTO Y VALUES (NULL);
第一个查询将 return 相同的结果 (blue
)。但是,上面的第二个查询将 return 没有行。这是为什么?
不要将 not in
用于子查询。时期。使用 not exists
;它做你想做的事:
select x.*
from x
where not exists (select 1 from y where y.y_name = x.x_name);
问题是这样的。当你有:
x_name in ('a', 'b', null)
SQL 实际上 returns NULL
,而不是 false
。但是,NULL
在 where
子句中被视为与 false
相同(和 when
子句但不适用于 check
约束)。因此,该行被过滤掉了。
当你否定这个时,可以是:
not x_name in ('a', 'b', null)
x_name not in ('a', 'b', null)
结果是 not NULL
,也是 NULL
,所有内容都被过滤掉了。
唉。在我看来,最简单的解决方案是养成使用 not exists
.
的习惯
假设以下 tables:
CREATE TABLE X (x_name VARCHAR(100));
CREATE TABLE Y (y_name VARCHAR(100));
INSERT INTO X VALUES ('blue');
INSERT INTO X VALUES ('red');
INSERT INTO Y VALUES ('blue');
导致:
+---------+ +---------+
| Table X | | Table Y |
+---------+ +---------+
| x_name | | y_name |
+---------+ +---------+
| 'blue' | | 'blue' |
| 'red' | +---------+
+---------+
以下查询的结果符合预期:
SELECT * FROM X WHERE x_name IN (SELECT y_name FROM Y);
将 return 一行| 'blue' |
.SELECT * FROM X WHERE x_name NOT IN (SELECT y_name FROM Y);
将 return 一行| 'red' |
.
让我们将 NULL
插入 table Y:
INSERT INTO Y VALUES (NULL);
第一个查询将 return 相同的结果 (blue
)。但是,上面的第二个查询将 return 没有行。这是为什么?
不要将 not in
用于子查询。时期。使用 not exists
;它做你想做的事:
select x.*
from x
where not exists (select 1 from y where y.y_name = x.x_name);
问题是这样的。当你有:
x_name in ('a', 'b', null)
SQL 实际上 returns NULL
,而不是 false
。但是,NULL
在 where
子句中被视为与 false
相同(和 when
子句但不适用于 check
约束)。因此,该行被过滤掉了。
当你否定这个时,可以是:
not x_name in ('a', 'b', null)
x_name not in ('a', 'b', null)
结果是 not NULL
,也是 NULL
,所有内容都被过滤掉了。
唉。在我看来,最简单的解决方案是养成使用 not exists
.