2

I am getting an inconsistent result from below two SQL queries.

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

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

Result for both queries same i.e 0

What's wrong am I missing some thing ?

NOTE : : I know I can use IS NULL and IS NOT NULL but my question is why result from above queries is inconsistent.

EDIT : Added from answer of @ppeterka.

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

This returns 0 too. Null is not even equal to itself.

But then what does this return?

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

0 again

SQLFiddle link

Aman J
  • 1,825
  • 1
  • 16
  • 30

6 Answers6

4

Because NULL is unknown that is why the result is 0. When you want to compare a column or a value if it is null or not, use IS NULL or IS 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
John Woo
  • 258,903
  • 69
  • 498
  • 492
  • @J W : Thanx for your answer but my concern is why are these results inconsistent? – Aman J Mar 22 '13 at 10:04
  • @AmandeepJiddewar They aren't inconsistent: this behavior is specified by the SQL standard – Mark Rotteveel Mar 22 '13 at 10:25
  • Good explanation. NULL is special. It is not equal to anything (even itself, as you've found out). Any operation on NULL returns NULL (except for the "NULL-taming" operation IS [NOT] NULL). – sebt Mar 22 '13 at 10:42
  • As I indicate in my answer below, I think the question really has to do with how CASE WHEN branching handles unknown/undefined. Should `CASE WHEN (undefined)...` crash, or should it branch to false? It depends on whether truth is defined strictly or loosely, like "truthyness" in javascript. – Tim Mar 22 '13 at 12:04
  • @AmandeepJiddewar In SQL, There are 3 truth values: `true`, `false` and `unknown`. So, `true <> false`, `false <> NULL`, `null <> null`. – John Woo Mar 22 '13 at 13:08
  • Right. And how should CASE WHEN ( unknown ) ... branch? to true or to false? – Tim Mar 22 '13 at 13:33
  • @Tim i already mentioned on the answer, use `IS NULL or IS NOT NULL`, you cannot use `=, <>, !=` when testing value. – John Woo Mar 22 '13 at 13:36
  • 1
    @ JW: I understand that, thanks. I am interrogating the OP about his claim that the results are not consistent. I should use ... markup :-) – Tim Mar 22 '13 at 14:14
2

The result of comparing anything to NULL, even itself, is always NULL(not TRUE or FALSE).

Searched CASE expression:

  • If no Boolean_expression evaluates to TRUE, the Database Engine returns the else_result_expression if an ELSE clause is specified, or a NULL value if no ELSE clause is specified.

In your case the result always will be 0, because 0 in ELSE clause

Aleksandr Fedorenko
  • 16,594
  • 6
  • 37
  • 44
  • Because NULL is the mathematical equivalent of undefined. And whenever you compare something to undefined, you get undefined as a result, no matter what comparison operator you use. – Frank Schmitt Mar 22 '13 at 10:33
1

To add a bit of twist to this, try this out:

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

This returns 0 too. Null is not even equal to itself.

But then what does this return?

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

This returns 0 again! Oh holy... It is not even not equal to itself, while it is not equal to itself... Quite a situation to grasp without getting insane...

Why to keep this all in mind? - one might ask

One example is indexing: in Oracle, indexes don't work the way one would expect them to work on NULL values where a column permits the use of that value. This means that given an index, if all the values (fields, functions on fields, etc) of a row that are included in the index are all NULL, that row won't be indexed in that given index. So this means that an index, that has only one value indexed (for example, a field directly), a null value would mean that row not to be included in the index.

To overcome this

  • it might be advisable to add an index with a distinct, exact value semantically representing the NULL meaning, like NVL(mynullcol,-1) on a column only containing positive integers to be able to query them quickly.
  • or you could add a constant value to form a "semi-multivalue" index, that indexes all rows, where one can be null, as the other is a constant. (create index idx_myindex on table(column_with_nulls,1); )

(This question and this article detail this subject in a bit more depth)

Another example is ordering...

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

Both 0. This is OK... We expected this by now... And what about this?

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

Uh-oh... Both 0 again. This might be an issue - how is ordering going to work?

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 

This however consistently returns:

Abc
null
null
null

Using ... order by col_1 DESC returns:

null
null
null
Abc

So from this, on an empirical basis, it does seem that 'Abc' < null... However, as per the valuable comment of @ypercube:

the sort order can be set with the NULLS LAST and NULLS FIRST modifiers (at least in Oracle). What you observe is the default sort order when the ORDER BY has no modifier

NULL is a twisted business, it is wise to steer away from it if it is possible... (And this is not only true for SQL, but for certain situations in OOP languages too.)

Community
  • 1
  • 1
ppeterka
  • 20,583
  • 6
  • 63
  • 78
  • Can you provide source about your claim that `NULL` values are not indexed? – ypercubeᵀᴹ Mar 22 '13 at 14:01
  • @ypercube you're right, that part needed quite a bit of rework (not just references), now it does read much more what I initially wanted it to... I hope not for me only... (damn language barrier...) – ppeterka Mar 22 '13 at 14:29
  • OK then. It wasn't obvious you were talking for Oracle only, before. – ypercubeᵀᴹ Mar 22 '13 at 14:31
  • 1
    One last (pedantic) comment. You shouldn't imply that `'Abc' < null` by those orderings.They are confusing admittedly but the sort order can be set with the [`NULLS LAST` and `NULLS FIRST`](http://www.orafaq.com/wiki/NULL) modifiers (at least in Oracle). What you observe is the default sort order when the `ORDER BY` has no modifier. – ypercubeᵀᴹ Mar 22 '13 at 14:37
  • @ypercube thanks, one day I might just feel I know Oracle - but that day somehow slips farther and farther in the future every day as I know more and more... – ppeterka Mar 22 '13 at 14:42
0

You can't use <> or = with nulls. You need to say

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

and

select (case when 'Abc' is not null then 1 else 0 ) from dual
Screwtape
  • 1,337
  • 2
  • 12
  • 27
  • Thanx for your answer but my main concern is why are these results inconsistent? – Aman J Mar 22 '13 at 10:05
  • = and <> don't work with null. Null can only be compared with "is null" or "is not null". Oracle uses tri-state boolean - i.e. the result can be true, false or null. If you use a comparison operator (such as = or <>) and one of the operands is null, the result is always null, not true or false. – Screwtape Mar 22 '13 at 10:18
0

It is not inconsistent. if you have 2 objects A,B then it's one of the following three:

  • A equals B

  • A not equals B

  • you cannot compare A and B

It's like examining if (0/0 > 0) or (0/0 < 0) or (0/0 = 0). You just cannot compare them. every option is false

For your example: case checks if your argument is true

  • argument ('abc'=null) is not true, it's null

  • argument ('abc'<>null) is not true, it's null

Thanos Darkadakis
  • 1,669
  • 2
  • 18
  • 30
0

The value NULL means the data value for the column is Unknown. A NULL is not synonymous with Zero, or zero length string or blank.

Anything you compare with NULL will result in Unknown (NULL).

Please check this to clear your doubts. To have the correct result, use IS NULL or IS Not NULL as you already know.

Nilesh Thakkar
  • 2,877
  • 1
  • 24
  • 43