Note: Since someone claimed that the external link is dead in Sushant Butta strong >'s answer, I posted the content here as a separate answer.
Beware of NULLS .
Today I came across very strange query behavior when using the IN and NOT IN operators. Actually, I wanted to compare two tables and find out if a value exists from table b to table a or not, and find out its behavior if the column contains null values. So I just created an environment to test this behavior.
We will create the table table_a .
SQL> create table table_a ( a number); Table created.
We will create the table table_b .
SQL> create table table_b ( b number); Table created.
Insert some values โโinto table_a .
SQL> insert into table_a values (1); 1 row created. SQL> insert into table_a values (2); 1 row created. SQL> insert into table_a values (3); 1 row created.
Insert some values โโinto table_b .
SQL> insert into table_b values(4); 1 row created. SQL> insert into table_b values(3); 1 row created.
Now we run a query to check if a value exists in table_a , checking its value from table_b using the IN statement.
SQL> select * from table_a where a in (select * from table_b); A ---------- 3
Run the following query to verify the absence.
SQL> select * from table_a where a not in (select * from table_b); A ---------- 1 2
The way out was as expected. Now we insert the null value in table_b and see how these two queries behave.
SQL> insert into table_b values(null); 1 row created. SQL> select * from table_a where a in (select * from table_b); A ---------- 3 SQL> select * from table_a where a not in (select * from table_b); no rows selected
The first request behaved as expected, but what happened to the second request? Why didnโt we get any result, what was supposed to happen? Is there a difference in request? No.
The change is shown in table_b . We entered null in the table. But how is this going? Let divide the two queries into "AND" and "OR" .
First request:
The first request will be processed inside something like this. This way, null will not create a problem here, since my first two operands will either evaluate to true or false . But my third operand a = null will not evaluate to true and false . It will be evaluated only null .
select * from table_a whara a = 3 or a = 4 or a = null; a = 3 is either true or false a = 4 is either true or false a = null is null
Second request:
The second request will be processed as shown below. Since we use the "AND" operator, and nothing but true in any of the operands will give me any output.
select * from table_a whara a <> 3 and a <> 4 and a <> null; a <> 3 is either true or false a <> 4 is either true or false a <> null is null
So how do we handle this? We will select all not null values โโfrom table_b when using the NOT IN operator.
SQL> select * from table_a where a not in (select * from table_b where b is not null); A ---------- 1 2
Therefore, always be careful with the null values โโin a column when using the NOT IN operator.
Beware of NULL !!