不等于<>!= NULL运算符


Answers:


308

<>是标准SQL-92;!=是等效的。两者都评估值,但NULL不是- NULL是占位符,表示不存在值。

这就是为什么您只能在此类情况下使用IS NULL/ IS NOT NULL作为谓词的原因。

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

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


4
实际上,我相信它是<>在92规范中,但是大多数供应商都支持!=和/或它包含在更高的规范中,例如99或03。–
Thomas

2
@Thomas:!=据我所知,直到〜i才支持Oracle ,这带来了许多ANSI-92语法。我相信MySQL是相似的,从4.x开始支持。
OMG Ponies,

这似乎暗示!=着以后的规范中可能包含替代的<>。不要动手掌握新规格,所以我不能肯定地说。
托马斯

2
是结果WHERE MyColumn != NULL还是WHERE MyColumn = NULL确定性的?换句话说,不管MyColumn数据库中是否可以为空,是否保证总是返回0行?
Slauma 2011年

11
还应注意,由于!=仅求值,因此执行类似操作WHERE MyColumn != 'somevalue'不会返回NULL记录。
jsumrall 2015年

88

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

换句话说,没有值可以等于(或不等于)NULL,因为NULL没有值。

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


3
+1。并且,与OP语句相反,这不是“ Microsoft SQL”。在SQL标准中定义了三元逻辑,在这一点上MS遵守该标准。
TomTom

6
我并不是在暗示这只是Microsoft的行为。我只是说我在Microsoft SQL Server上观察到它。
Maxim Gershkovich 2011年

13
出于兴趣,在任何情况下这种(预期)行为都是有用的吗?在我看来,'a' != null不返回值(true/ 1)是反直观的,并且会不时地吸引我!我本以为“一些价值与没有价值相比”永远都是“不平等”,但也许那只是我吗?!
DarthPablo 2014年

1
我认为人们将NULL描述为“ 没有价值 ” 很有趣。因此,类似于说数字1实际上是一个值时说“具有一个值”。但NULL代表非价值..
systemaddict

作为一种手动解决方法,SELECT * FROM MyTable WHERE coalesce(MyColumn, 'x') <> 'x'如果为常量值x提供适当的数据类型(在本例中为字符串/字符),则通常可以分配一个常量(如果它是NULL值)。这是TSQL语法,但是Oracle和其他引擎具有类似的功能。
systemaddict

26

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

如果你:

 SET ANSI_NULLS OFF

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

您会得到不同的结果。

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


8
+1 ...还不够。现在何时可以在索引中获得“重复的” NULL?:(

通过在过滤索引(例如create unique index UK_MyTable on MyTable (Column) where Column is not null)中添加WHERE子句,可以在SQL Server索引中获得重复的NULL :msdn.microsoft.com/en-us/library/cc280372.aspx
Anthony Mills,

3
从文档中注意:SET ANSI_NULLS为OFF时,等于(=)和不等于(<>)比较运算符不遵循ISO标准。使用的SELECT语句WHERE column_name = NULL返回column_name中具有空值的行。使用SELECT语句WHERE column_name <> NULL返回该列中具有非空值的行。同样,使用的SELECT语句WHERE column_name <> XYZ_value返回所有不是XYZ_value且不是NULL的行。恕我直言,最后一条语句从结果中排除了空值,这似乎有些奇怪!
DarthPablo 2014年

4
msdn doc中的重要说明: 在SQL Server的较新版本中(2014年以后),ANSI_NULLS将始终为ON,并且任何将选项显式设置为OFF的应用程序都将产生错误。避免在新的开发工作中使用此功能,并计划修改当前使用此功能的应用程序。
Otiel

7

在SQL中,您对NULL结果进行评估/计算的任何结果都为未知

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

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

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

希望这可以帮助。


“在SQL中,任何您使用NULL评估/计算的结果都将变为'NULL'” –错误。您的意思是未知的结果。
2011年

@MahendraLiya没有提供isNull函数来检查NULL,但是它“ 用指定的替换值替换NULL。 ”。您应该使用IS NULL或IS NOT NULL代替ISNULL,这是另一回事。
反向工程师


6

我们用

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

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


5

我只是看不到null不能与其他值或其他null相提并论的功能性和无缝原因,因为我们可以清楚地比较它并说它们在我们的上下文中是相同还是不同。这很有趣。仅仅由于一些合理的结论和一致性,我们需要不断地对其进行打扰。它不是功能性的,要使其更具功能性,然后让哲学家和科学家们来断定它是否一致,并且是否具有“通用逻辑”。:)有人可能会说这是由于索引或其他原因造成的,我怀疑这些东西是否不能支持与值相同的null。就像比较两个空杯子,一个是藤蔓玻璃,另一个是啤酒杯,我们不是在比较对象的类型,而是它们包含的值,就像可以比较int和varchar一样,将其为null。甚至更容易,没有什么和两个虚无的共同点是什么,它们是相同的,对于我和其他编写sql的人来说,它们显然是可比较的,因为由于某些ANSI标准,我们不断以奇怪的方式比较它们来打破这种逻辑。为什么不使用计算机功能为我们做到这一点,我怀疑如果考虑到所有相关内容,它会减慢速度。“这不是null,什么也不是”,不是苹果,而是apfel,加油...功能上是您的朋友,这里也有逻辑。最后,唯一重要的是功能,并且确实以这种方式使用null会带来或多或少的功能和易用性。它更有用吗?因为我们由于某些ANSI标准而不断以奇怪的方式进行比较来打破这种逻辑。为什么不使用计算机功能为我们做到这一点,我怀疑如果考虑到所有相关内容,它会减慢速度。“这不是null,什么也不是”,不是苹果,而是apfel,加油...功能上是您的朋友,这里也有逻辑。最后,唯一重要的是功能,并且确实以这种方式使用null会带来或多或少的功能和易用性。它更有用吗?因为我们由于某些ANSI标准而不断以奇怪的方式进行比较来打破这种逻辑。为什么不使用计算机功能为我们做到这一点,我怀疑如果考虑到所有相关内容,它会减慢速度。“这不是null,什么也不是”,不是苹果,而是apfel,加油...功能上是您的朋友,这里也有逻辑。最后,唯一重要的是功能,并且确实以这种方式使用null会带来或多或少的功能和易用性。它更有用吗?不是苹果,它是apfel,来吧...从功能上来说是您的朋友,这里也有逻辑。最后,唯一重要的是功能,并且确实以这种方式使用null会带来或多或少的功能和易用性。它更有用吗?不是苹果,它是apfel,来吧...从功能上来说是您的朋友,这里也有逻辑。最后,唯一重要的是功能,并且确实以这种方式使用null会带来或多或少的功能和易用性。它更有用吗?

考虑以下代码:

SELECT CASE WHEN NOT (1 = null or (1 is null and null is null)) THEN 1 ELSE 0 end

你们当中多少人知道这段代码会返回什么?不管是否带有NOT,它都返回0。对我来说,它不起作用并且令人困惑。在c#中,它应该是全部,比较操作返回值,从逻辑上讲,这也会产生值,因为如果没有,则没有什么可比较的(nothing :)除外)。他们只是“说”:与null相比,任何东西都“返回” 0,这会造成许多变通方法和麻烦。

这是使我来到这里的代码:

where a != b OR (a is null and b IS not null) OR (a IS not null and b IS null)

我只需要比较两个字段(在哪里)具有不同的值,就可以使用函数,但是...


4

NULL无法使用比较运算符与任何值进行比较。NULL = NULL为假。Null不是值。IS运算符专门用于处理NULL比较。


5
当我有时在某些临时查询中null = null可能使用的地方时,我总是很困惑1=0。如果他们抱怨,我将其更改为null != null:)
SWeko 2011年

8
“ NULL = NULL为假”不是这样。NULL = NULL的值等于未知值,而不是false。
nvogel

@dportas是这样,但我的意思是说在有条件的情况下它不会被评估为true。
Vincent Ramdhanie 2011年

@VincentRamdhanie都不为假;实际上,在postgres中,它将被评估为NULL
Pere

2

旧问题,但以下内容可能会提供更多详细信息。

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

假设您运行如下查询:

SELECT *
FROM orders
WHERE delivered=ordered;

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

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

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

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

SELECT *
FROM orders
WHERE delivered<>ordered;

再说一次,如果我们不知道两个值是什么,我们怎么能说这两个值相同。

SQL对缺失值进行了特定的测试:

IS NULL

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

最后,就!=操作员而言,据我所知,它实际上并没有任何标准,但得到了广泛的支持。它的添加使某些语言的程序员感到宾至如归。坦白说,如果程序员难以记住他们使用的语言,那么他们将是一个糟糕的开端。


这与@Hove在他的回答中描述的相同的“荒谬”“逻辑”。事实是,在这种情况下,不需要额外的用具。可以很容易地假设,当我们将某物与a进行比较时,是NULL指我们将一个值与“具有一个NULL值” 进行比较,而不是将该值与“底层资产具有”的未确定值进行比较,NULL但是我们不知道”,这显然是我们永远无法知道的。这确实可以缓解问题。
佩雷

@Pere我不会说这完全是“荒谬的”,而且我不确定写作IS NULL比写作还要艰巨得多= NULL。我认为,如果WHERE columnA = columnB具有与相同的解释WHERE columnA = NULL,将会更一致,而不是将后者视为特殊情况。请记住,NULL不是一个值。在编程语言的地方合法的,以测试variable == null它是因为null有不同的含义; 它并不代表未知的事物,而是有意重置的值。SQL并非如此。
曼戈

这就是为什么我将其放在引号@Mangoo;)(以及“逻辑”)中。不要生我的气。我说的是ANSI的“原因”,而不是您的解释。我同意您的最新示例中IS NULLAND 之间没有开销=NULL。但是,请看一下Hover的最后一个。我厌倦了一次又一次的体验,不得不做不必要的负担?额外的检查...
Pere

1

我想建议我编写的这段代码,以查找值是否有所变化, i是新值还是d旧值(尽管顺序无关紧要)。因此,从值更改为null或从值更改为null都不是更改(当然,从值更改为另一个值是更改,但从值更改为相同则不是)。

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的用法使其兼容各种类型


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.