SQL案例给出不一致的结果

时间:2013-03-22 09:57:21

标签: mysql sql sql-server oracle

我从以下两个SQL查询中获得了不一致的结果。

查询1:select (case when 'Abc' = null then 1 else 0 end) from dual

查询2:select (case when ('Abc' <> null) then 1 else 0 end) from dual

两个查询的结果相同,即 0

我错过了什么?

注意::我知道我可以使用IS NULL and IS NOT NULL,但我的问题是为什么上述查询的结果不一致。

编辑:从@ppeterka的回答中添加。

select (case when null = null then 1 else 0 end) from dual

这也会返回0。 Null甚至不等于它自己。

但那又回归了什么?

select (case when null <> null then 1 else 0 end) from dual
再次

0

SQLFiddle link

6 个答案:

答案 0 :(得分:4)

因为NULL未知,因此结果为0。如果要比较列或值是否为空,请使用IS NULLIS NOT NULL

select (case when 'Abc' IS null then 1 else 0 end) from dual       -- 0
select (case when ('Abc' IS NOT null) then 1 else 0 end) from dual -- 1

答案 1 :(得分:2)

将任何内容与NULL进行比较的结果,甚至本身,总是为NULL(不是TRUE或FALSE)。

搜索CASE表达式:

  • 如果没有Boolean_expression计算为TRUE,则数据库引擎在指定ELSE子句时返回else_result_expression,如果未指定ELSE子句则返回NULL值。

在您的情况下,结果始终为0,因为ELSE子句中的0

答案 2 :(得分:1)

要为此添加一些扭曲,请尝试这样做:

select (case when null = null then 1 else 0 end) from dual

这也会返回0。 Null甚至不等于它自己。

但那又回归了什么?

select (case when null <> null then 1 else 0 end) from dual

这会再次返回0!哦,圣洁......它本身并不是不等于,而它 不等于它自己......相当一种情况要抓住而不会疯狂...... < / p>

为什么要记住这一切? - 有人可能会问

一个例子是索引:在Oracle中,索引不能像人们期望它们在NULL值上工作一样,其中列允许使用该值。这意味着给定索引,如果索引中包含的行的所有值(字段,字段上的函数等)都是 all NULL,那么该行将不会索引在该给定索引中。所以这意味着一个索引只有一个索引值(例如,一个字段直接),一个空值意味着该行不包含在索引中。

要克服这个

  • 建议添加一个索引,其中一个独特的,精确的值,在语义上代表NULL含义,就像NVL(mynullcol,-1)在只包含正整数的列上一样快速查询。
  • 或者你可以添加一个常量值来形成一个“半多值”索引,它索引所有行,其中一个可以为null,另一个是常量。 (create index idx_myindex on table(column_with_nulls,1);

This questionthis article详细介绍了此主题)

另一个例子是订购 ......

select (case when null < null then 1 else 0 end) from dual;
select (case when null > null then 1 else 0 end) from dual;

0。这没关系......我们现在期待这个......那么这个呢?

select (case when 'Abc' > null then 1 else 0 end) from dual;
select (case when null > 'Abc' then 1 else 0 end) from dual;

呃 - 哦......两个0再次。这可能是一个问题 - 订购如何运作?

select col_1 from
(select null as col_1 from dual)
union all (select 'Abc' as col_1 from dual)
union all (select null as col_1 from dual)
union all (select null as col_1 from dual)
order by col_1 

然而,这始终如一地回归:

Abc
null
null
null

使用... order by col_1 DESC返回:

null
null
null
Abc

因此,从经验的角度来看,似乎'Abc' < null ......但是,根据valuable comment of @ypercube

  

可以使用NULLS LAST and NULLS FIRST修饰符设置排序顺序(至少在Oracle中)。   您观察到的是ORDER BY没有修饰符时的默认排序顺序

NULL是一个扭曲的事业,如果可能的话,明智地避开它......(这不仅适用于SQL,而且适用于OOP语言中的某些情况。)

答案 3 :(得分:0)

您无法使用&lt;&gt;或=与空值。你需要说

select (case when 'Abc' is null then 1 else 0 end) from dual

select (case when 'Abc' is not null then 1 else 0 ) from dual

答案 4 :(得分:0)

这并不矛盾。 如果您有2个对象A,B则它是以下三个中的一个:

  • A等于B

  • A不等于B

  • 您无法比较A和B

就像检查(0/0> 0)或(0/0 <0)或(0/0 = 0)一样。你无法比较它们。每个选项都是假的

对于您的示例:案例检查您的参数是否为真

  • 参数('abc'= null)不为真,它为空

  • 参数('abc'&lt;&gt; null)不正确,它为空

答案 5 :(得分:0)

值NULL表示该列的数据值为Unknown。 NULL不与Zero同义,也不是零长度字符串或空白。

与NULL比较的任何内容都将导致未知(NULL)。

请检查this以清除您的疑虑。要获得正确的结果,请使用IS NULL或IS Not NULL,如您所知。