Answered by:
Checking for NULL

Question
-
Hi
When I use below in WHERE clause in a SELECT it fails when Role is NULL;
SELECT * FROM tblStaffBookings WHERE .... AND (tblStaffBookings.[Role] <> 'Available')
Why doesn't tblStaffBookings.[Role] <> 'Available' come out as TRUE when tblStaffBookings.[Role] is NULL? How do I get round it? At present I am using;
SELECT * FROM tblStaffBookings WHERE .... AND (tblStaffBookings.[Role] <> 'Available' OR tblStaffBookings.[Role] IS NULL)
Thanks
Regards
- Edited by Y a h y a Wednesday, December 16, 2015 9:19 PM
Wednesday, December 16, 2015 9:18 PM
Answers
-
comparison (NULL = something) or (NULL <> something) always returns False, just keep this in mind.
you can use your way or you can use ISNULL() function as well:
SELECT * FROM tblStaffBookings WHERE .... AND isnull(tblStaffBookings.[Role], '') <> 'Available'
- Edited by S.Khanzhin Wednesday, December 16, 2015 9:30 PM
- Proposed as answer by Eric__Zhang Thursday, December 17, 2015 6:16 AM
- Marked as answer by Eric__Zhang Thursday, December 24, 2015 8:28 AM
Wednesday, December 16, 2015 9:27 PM -
you can write something like below
SELECT * FROM tblStaffBookings WHERE .... AND (isnull(tblStaffBookings.[Role],'NA') <> 'Available')
Cheers,
Amit Tomar
---------------------------------------------------
Please mark this as answer if it solved your query
Please vote this as helpful if it solved your query
---------------------------------------------------
My Blog My Wiki Page- Proposed as answer by Eric__Zhang Thursday, December 17, 2015 6:17 AM
- Marked as answer by Eric__Zhang Thursday, December 24, 2015 8:29 AM
Thursday, December 17, 2015 1:42 AM
All replies
-
comparison (NULL = something) or (NULL <> something) always returns False, just keep this in mind.
you can use your way or you can use ISNULL() function as well:
SELECT * FROM tblStaffBookings WHERE .... AND isnull(tblStaffBookings.[Role], '') <> 'Available'
- Edited by S.Khanzhin Wednesday, December 16, 2015 9:30 PM
- Proposed as answer by Eric__Zhang Thursday, December 17, 2015 6:16 AM
- Marked as answer by Eric__Zhang Thursday, December 24, 2015 8:28 AM
Wednesday, December 16, 2015 9:27 PM -
-
Your 'workaround' is the right way to go about things.
In SQL, NULL is an often misunderstood concept. It's definition essentially is that of the absence of a value. NULL is not a value, and one NULL is not equal to (nor unequal to) another NULL, because we don't know what it is (or isn't, for that case)
As a result the following...
tblStaffBookings.Role <> 'Available'
..won't return NULL. The reason for this is that we can't be sure that NULL is equal to, nor unequal to, ANYTHING...it's a bizarre concept but one that makes more sense the more you work with it.
Basically you just have to accept that NULL is neither equal to, nor unequal to anything else and its presence can only be tested by using IS NULL, or converting NULL to something else that can be tested using ISNULL or COALESCE functions.
Hope this is helpful and not more confusing to you.
- Proposed as answer by Naomi N Wednesday, December 16, 2015 11:11 PM
- Edited by matprichardson Wednesday, December 16, 2015 11:15 PM
Wednesday, December 16, 2015 11:02 PM -
you can write something like below
SELECT * FROM tblStaffBookings WHERE .... AND (isnull(tblStaffBookings.[Role],'NA') <> 'Available')
Cheers,
Amit Tomar
---------------------------------------------------
Please mark this as answer if it solved your query
Please vote this as helpful if it solved your query
---------------------------------------------------
My Blog My Wiki Page- Proposed as answer by Eric__Zhang Thursday, December 17, 2015 6:17 AM
- Marked as answer by Eric__Zhang Thursday, December 24, 2015 8:29 AM
Thursday, December 17, 2015 1:42 AM -
SELECT * FROM tblStaffBookings WHERE .... AND (tblStaffBookings.[Role] <> 'Available' OR tblStaffBookings.[Role] IS NULL)
- Proposed as answer by Jason A Long Thursday, December 17, 2015 10:12 PM
Thursday, December 17, 2015 4:39 AM -
everytime have a problem with "null" query
i think you first use
SET
ANSI_NULLS standart from ANSI SQL
for example you query will with this model
set ANSI_NULLS off /* your sql query */ set ANSI_NULLS on
and see my wiki page
Thursday, December 17, 2015 6:51 AM -
i think you first use SET ANSI_NULLS standart from ANSI SQL
Please, don't ever mess with SET ANSI_NULLS and even less suggest this in public!
SET ANSI_NULLS OFF is a legacy setting for application writtn in the nineties and who still have not mended their ways. There are several points of functionality in SQL Server that does not work when ANSI_NULLS is OFF:
* Queries with linked servers.
* XQuery and the xml type methods.
* Indexed views.
* Filtered indexes.
* XML indexes.
* Spatial indexes.There may be more.
If run with ANSI_NULLS off you will be burnt sooner or later.
- Proposed as answer by Jason A Long Thursday, December 17, 2015 10:13 PM
Thursday, December 17, 2015 8:17 AM -
WHERE .... AND (COALESCE(tblStaffBookings.[Role],'Not Available') <> 'Available')
COALESCE returns the first NON NULL value. In this case if Role IS NULL it will return Not available, which is evaluated in the <> 'Available' and will return true.
I'd also like to introduce you to aliasing.
SELECT * FROM myReallyLongTableNameOfGreatDoomAndWorry d WHERE d.col = 1
In this example I have a table with a long name. I don't want to have to use that long name to refer to it all the time, so I've given it the ALIAS d. Now I can refer to it using that ALIAS.
Don't forget to mark helpful posts, and answers. It helps others to find relevant posts to the same question. Enjoyed my post? Hit the up arrow (left)
Really enjoyed it? See my profile!
My Tech Net Articles.- Edited by Patrick Hurst Thursday, December 17, 2015 2:26 PM
Thursday, December 17, 2015 2:23 PM -
Please, don't ever mess with SET ANSI_NULLS and even less suggest this in public!
Don't forget to mark helpful posts, and answers. It helps others to find relevant posts to the same question. Enjoyed my post? Hit the up arrow (left)
Really enjoyed it? See my profile!
My Tech Net Articles.Thursday, December 17, 2015 2:24 PM -
-
WHERE .... AND (COALESCE(tblStaffBookings.[Role],'Not Available') <> 'Available')
Using the COALESCE in the WHERE clause should be a no no... It make the predicate non-sargable.
The preferred syntax should be as the OP had it in his 2nd example...
WHERE .... AND (tblStaffBookings.[Role] <> 'Available' OR tblStaffBookings.[Role] IS NULL)
Jason Long
- Proposed as answer by Naomi N Sunday, December 20, 2015 7:59 PM
Thursday, December 17, 2015 10:22 PM -
Please, don't ever mess with SET ANSI_NULLS and even less suggest this in public!
I'm pretty sure if you mess with ANSI_NULLS they send Celko to your christmas party. I'm also pretty sure he brings his whomping stick.
Don't forget to mark helpful posts, and answers. It helps others to find relevant posts to the same question. Enjoyed my post? Hit the up arrow (left)
Really enjoyed it? See my profile!
My Tech Net Articles.
On a more serious note, it might be a good idea to address the encoding that allows something to be null. Since it seems to be a list of codes of some kind, the encoding might include a "N/A", "miscellaneous", "missing" or whatever.--CELKO-- Books in Celko Series for Morgan-Kaufmann Publishing: Analytics and OLAP in SQL / Data and Databases: Concepts in Practice Data / Measurements and Standards in SQL SQL for Smarties / SQL Programming Style / SQL Puzzles and Answers / Thinking in Sets / Trees and Hierarchies in SQL
Thursday, December 17, 2015 10:53 PM -
Please correct me if I'm wrong, but doesn't the engine switch COALESCE out for a CASE behind the scenes, meaning that it actually IS sargable?
Also, regardless of the sargability (is that a word? it should be!) would this only be applicable if the column has an index on it? If it's a varchar with NULL and repeated values, I think the chances of an index are pretty slim :)
Don't forget to mark helpful posts, and answers. It helps others to find relevant posts to the same question. Enjoyed my post? Hit the up arrow (left)
Really enjoyed it? See my profile!
My Tech Net Articles.Friday, December 18, 2015 2:11 PM -
But I always bring a bag of coal for the children when I go to Christmas parties :-)
On a more serious note, it might be a good idea to address the encoding that allows something to be null. Since it seems to be a list of codes of some kind, the encoding might include a "N/A", "miscellaneous", "missing" or whatever.
--CELKO-- Books in Celko Series for Morgan-Kaufmann Publishing: Analytics and OLAP in SQL / Data and Databases: Concepts in Practice Data / Measurements and Standards in SQL SQL for Smarties / SQL Programming Style / SQL Puzzles and Answers / Thinking in Sets / Trees and Hierarchies in SQL
Don't forget to mark helpful posts, and answers. It helps others to find relevant posts to the same question. Enjoyed my post? Hit the up arrow (left)
Really enjoyed it? See my profile!
My Tech Net Articles.Friday, December 18, 2015 2:12 PM -
But I always bring a bag of coal for the children when I go to Christmas parties :-)
On a more serious note, it might be a good idea to address the encoding that allows something to be null. Since it seems to be a list of codes of some kind, the encoding might include a "N/A", "miscellaneous", "missing" or whatever.
--CELKO-- Books in Celko Series for Morgan-Kaufmann Publishing: Analytics and OLAP in SQL / Data and Databases: Concepts in Practice Data / Measurements and Standards in SQL SQL for Smarties / SQL Programming Style / SQL Puzzles and Answers / Thinking in Sets / Trees and Hierarchies in SQL
Guys! A NICE Celko post! See, Christmas miracles do happen! Merry Christmas Joe!
Don't forget to mark helpful posts, and answers. It helps others to find relevant posts to the same question. Enjoyed my post? Hit the up arrow (left)
Really enjoyed it? See my profile!
My Tech Net Articles.Friday, December 18, 2015 7:08 PM -
Please correct me if I'm wrong, but doesn't the engine switch COALESCE out for a CASE behind the scenes, meaning that it actually IS sargable?
Also, regardless of the sargability (is that a word? it should be!) would this only be applicable if the column has an index on it? If it's a varchar with NULL and repeated values, I think the chances of an index are pretty slim :)
Don't forget to mark helpful posts, and answers. It helps others to find relevant posts to the same question. Enjoyed my post? Hit the up arrow (left)
Really enjoyed it? See my profile!
My Tech Net Articles.You are correct that a COALESCE is just a CASE expression with an alternate syntax.
No... Neither a COALESCE nor a CASE expression in the WHERE clause are sargable. In fact, off the top of my head, the only two functions that are sargable are CAST & CONVERT. And even then it only works with certain datatypes.
Is sargability as word? I get the red squiggly in all browsers and MS Word... But if you ask Google to find sargibility it'll ask if you mean sargability... So I suppose it depends on who's dictionary you're using...
Yes... You are correct in saying that, if no index exists on the column, then it doesn't matter... But that's a big IF. There's nothing that would or should keep a nullable (another iffy word) column from being an index key.
In either case, using functions in the WHERE clause is just a bad habit. Even if there isn't an index on that column today, doesn't mean that one won't be created down the road.
Below is a quick little demo...
IF OBJECT_ID('tempdb..#temp', 'U') IS NOT NULL DROP TABLE #temp; CREATE TABLE #temp ( FirstNumber INT NOT NULL PRIMARY KEY, SecondNumber INT NULL ); -- run with & without the nonclustered index -- CREATE NONCLUSTERED INDEX ix_temp ON #temp (SecondNumber) INCLUDE (FirstNumber); GO WITH n (n) AS ( SELECT 1 FROM (VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) n (n) ), Tally (n) AS ( SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM n n1, n n2, n n3, n n4, n n5, n n6 ) INSERT #temp (FirstNumber,SecondNumber) SELECT t.n, CASE WHEN t.n % 10 > 0 THEN t.n END FROM Tally t ; --======================================================================= DECLARE @n INT, @b1 DATETIME2(7), @b2 DATETIME2(7) ; SET @b1 = SYSDATETIME(); SELECT @n = t.FirstNumber FROM #temp t WHERE t.SecondNumber < 10000 OR t.SecondNumber IS NULL ; SET @b2 = SYSDATETIME(); SELECT @n = t.FirstNumber FROM #temp t WHERE COALESCE(t.SecondNumber, 0) < 10000 ; SELECT DATEDIFF(ms, @b1, @b2) AS Query_1, DATEDIFF(ms, @b2, SYSDATETIME()) AS Query_2 ;
In any case... Hope I didn't come off as a ball buster. The only reason I harp on it is because it's one of my own personal bad habits that I have to keep reminding myself to break. The COALESCE syntax makes for cleaner looking code... Which make too damn tempting...
Jason Long
- Proposed as answer by Naomi N Sunday, December 20, 2015 8:01 PM
Friday, December 18, 2015 11:14 PM -
Personally, I think "sargable" or however you would spell it is a useless word. What matters is whether any index can or will be seeked.
Consider this script:
SELECT * INTO objects FROM sys.objects
CREATE CLUSTERED INDEX clu ON objects(create_date)
ALTER TABLE objects ADD CONSTRAINT pk_objects PRIMARY KEY (object_id)
go
SELECT * FROM objects WHERE create_date > '20020101' AND create_date < '20030101'
SELECT * FROM objects WHERE year(create_date) = 2002
SELECT * FROM objects WHERE month(create_date) = 12
go
DROP TABLE objectsAs it happens, the clustered index is only seeked in the first query. Still there is a fundamental difference between the second and the third query. From a logical point of view, the index could be seeked, if the optimizer only cared to make the transformation and not just give up. But in the third query, there is not the ghost of a chance, as the condition is not aligned with the index.
- Proposed as answer by Ahsan KabirMVP Sunday, December 20, 2015 5:02 AM
Saturday, December 19, 2015 10:58 AM