2

我从以下两个 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 链接

4

6 回答 6

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
于 2013-03-22T09:59:36.690 回答
2

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

搜索到的 CASE 表达式:

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

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

于 2013-03-22T10:18:44.167 回答
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了!哦,天哪……它甚至不等于自己,而它又不等于自己……这一个可以抓住而不发疯的情况……

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

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

为了克服这个

  • 建议添加一个索引,该索引具有语义上表示NULL含义的不同、精确的值,例如NVL(mynullcol,-1)在仅包含正整数的列上以便能够快速查询它们。
  • 或者您可以添加一个常量值以形成一个“半多值”索引,该索引索引所有行,其中一个可以为空,而另一个为常量。( create index idx_myindex on table(column_with_nulls,1);)

这个问题这篇文章更深入地详细介绍了这个主题)

另一个例子是订购...

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......但是,根据@ypercube的宝贵评论

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

NULL是一个扭曲的业务,如果可能的话,明智的做法是远离它......(这不仅适用于 SQL,而且适用于 OOP 语言的某些情况。)

于 2013-03-22T10:19:42.110 回答
0

值 NULL 表示该列的数据值是未知的。NULL 不是零、零长度字符串或空白的同义词。

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

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

于 2013-03-22T10:40:48.300 回答
0

这并不矛盾。如果您有 2 个对象 A、B,那么它是以下三个对象之一:

  • A等于B

  • A不等于B

  • 你不能比较 A 和 B

这就像检查 (0/0 > 0) 或 (0/0 < 0) 还是 (0/0 = 0)。你只是无法比较它们。每个选项都是错误的

对于您的示例: case 检查您的论点是否为真

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

  • 参数 ('abc'<>null) 不正确,它是 null

于 2013-03-22T10:20:15.840 回答
0

您不能将 <> 或 = 与空值一起使用。你需要说

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
于 2013-03-22T10:00:06.790 回答