理解具有空值的SQL IN子句

理解具有空值的SQL IN子句,sql,oracle,sql-null,Sql,Oracle,Sql Null,假设下表: 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 | +--------

假设下表:

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' |        +---------+
+---------+
以下查询的结果与预期一致:

选择*FROM X,其中X_name在中选择y_name FROM y;将返回一行|蓝色|

从X中选择*其中X_名称不在y中选择y_名称;将返回一行|红色|

让我们在表Y中插入NULL:

INSERT INTO Y VALUES (NULL);
第一个查询将返回相同的结果。但是,上面的第二个查询将不返回任何行。为什么会这样?

不要在子查询中使用not in。时期使用不存在;它可以满足您的需求:

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实际上返回NULL,而不是false。但是,对于where子句和when子句,NULL被视为false,但对于check约束,NULL则被视为false。因此,该行被过滤掉

当您否定这一点时,可以是:

not x_name in ('a', 'b', null)
x_name not in ('a', 'b', null)
结果不是空的,也是空的,所有内容都被过滤掉

唉。在我看来,最简单的解决办法就是养成使用“不存在”的习惯