NULL values inside NOT IN clause
Query A is the same as:
select 'true' where 3 = 1 or 3 = 2 or 3 = 3 or 3 = null
Since 3 = 3
is true, you get a result.
Query B is the same as:
select 'true' where 3 <> 1 and 3 <> 2 and 3 <> null
When ansi_nulls
is on, 3 <> null
is UNKNOWN, so the predicate evaluates to UNKNOWN, and you don't get any rows.
When ansi_nulls
is off, 3 <> null
is true, so the predicate evaluates to true, and you get a row.
The NOT IN with NULL values dilemma in ORACLE SQL
This is not an issue with Oracle. This is how SQL is defined.
When the subquery returns a NULL
value with NOT IN
, then no rows match at all. For this reason, I strongly recommend always using NOT EXISTS
instead:
WHEN NOT EXISTS (SELECT 1 FROM bst WHERE x.n = bst.p)
THEN 'Leaf'
As a corollary, I usually use EXISTS
instead of IN
, even though it does not have this problem.
Why does this occur? NULL
means that the value is unknown, not that the value is "missing" or something else.
So, if all the elements have values, this is easy to calculate:
1 NOT IN (1, 2) --> false
3 NOT IN (1, 2) --> true
However:
1 NOT IN (1, 2, NULL) --> false
3 NOT IN (1, 2, NULL) --> NULL, because NULL could be equal to "3"
Basically, if any value is NULL
, then NOT IN
returns either "false" or NULL
. Both "false" and NULL
are treated the same in WHEN
and WHERE
.
using the NOT IN operator on a column with NULL values
Try this way:
select *
from employee E
where (E.company NOT IN ('ABC', 'DEF')
or E.company is null)
Understanding SQL IN clause with NULL values
Don't use not in
with subqueries. Period. Use not exists
; it does what you want:
select x.*
from x
where not exists (select 1 from y where y.y_name = x.x_name);
The problem is this. When you have:
x_name in ('a', 'b', null)
SQL actually returns NULL
, not false
. However, NULL
is treated the same as false
in where
clauses (and when
clauses but not for check
constraints). So, the row gets filtered out.
When you negate this, either as:
not x_name in ('a', 'b', null)
x_name not in ('a', 'b', null)
The results is not NULL
which is also NULL
and everything gets filtered out.
Alas. The simplest solution in my opinion is to get in the habit of using not exists
.
IN Clause with NULL or IS NULL
An
in
statement will be parsed identically tofield=val1 or field=val2 or field=val3
. Putting a null in there will boil down tofield=null
which won't work.
(Comment by Marc B)
I would do this for clairity
SELECT *
FROM tbl_name
WHERE
(id_field IN ('value1', 'value2', 'value3') OR id_field IS NULL)
Null with NOT in sub-query
Using not exists
is recommended approach rather than using not in
select * from #FirstTable f
where not exists(select 1 from #secondTable
where i = f.i)
How to ignore NULL in WHERE clause when SELECT is used?
To address your specific issue of dealing with null values, you can simply use isnull
SELECT *
FROM MyTable
WHERE PartNum = (SELECT isnull(Value, PartNum) FROM #Variables WHERE VarName = 'PartNum')
AND PartColor = (SELECT isnull(Value, PartColor) FROM #Variables WHERE VarName = 'PartColor')
Why does WHERE clause removes null values from the result?
Neither "not equal" nor "equal" will select a value that is NULL.
SQL uses "three-way logic" where an expression can be true or false or unknown. NULL is the absence of any value at all so it cannot be equal to something, and if it cannot be equal to a compared value it also cannot be "not equal", instead it is unknown.
To overcome this you need to treat NULL explicitly in your where clause, to include NULLs use OR SIS IS NULL
SELECT
SIS, COUNT(*)
FROM DL_SQ_DEV_INT.SMRY_DAILY_TRAILER_REPORT
WHERE UPPER(TRIM(SIS)) <> 'EQ' OR SIS IS NULL
GROUP BY 1;
Related Topics
How Does Database Indexing Work
How to See What Character Set a MySQL Database/Table/Column Is
Selecting Data from Two Different Servers in SQL Server
Why Isn't SQL Ansi-92 Standard Better Adopted Over Ansi-89
In VS or in the SQL Where Clause
T-Sql: Deleting All Duplicate Rows But Keeping One
Including Parameters in Openquery
Select Rows Which Are Not Present in Other Table
MySQL Query Finding Values in a Comma Separated String
SQL Left Join VS Multiple Tables on from Line
Select N Random Rows from SQL Server Table
Save Pl/Pgsql Output from Postgresql to a CSV File
How to Combine Date from One Field With Time from Another Field - Ms SQL Server