不等于 NULL 上的 <> != 运算符

Not equal <> != operator on NULL

提问人:Maxim Gershkovich 提问时间:4/14/2011 最后编辑:BenMaxim Gershkovich 更新时间:5/19/2022 访问量:569698

问:

有人可以解释一下SQL中的以下行为吗?

SELECT * FROM MyTable WHERE MyColumn != NULL (0 Results)
SELECT * FROM MyTable WHERE MyColumn <> NULL (0 Results)
SELECT * FROM MyTable WHERE MyColumn IS NOT NULL (568 Results)
sql-server t-sql null

评论


答:

415赞 OMG Ponies 4/14/2011 #1

<>是标准 SQL-92; 是它的等价物。两者都计算值,但值不是 -- 是一个占位符,表示没有值。!=NULLNULL

这就是为什么在这种情况下,您只能使用 / 作为谓词。IS NULLIS NOT NULL

此行为并非特定于 SQL Server。所有符合标准的 SQL 方言都以相同的方式工作。

注意:要比较您的值是否为空,请使用 ,而要与非空值进行比较,请使用 .我不能说我的值是否等于 NULL,但我可以说我的值是 NULL 还是 NOT NULL。我可以比较我的值是否不是 NULL。IS NOT NULL<> 'YOUR_VALUE'

评论

4赞 Thomas 4/14/2011
实际上,我相信它在 92 规范中,但大多数供应商支持和/或它包含在 99 或 03 等更高规格中。<>!=
2赞 OMG Ponies 4/14/2011
@Thomas:据我所知,Oracle 直到 ~9i 才支持,它引入了许多 ANSI-92 语法。我相信MySQL是类似的,从4.x开始支持。!=
0赞 Thomas 4/15/2011
这似乎表明它可能已包含在以后的规范中,作为 的替代。我没有掌握新的规格,所以我不能肯定地说。!=<>
4赞 Slauma 12/7/2011
结果是确定的还是确定的?或者换句话说,是否保证始终返回 0 行,无论在数据库中是否可为 null?WHERE MyColumn != NULLWHERE MyColumn = NULLMyColumn
37赞 jsumrall 2/12/2015
还应该注意的是,由于仅计算值,因此执行类似操作不会返回 NULL 记录。!=WHERE MyColumn != 'somevalue'
9赞 dkretz 4/14/2011 #2

NULL 的唯一测试是 IS NULL 或 IS NOT NULL。测试相等性是荒谬的,因为根据定义,人们不知道值是什么。

这是一篇维基百科文章:

https://en.wikipedia.org/wiki/Null_(SQL)

126赞 Barry Brown 4/14/2011 #3

NULL 没有值,因此不能使用标量值运算符进行比较。

换句话说,任何值都不能等于(或不等于)NULL,因为 NULL 没有值。

因此,SQL 具有特殊的 IS NULL 和 IS NOT NULL 谓词来处理 NULL。

评论

3赞 TomTom 4/14/2011
+1.而且,与OP声明相反,这不是“Microsoft SQL”。三位一体逻辑在 SQL 标准中定义,而 MS 在这一点上遵循该标准。
6赞 Maxim Gershkovich 4/14/2011
我并不是说这是Microsoft独有的行为。我只是说我在 Microsoft SQL Server 上观察到了它。
21赞 DarthPablo 6/23/2014
出于兴趣,是否有任何情况这种(预期)行为有用?在我看来,不返回值 (/) 是违反直觉的,并且不时会让我感到惊讶!我本来以为“有价值与无价值相比”总是“不相等”,但也许这只是我?!?'a' != nulltrue1
2赞 systemaddict 6/28/2017
我认为有趣的是,人们将 NULL 描述为“没有价值”。因此,类似于说数字 1“有价值”,而它实际上是一个价值。但 NULL 表示非值。
1赞 systemaddict 6/28/2017
作为手动解决方法,如果常量值为 NULL 值,则通常可以分配一个常量,前提是您为 sentinel 值 x(在本例中为 string/char)提供适当的数据类型。这是 TSQL 语法,但 Oracle 和其他引擎具有类似的功能。SELECT * FROM MyTable WHERE coalesce(MyColumn, 'x') <> 'x'
6赞 Vincent Ramdhanie 4/14/2011 #4

NULL 不能使用比较运算符与任何值进行比较。NULL = NULL 为 false。Null 不是值。IS 运算符专门设计用于处理 NULL 比较。

评论

6赞 SWeko 4/14/2011
我总是喜欢困惑的人,当我有时使用一些临时查询中可能使用的地方时。如果他们抱怨,我会把它改成:)null = null1=0null != null
11赞 nvogel 4/14/2011
“NULL = NULL is false”事实并非如此。NULL = NULL 的计算结果为 unknown,而不是 false。
0赞 Vincent Ramdhanie 4/14/2011
@dportas是这样,但我的意思是在条件中它不会被评估为真。
0赞 Pere 4/12/2018
@VincentRamdhanie既不是假的;事实上,在 postgres 中,它将被评估为 NULL
11赞 Mahendra Liya 4/14/2011 #5

在 SQL 中,您评估/计算的任何结果都为 UNKNOWNNULL

这就是为什么或给你 0 个结果。SELECT * FROM MyTable WHERE MyColumn != NULLSELECT * FROM MyTable WHERE MyColumn <> NULL

为了提供对值的检查,提供了 isNull 函数。NULL

此外,您可以像在第三个查询中使用的那样使用运算符。IS

评论

3赞 onedaywhen 4/14/2011
“在 SQL 中,您使用 NULL 计算/计算的任何内容都会导致 'NULL'” -- 不正确。你的意思是未知。
1赞 Reversed Engineer 5/31/2018
@MahendraLiya isNull 函数未用于检查 NULLS,但它“将 NULL 替换为指定的替换值”。您应该使用 IS NULL 或 IS NOT NULL 而不是 ISNULL,这是另一回事。
30赞 Cade Roux 4/14/2011 #6

请注意,此行为是默认 (ANSI) 行为。

如果您:

 SET ANSI_NULLS OFF

http://msdn.microsoft.com/en-us/library/ms188048.aspx

你会得到不同的结果。

SET ANSI_NULLS OFF显然将来会消失......

评论

8赞 4/14/2011
+1 ...还不够快。现在,何时可以在索引中获取“重复”的 NULL?:(
0赞 Anthony Mills 5/11/2014
可以通过在筛选的索引中添加 WHERE 子句来获取 SQL Server 索引中的重复 NULL(例如:msdn.microsoft.com/en-us/library/cc280372.aspxcreate unique index UK_MyTable on MyTable (Column) where Column is not null
4赞 DarthPablo 6/23/2014
文档中的注释:SET ANSI_NULLS 为 OFF 时,等于 (=) 和不等于 (<>) 比较运算符不遵循 ISO 标准。使用 WHERE column_name = NULL 的 SELECT 语句返回 column_name 中具有 null 值的行。使用 WHERE column_name <> NULL 的 SELECT 语句返回列中具有非 null 值的行。此外,使用 WHERE column_name <> XYZ_value 的 SELECT 语句将返回所有未XYZ_value且非 NULL 的行。恕我直言,最后这句话似乎有点奇怪,因为它从结果中排除了空值!
6赞 Otiel 1/15/2015
msdn 文档的重要说明:在 SQL Server 的未来版本 [2014 年更新] 中,ANSI_NULLS将始终处于 ON 状态,任何将该选项显式设置为 OFF 的应用程序都将生成错误。避免在新的开发工作中使用此功能,并计划修改当前使用此功能的应用程序。
0赞 Shadow 6/3/2016 #7

NULL 什么都不是......这是未知的。NULL 不等同于任何东西。这就是为什么您必须在 SQL 查询中使用魔术短语 IS NULL 而不是 = NULL 的原因

您可以参考以下内容:http://weblogs.sqlteam.com/markc/archive/2009/06/08/60929.aspx

2赞 Yariv de Botton 12/24/2016 #8

我想建议我编写的这段代码来查找值是否有变化,是新值还是旧值(尽管顺序无关紧要)。就此而言,从 value 到 null 的更改,反之亦然,但从 null 到 null 的更改不是(当然,从值到另一个值是更改,但从值到相同不是)。id

CREATE FUNCTION [dbo].[ufn_equal_with_nulls]
(
    @i sql_variant,
    @d sql_variant
)
RETURNS bit
AS
BEGIN
    DECLARE @in bit = 0, @dn bit = 0
    if @i is null set @in = 1
    if @d is null set @dn = 1

    if @in <> @dn
        return 0

    if @in = 1 and @dn = 1
        return 1

    if @in = 0 and @dn = 0 and @i = @d
        return 1

    return 0

END

要使用此功能,您可以

declare @tmp table (a int, b int)
insert into @tmp values
(1,1),
(1,2),
(1,null),
(null,1),
(null,null)

---- in select ----
select *, [dbo].[ufn_equal_with_nulls](a,b) as [=] from @tmp

---- where equal ----
select *,'equal' as [Predicate] from @tmp where  [dbo].[ufn_equal_with_nulls](a,b) = 1

---- where not equal ----
select *,'not equal' as [Predicate] from @tmp where  [dbo].[ufn_equal_with_nulls](a,b) = 0

结果是:

---- in select ----
a   b   =
1   1   1
1   2   0
1   NULL    0
NULL    1   0
NULL    NULL    1

---- where equal ----
1   1   equal
NULL    NULL    equal

---- where not equal ----
1   2   not equal
1   NULL    not equal
NULL    1   not equal

sql_variant的使用使其与多种类型兼容

12赞 Jeff Mergler 6/8/2017 #9

我们使用

SELECT * FROM MyTable WHERE ISNULL(MyColumn, ' ') = ' ';

返回 MyColumn 为 NULL 的所有行或 MyColumn 为空字符串的所有行。对于许多“最终用户”来说,NULL 与空字符串问题是一种区别,没有必要和混淆点。

评论

0赞 sisisisi 10/20/2020
这是最好的解决方法,只是在空字符串与 null 比较并非毫无意义的少数情况下要小心。
8赞 Manngo 3/29/2018 #10

null表示无值或未知值。它没有具体说明为什么没有值,这可能会导致一些歧义。

假设您运行如下查询:

SELECT *
FROM orders
WHERE delivered=ordered;

也就是说,您正在寻找 和 日期相同的行。ordereddelivered

当一列或两列为 null 时会发生什么?

因为至少有一个日期是未知的,所以你不能指望说这两个日期是相同的。当两个日期都未知时,情况也是如此:如果我们甚至不知道它们是什么,它们怎么可能相同?

因此,任何被视为值的表达式都必须失败。在这种情况下,它将不匹配。如果您尝试以下操作,情况也是如此:null

SELECT *
FROM orders
WHERE delivered<>ordered;

同样,如果我们不知道两个值是什么,我们怎么能说它们不相同。

SQL 对缺失值有一个特定的测试:

IS NULL

具体来说,它不是比较值,而是寻找缺失的值。

最后,关于运营商,据我所知,它实际上并不在任何标准中,但它得到了非常广泛的支持。添加它是为了让某些语言的程序员感到更自在。坦率地说,如果程序员难以记住他们使用的是什么语言,那么他们就有一个糟糕的开始。!=

评论

0赞 Pere 4/12/2018
这与@Hove在他的回答中描述的“荒谬”的“逻辑”相同。事实是,在这种情况下,不需要额外的用具;可以很容易地假设,当我们将某物与某物进行比较时,我们的意思是我们将一个价值与“具有价值”进行比较,而不是将该价值与“底层所具有的未确定价值”进行比较。但我们不知道“,显然我们永远无法知道。这真的会让事情变得容易。NULLNULLNULL
1赞 Manngo 4/12/2018
@Pere我不会说这是严格意义上的“荒谬”,我不确定写作比写作要辛苦得多。我认为,如果与 具有相同的解释,而不是将后者视为特例,那会更加一致。请记住,这不是一个值。在编程语言中,测试它是合法的,因为具有不同的含义;它不代表未知的东西,而是故意重置一个值。但 SQL 并非如此。IS NULL= NULLWHERE columnA = columnBWHERE columnA = NULLNULLvariable == nullnull
0赞 Pere 4/12/2018
这就是为什么我把它放在引号之间,@Mangoo ;)(还有“逻辑”)。不要生我的气;我说的是 ANSI 的“推理”,而不是你的解释。我同意,在您最新的示例中,AND 之间没有开销。但是看看 Hover 的最后一个。我厌倦了一次又一次地经历它,不得不做很多不必要的事情?额外检查...IS NULL=NULL