Output of "select 1 where NULL <> -1;" [duplicate] - sql

This question already has answers here:
why is null not equal to null false
(7 answers)
Closed 6 years ago.
I guess I don't fully understand the meaning of NULL in SQL. I ran this SQL and I expected to see 1 as the output but I didn't see that:
select 1 where NULL <> -1;
Isn't NULL and -1 different? Can anyone explain why this clause of "NULL <> -1" is FALSE?

NULL Is not a value and therefore cannot be compared with any other value and get any other result than null. Docs. And how to compare nulls.

NULL means unknown. So with where NULL <> -1 you want to know whether the unknown value equals -1. The DBMS does not know (of course), so the result of the expression is neither TRUE nor FALSE; it is NULL.
Only rows for which the WHERE clause results in TRUE are selected. As your expression doesn't result in TRUE but in NULL, there is no row selected.

Related

SQL Case statement - Null + Not Null - then return a column [duplicate]

This question already has answers here:
SQL is null and = null [duplicate]
(4 answers)
Closed 11 months ago.
I use SQL inside a 3rd party system (So don't know the type it is)
I am trying to make a CASE work on a column using data from 2 more.
I want to display a column call Channel that is calculated using the following logic:
If column O.Test is blank and column o.subsource is not blank, display 'RESEND', otherwise display the value of column o.Source.
This is part of the SQL showing the CASE I wrote to do this:
select
-- other columns
(CASE
WHEN o.Test = NULL AND o.Subsource IS NOT NULL THEN 'RESEND'
ElSE o.Source
END) o.Source AS 'Channel',
-- other columns
The SQL runs with no errors but the output always shows what is in o.Source.
X = NULL is not equal IS NULL X
Check this question,
SQL is null and = null
change this statement "o.Test = NULL" instead of "o.Test IS NULL"

MsSql behaves differently when filtering for an empty string by positive and negative query [duplicate]

This question already has answers here:
Issues with SQL comparison and null values
(8 answers)
Closed 2 years ago.
I just realized very strange behavior of my MsSql database when filtering empty string != '' or <> '' regarding NULL values.
I have following data in the table
ID
Value
(table X)
1
(empty string)
2
NULL
(no value)
3
text
(some real text)
This query select * from X where Value = '' results in:
ID: [1]
Both queries select * from X where Value != '' and select * from X where Value <> '' result in:
ID: [3]
What I do not understand is, why 2nd query is not returning ID=2?
I know the syntax for checking explicitly on null values where Value IS NULL so I would expect, that 2nd query would behave differently. When checking for non-empty values, I used to write where Value <> '' AND Value IS NOT NULL. From now on I am totally confused...
NULL does not have a string value - or any value at all, whereas ' ' is an empty string. You're looking for not empty strings in your 2nd query. NULL is not an empty string or a string at all. NULL is a "value" of no other type than NULL itself
It is not possible to test for NULL values with comparison operators,
such as =, <, or <>.
https://www.w3schools.com/sql/sql_null_values.asp

TSQL filter that I do not understand, 2 versions that I thought would return the same data do not

So I have a SQL statement that was not returning data like it should (MSSQL Server), in part of the query I had this
and t.Invc_Sts_Cd <> 2
turns out if I changed that to
and (t.Invc_Sts_Cd <> 2 OR t.Invc_Sts_Cd IS NULL)
then it returned the data I expected, I would have thought those 2 things would be equivalent but obviously not in TSQL.
Here is the full Statement
SELECT t.tm_sht_id,0
FROM tm_sht t
INNER JOIN cand c ON c.cand_id = t.cand_id
LEFT JOIN SOW_Resource sr on c.Req_Id = sr.Req_Id and (sr.Invoice_Timesheets=1 OR sr.Invoice_Timesheets is NULL)
WHERE t.tm_sht_sts_cd = 3
AND t.apvd_dt >= #Last_Run_Time
and c.clnt_org_id = #Org_Id
and (t.Suspend_Fg <> 1)
and (t.Invc_Sts_Cd <> 2 OR t.Invc_Sts_Cd IS NULL)
My question is why do those return different data sets?
t.Invc_Sts_Cd <> 2 and (t.Invc_Sts_Cd <> 2 OR t.Invc_Sts_Cd IS NULL) are not equivalent, but they are similar.
The key thing you need to understand here is how NULL values work. Nothing is equal to or not equal to NULL, including NULL itself; NULL = NULL isn't TRUE (though is isn't FALSE either, but I come to that shortly). The only way to evaluate against a NULL is using IS NULL and IS NOT NULL.
When doing a comparison against NULL, if you don't use IS (NOT) NULL then the result will be UNKNOWN. For a expression like WHERE Column = 1 then it isn't a problem when Column has the value NULL, as it isn't 1. For other expressions, it does.
For WHERE Column <> 2, when Column has the value NULL it gives result the UNKNOWN, which importantly is not TRUE. Thus the row does not meet to criteria.
The same is true for an expression like WHERE NOT(Column = 1). If Column has the value NULL, then Column = 1 = UNKNOWN and NOT(UNKNOWN) is still UNKNOWN.
Therefore, if you have NULL values, and are performiong comparisons which rely on them, you must include IS NULL and/or IS NOT NULL logic.
Remember, NULL means you don't know what the value is. This is subtly different than not having a value at all. When you don't know what the value is, it's still possible the value might be 2, and therefore NULL <> 2 could still possibly be false... but, again, the result is you don't know.
Therefore, if t.Invc_Sts_Cd is NULL, then t.Invc_Sts_Cd <> 2 must evaluate as... NULL, because we don't know what the result is. And NULL is falsy when you force it into a true/false boolean situation.
This is not about T-SQL, but SQL in general. NULL is the unknown value. If you compare it with some value, the result is hence unknown (i.e. it could or could not match the value).
So both
and t.Invc_Sts_Cd <> 2
and
and t.Invc_Sts_Cd = 2
exclude NULLs from the result, because for a NULL in Invc_Sts_Cd neither expression results in TRUE.
The crux here is that the logical comparison:
t.Invc_Sts_Cd <> 2
is actually false when the Invc_Sts_Cd value is NULL. The reason for this is that comparing NULL to any other value yields the value NULL, which will evaluate to false when it appears inside a WHERE clause.
The second version of your logic is correct:
and (t.Invc_Sts_Cd <> 2 OR t.Invc_Sts_Cd IS NULL)
This will be true when either Invc_Sts_Cd is not equal to 2, or this value happens to be NULL.

What's the difference between the queries? "SELECT * FROM bookings where code = null" and "SELECT * FROM bookings where code IS null" [duplicate]

This question already has answers here:
What's the difference between " = null" and " IS NULL"?
(4 answers)
Closed 4 years ago.
I get different outputs for these queries. Did anyone face this?
The col= null would not work because
NULL means I don't know. which is a placeholder to say there is the absence of a value.
= evaluate for values, so that will not to work.
You need to use IS NULL to get NULL row value.
=NULL IS is an expression of a value and IS NULL is the preferred method of evaluating the condition of a variable being NULL.
Here is the detail description
Click here
The first statement,
SELECT * FROM bookings where code = null--
It Checks Directly if any row has the value null
The Second Statement,
SELECT * FROM bookings where code IS null
It Checks all the rows its a null or not..
That's completely normal. "X = NULL" is NULL, which amounts to false ("NOT X = NULL" is also false; NULL is falser than false). For most SQL dialects.

IS NULL versus <> 1 SQL bit

I have a bit column on a table in a SQL Server 2012 database.
I am trying to retrieve all the rows where this bit column is either NULL or NOT TRUE.
This query does not bring back what it should: (returns 0 rows)
Select *
from table
where bit_column_value <> 1
This query brings back the correct rows:
Select *
from table
where bit_column_value IS NULL
Now, I'd be happy to use the second query, but my issue is that, in a similar query for another table, the reverse of the above is true, where the first way works, but the second way does not!
Could someone assist in explaining what the difference is in the above? I have specifically updated the relevant bit columns to be NULL and this does not change the results. (Thought maybe there was a difference between "Empty" and Null values.
Thanks in advance for any explanations.
The reason <> doesn't work is that SQL treats NULL as unknown - it doesn't know what NULL is supposed to mean, so it evaluates both = and <> on a NULL value as UNKNOWN (which is treated as false in a where clause or join condition). For more info, read this: Why does NULL = NULL evaluate to false in SQL server.
If there's an index on it, using the ISNULL function will mean the index can't be used, so to
ensure the query can use the index just use OR:
SELECT *
FROM TableName
WHERE
bit_column_value IS NULL OR bit_column_value = 0
your best bet would be to write the query as such:
SELECT
*
FROM
table
WHERE
ISNULL(bit_column_value, 0) = 0
This should return all the NULL and FALSE records.
Without seeing your table structure and data, I cannot really comment on why you are getting different results from your 2 queries.
MSDN says that the BIT type can store values 0, 1 or NULL. (The fact that a BIT value is NULL must be stored separately from the bit value itself, since the bit values can be compressed so that 8 BIT values are stored in a byte.)
Remember that a condition in a WHERE clause selects a row when the condition is TRUE. For most binary predicates (conditions), if you compare NULL with some value, the result is NULL or UNKNOWN (not TRUE). So, for example, if the value in a column is NULL, then column = 0 evaluates to NULL or UNKNOWN, and so does column <> 0.
Looking at your queries:
SELECT * FROM table WHERE bit_column_value <> 1
Where the value in the bit_column_value column is 1, the condition is FALSE so the row is not returned; where the value is 0, the condition is TRUE so the row is returned; and where the value is NULL, the condition is also NULL or UNKNOWN so the row is not returned.
SELECT * FROM table WHERE bit_column_value IS NULL
According to the SQL standard, the IS [NOT] NULL predicate, and the related IS [NOT] {TRUE|FALSE|UNKNOWN} predicates, are slightly different. The IS NULL test returns TRUE if the tested value is NULL; otherwise, they return FALSE (and never return UNKNOWN). The IS [NOT] {TRUE|FALSE|UNKNOWN} tests are similar; they return TRUE if the value is of the specified type and FALSE otherwise (not UNKNOWN). For example:
Column IS TRUE IS FALSE IS UNKNOWN IS NOT TRUE IS NOT FALSE IS NOT UNKNOWN
FALSE FALSE TRUE FALSE TRUE FALSE TRUE
TRUE TRUE FALSE FALSE FALSE TRUE TRUE
NULL FALSE FALSE TRUE TRUE TRUE FALSE
So, in your second query, only the rows where the bit_column_value value is NULL (which is separate from both 0 and 1) will be selected — not the TRUE, nor the FALSE.
I am trying to retrieve all the rows where this bit column is either NULL or NOT TRUE.
Try writing the query directly from your specification:
SELECT * FROM table WHERE bit_column_value IS NULL OR bit_column_value IS NOT TRUE
SELECT * FROM table WHERE bit_column_value IS NULL OR bit_column_value = FALSE
SELECT * FROM table WHERE bit_column_value IS NULL OR bit_column_value <> TRUE
SELECT * FROM table WHERE bit_column_value IS NOT TRUE
Given the truth table above, query 4 would yield the result you want — with the major caveat that I'm not certain that MS SQL Server supports the IS [NOT] {TRUE|FALSE|UNKNOWN}. Judging from MSDN on Predicates, the IS [NOT] {TRUE|FALSE|UNKNOWN} predicates are not supported (but I might have missed the correct part of the manual). If that's correct, you need to use one of query 2 or 3.
(There are some extra complications with these predicates when the value is not a simple column but is a row value. However, that's not relevant to your question or problem; doubly not since MS SQL Server does not seem to support them.)
Please check your table data, if it's contain value = 0 ?
SQL Bit data type can only have value either 0, 1 or NULL, if you insert other value, it's considered to 1 (Exception : If you insert 'False' it will became 0, 'True' will became 1).
For example :
insert into t1 values (1),(2),(1),(3),(-1),(0),(NULL),('false'),('true')
The result :
1, 1, 1, 1, 1, 0, NULL, 0, 1
I think this is because that all the data have NULL values in this column. So:
Select *
from table
where bit_column_value <> 1;
Won't give you the result. Since NULL is unknown. And this:
Select *
from table
where bit_column_value IS NULL;
Will give you the result you are looking for.
But you have a misconception of representing true and false using the bit data type.
You are representing false as NULL, 0 is empty and true is any other value. The bit data types works as #IswantoSan explained in his answer; It should be 0 or 1 or NULL:
0 is false,
1 is true,
NULL is empty.
Therefore to get:
true values use the where bit_column_value = 1.
false values use the where bit_column_value = 0.
NULL or empty where bit_column_value IS NULL.
NULL or not true:where bit_column_value IS NULL or bit_column_value = 0`.
The other thing to note is that NULL and empty are two different things, they are not the same. In case of the BIT data type empty is NULL not 0, because 0 is supposed to be false. But consider a string data type like VARCHAR for example then the empty string '' is totally different from the NULL value.