在NOT IN子句中的NULL值

18 浏览
0 Comments

在NOT IN子句中的NULL值

当我以为是相同的查询时,我得到了不同的记录计数,其中一个使用了not in where约束,另一个使用了left join。在not in约束中的表中有一个空值(坏数据),这导致该查询返回0条记录。我有点理解为什么会这样,但我需要一些帮助完全理解这个概念。\n简单来说,为什么查询A返回结果而查询B不返回结果?\n

A: select 'true' where 3 in (1, 2, 3, null)
B: select 'true' where 3 not in (1, 2, null)

\n这是在SQL Server 2005上的情况。我还发现调用set ansi_nulls off会导致查询B返回结果。

0
0 Comments

在使用NULL时,你实际上是在处理三值逻辑。你的第一个查询返回结果,因为WHERE子句的计算结果是:

    3 = 1 or 3 = 2 or 3 = 3 or 3 = null
这是:
    FALSE or FALSE or TRUE or UNKNOWN
计算结果是
    TRUE

第二个查询:

    3 <> 1 and 3 <> 2 and 3 <> null
计算结果是:
    TRUE and TRUE and UNKNOWN
计算结果是:
    UNKNOWN

UNKNOWN不同于FALSE,你可以通过调用以下代码进行测试:

select 'true' where 3 <> null
select 'true' where not (3 <> null)

这两个查询将不会给出结果。

如果UNKNOWN等同于FALSE,那么假设第一个查询将会得到FALSE,那么第二个查询将会评估为TRUE,因为它将与NOT(FALSE)相同。

但事实并非如此。

关于这个主题有一篇非常好的文章,你可以在SqlServerCentral上找到。

整个NULL和三值逻辑的问题可能有点令人困惑,但是理解它是写出正确的TSQL查询的关键。

我还推荐另一篇文章,关于SQL聚合函数和NULL的问题。

0
0 Comments

在使用NOT IN子句时,如果在可能值的列表中包含NULL或者NULL,将会返回0条记录。这是因为NULL是一个未知的值,无法确定NULL值是否是要测试的值。

出现这个问题的原因是NOT IN子句无法处理NULL值。在比较时,NULL会导致查询无法确定是否匹配,因此会返回0条记录。

解决这个问题的方法是使用NOT EXISTS子句来替代NOT IN子句。在NOT EXISTS子句中,可以使用IS NULL来判断是否存在NULL值。

以下是一个示例,演示如何使用NOT EXISTS来解决这个问题:

SELECT column_name
FROM table_name
WHERE NOT EXISTS (
    SELECT 1
    FROM another_table
    WHERE another_table.column_name = table_name.column_name
    AND another_table.column_name IS NULL
);

通过使用NOT EXISTS子句和IS NULL条件,可以避免NULL值导致NOT IN子句返回0条记录的问题。

0
0 Comments

在上述内容中,描述了一个关于在NOT IN子句中使用NULL值的问题。问题的原因是,在使用NOT IN子句时,NULL值的处理方式不一致,导致查询结果与预期不符。解决方法是将NOT IN子句转换为一系列的<>(不等于)操作符,并使用IS NULL来处理NULL值。

具体来说,Query A中的代码是:

select 'true' where 3 = 1 or 3 = 2 or 3 = 3 or 3 = null

由于3 = 3为真,因此会返回结果。

Query B中的代码是:

select 'true' where 3 <> 1 and 3 <> 2 and 3 <> null

当ansi_nulls开启时,3 <> null的结果为UNKNOWN,因此谓词的结果为UNKNOWN,不会返回任何行。当ansi_nulls关闭时,3 <> null的结果为真,因此谓词的结果为真,会返回一行。

问题的关键在于将NOT IN转换为一系列的<>操作符时,改变了"not in this set"的语义行为。

此外,还提到了一些其他相关的问题和观点,例如:

- SQL Server的行为是错误的,因为它应该使用"IS NULL"来处理NULL值的比较,而不是错误地应用错误的语义。

- 在某些SQL解释器中,查询可以正常执行,但在其他解释器中不起作用。

- 关于NULL值的解释可能存在混淆,因为NULL可以被解释为"某个未知的值",所以3在(1, 2, 3, unknown)中是真的,而3不在(1, 2, unknown)中既不是真也不是假。

- NULL值的布尔转换可能会导致一些意外的结果。

为了解决在NOT IN子句中使用NULL值的问题,可以将NOT IN转换为一系列的<>操作符,并使用IS NULL来处理NULL值。此外,需要注意NULL值的处理方式可能会导致一些意外的结果。

0