当集合为空时如何理解“NULL NOT IN”?

Jus*_*ner 3 null oracle sql-server

这个问题中的 SQL 是针对 Oracle 的。但是您可以简单地删除FROM dual以使其在 SQL Server 上工作(它返回与 Oracle 相同的结果)。

我有以下 SQL:

SELECT 1
FROM dual
WHERE NULL IN (SELECT 1 FROM dual WHERE 1 = 0);

SELECT 1
FROM dual
WHERE NULL NOT IN (SELECT 1 FROM dual WHERE 1 = 0);
Run Code Online (Sandbox Code Playgroud)

它分别返回一个空集和 1。当我们用其他值代替 时NULL,我们得到了完全相同的结果。

SELECT 1
FROM dual
WHERE 33 IN (SELECT 1 FROM dual WHERE 1 = 0);

SELECT 1
FROM dual
WHERE 33 NOT IN (SELECT 1 FROM dual WHERE 1 = 0);
Run Code Online (Sandbox Code Playgroud)

那么 NULL 和空结果集之间的比较在这里是如何工作的呢?

ype*_*eᵀᴹ 5

让我们看看这两种情况会发生什么:

WHERE NULL IN (SELECT 1 FROM dual WHERE 1 = 0);

WHERE NULL NOT IN (SELECT 1 FROM dual WHERE 1 = 0);
Run Code Online (Sandbox Code Playgroud)

由于子查询产生一个空表,我们可以用伪代码编写它们:

WHERE NULL IN (<empty_table>);

WHERE NULL NOT IN (<empty_table>);
Run Code Online (Sandbox Code Playgroud)

所以第一个询问一些(NULL)值是否在一个空表中。这种条件的结果总是FALSE,与值是否为空无关,因为表是空的

在第二个条件中应用相同的推理,它总是TRUE,再次独立于值。

在 Postgres 中很容易确认这些条件的结果值是什么,因为我们有一个布尔类型。请参阅dbfiddle.uk,其中第一个显示f(FALSE),第二个显示t(TRUE)。


由于上述原因,当您运行两个查询时,它们将变为:

SELECT 1
FROM dual
WHERE FALSE ;
Run Code Online (Sandbox Code Playgroud)

给出一个空结果(正确,因为WHERE条件是FALSE

SELECT 1
FROM dual
WHERE TRUE ;
Run Code Online (Sandbox Code Playgroud)

给一行(再次正确)。