TSQL Comparing 2 uniqueidentifier values not working as expected - sql

I'm trying to compare 2 uniqueidentifier values as shown in the query below. However, if one value is null and one value isn't, the result is 'same'?! I'm sure that both values are uniqueidentifiers, and have also tried casting both values to uniqueidentifier to make absolutely sure. The 2 values being compared are coming from different databases with different collations. Does the collation make any difference? Any ideas would be appreciated.
select [result] = case when
[target].StaffID <> [source].StaffID then 'different'
else 'same'
end
from
...
If I replace the <> with an = the query then thinks that 2 null values don't match.
EDIT:
I used:
declare #empty uniqueidentifier
set #empty = '00000000-0000-0000-0000-000000000000'
... isnull(somevalue, #emtpy) <> isnull(othervalue, #empty) ...

NULL is neither equal to something nor equal to nothing. Generally you'd check for null values by comparing with IS NULL. For example,
somefield IS NULL
You could look into using COALESCE for what you're trying to do -- just make sure you use the same data types (in this case UniqueIdentifier):
...
case
when coalesce(t.StaffID,'00000000-0000-0000-0000-000000000000') <>
coalesce(t2.StaffID,'00000000-0000-0000-0000-000000000000')
then 'different'
else 'same'
end
...
http://sqlfiddle.com/#!3/181e9d/1

null is more of an unknown, it's not really a value. Unfortunately SQL will tell you that null = null is false.
Basically you have to cast nulls to empty strings than you can compare. We use IFNULL(value, replacement) to do that...
http://msdn.microsoft.com/en-us/library/ms184325.aspx
Hope this helps.
select case when null = null then 'equal' else 'not equal' end
Above will be "not equal"
select case when ISNULL(null, '') = ISNULL(null, '') then 'equal' else 'not equal' end
This one will be "equal"
And finally your case...
select [result] = case when
ISNULL([target].StaffID, '') <> ISNULL([source].StaffID, '') then 'different'
else 'same'
end
from

Related

Comparing empty string with null value - SQL Server

I need to compare two columns, and am hitting issues when comparing NULL against an empty string. Put simply, this is what I'm looking at.
DECLARE #EmptyString VARCHAR(20) = '', -- Could have valid VARCHAR data, empty string, or NULL
#Null VARCHAR(20) = Null; -- Could have valid VARCHAR data, empty string, or NULL
SELECT
CASE WHEN #EmptyString != #Null THEN 'Pass' ELSE 'Fail' END AS EmptyStringVsNull
In this case, because we all know that an empty string and a null column value are different, I would hope to see the result come back as 'Pass', however it doesn't.
From Martin's asnwer here, he explains that that a comparison like this results to UNKNOWN, rather than TRUE or FALSE, which clarifies the reason I am seeing these results, but I need find a solution to this. I know there must be a simply way around this that I'm missing...
I know that there are a few built in functions such as ISNULL() and NULLIF(), however I don't know if these can help in this situation...
ISNULL()
If we use the ISNULL() function to set null values to an empty string, then the comparison wont work as an empty string is equal to an empty string, for example
DECLARE #EmptyString VARCHAR(20) = '',
#Null VARCHAR(20) = Null;
SELECT
CASE WHEN ISNULL(#EmptyString, '') != ISNULL(#Null, '') THEN 'Pass' ELSE 'Fail' END AS EmptyStringVsNull
This also returns 'FAIL', so this is a no go. I could always use ISNULL to convert this to a different string, but this still isn't suitable, as the empty string may have a different value which by chance could match whatever we decide to convert null values to.
NULLIF()
DECLARE #EmptyString VARCHAR(20) = '',
#Null VARCHAR(20) = Null;
SELECT
CASE WHEN NULLIF(#EmptyString, '') != NULLIF(#Null, '') THEN 'Pass' ELSE 'Fail' END AS EmptyStringVsNull
If we use the NULLIF() function to convert empty strings to null, our comparison still doesn't return true. This is because, as explained in the linked post, comparing null values results in UNKNOWN.
With the simple SQL example above, how can I check that a NULL value is not equal to an empty string?
Your first example returns fail because you have the wrong operator. If you want to see if something equals something else you use =, not !=
Here is the code that proves that NULL can be compared to '':
DECLARE #EmptyString VARCHAR(20) = '',
#Null VARCHAR(20) = Null;
SELECT
CASE WHEN ISNULL(#EmptyString, '') = ISNULL(#Null, '')
THEN 'Pass' ELSE 'Fail'
END AS EmptyStringVsNull
It returns pass because you use =, not !=
Just reverse the comparison:
SELECT (CASE WHEN #EmptyString = #Null THEN 'Fail' ELSE 'Pass' END) as EmptyStringVsNull
The only complication is if you want two NULL values to be the same. If so:
SELECT (CASE WHEN #EmptyString = #Null OR (#EmptyString IS NULL AND #Null IS NULL)
THEN 'Fail' ELSE 'Pass'
END) as EmptyStringVsNull
DECLARE #EmptyString VARCHAR(20) = '', -- Could have VARCHAR data, empty string, or NULL
#Null VARCHAR(20) = Null; -- Could have VARCHAR data, empty string, or NULL
SELECT
CASE WHEN #EmptyString IS NOT #Null THEN 'Pass' ELSE 'Fail' END AS EmptyStringVsNull.
Because of ansi sql standard you can check for NUll value using IS NULL or IS NOT NULL operator.
It is quicker and more "Pythonic" (easier to understand by someone else who reads your code) to evaluate to the same outcome on both sides of the equal sign:
DECLARE #EmptyString VARCHAR(20) = ''
SELECT
CASE WHEN ISNULL(#EmptyString, '') != ''
THEN 'Pass'
ELSE 'Fail' END AS EmptyStringVsNull
GO
Both an EMPTY string and a true NULL value will yield TRUE for the search condition.
NOTE: It is not optimal, since good bussiness rules practices should clearly differenciate a NULL attribute from an EMPTY attribute.
i.e.
spouse_field = NULL (I still don't have the information regarding entity X's marital status)
spouse_field = '' (empty): That specific entity is confirmed as single. Otherwise, a name would have shown up.

CASE logic when removing NULLs

This is my first post, and I attempted to do a thorough search for this issue, so please accept my apologies if it has been posted elsewhere many times, but I'm wondering if anyone has encountered the following issue when attempting to remove NULLs from their result set:
case Occurrence
when NULL then '0'
else occurrence
end as Occurrence,
case Aggregate
when NULL then '0'
else Aggregate
end as Aggregate,
This didn't do anything to my NULLs; however, this did the trick:
case
when occurrence is NULL then '0'
else occurrence
end as Occurrence,
case
when aggregate is NULL then '0'
else Aggregate
end as Aggregate
Does anyone have any idea why this behaves this way? I'm using SQLServer2012.
I'm also not very versed in programming and only have less than a year SQL experience.
Thanks!
You should be using the ISNULL() or COALESCE() system function for handling nulls
something like
SELECT ISNULL(Occurrence , 0) AS Occurrence
,ISNULL(Aggregate , 0) AS Aggregate
FROM Table
OR
SELECT COALESCE(Occurrence , 0) AS Occurrence
,COALESCE(Aggregate , 0) AS Aggregate
FROM Table
The reason it didn't work in the case statement with
case Occurrence
when NULL then '0'
else occurrence
end as Occurrence,
is because it is interpreting it as
CASE
WHEN Occurrence = NULL THEN 0
ELSE Occurrence
END
Null is checked in sql server using IS NULL or IS NOT NULL if you use any other operator with null like = , <> or <, < it yields NULL hence the unexpected results.
Only for SQL Server 2012 and Later
In sql server 2012 and later versions you also have the IIF function
SELECT IIF(Occurrence IS NULL, 0, Occurrence) AS Occurrence
,IFF(Aggregate IS NULL , 0, Aggregate) AS Aggregate
FROM Table
You use simple case:
The simple CASE expression operates by comparing the first expression to the expression in each WHEN clause for equivalency. If these expressions are equivalent, the expression in the THEN clause will be returned.
Allows only an equality check.
case Occurrence
when NULL then '0'
else occurrence
end as Occurrence,
Which is executed as :
case
when occurence = NULL then '0'
else occurrence
end as Occurrence
Then expression occurence = NULL return NULL and is treated like False
Second your case use searched CASE with full condition and works fine:
case
when occurrence IS NULL then '0'
else occurrence
end as Occurrence,
So your question is about difference column IS NULL vs column = NULL
try
select 1 where null =null
select 1 where null is null
your statement looks like null equals null
select case when null is null then 1 else 0 end
select case null when null then 1 else 0 end
In your case use ISNULL this will give you the results your after
SELECT ISNULL(null,1)

DATALENGTH() or ISNULL() to retrieve fields that are not null and not empty

Quite simply, which of the following methods is better in a WHERE clause to retrieve records where the FIELD_NAME is NOT NULL and NOT Empty
WHERE DATALENGTH(FIELD_NAME) > 0
or
WHERE ISNULL(FIELD_NAME, '') <> ''
Update
I have been informed that the first method gives spurious results for some types of fields... Agree?
Firstly,
select *
from table
where column <> ''
will give exactly the same results as
select *
from table
where isnull(column, '') <> ''
because records where the condition is UNKNOWN rather than FALSE will still be filtered out. I would generally go with the first option.
DATALENGTH counts trailing spaces, which a comparison with '' does not. It is up to you whether you want ' ' to compare unequal to ''. If you do, you need DATALENGTH. If you don't, simply compare with ''.
Note that for TEXT/NTEXT types, comparisons are not supported, but DATALENGTH is.
ISNULL is the best approach instead of DATALENGTH.
I would use
WHERE ISNULL(FIELD_NAME, '') <> ''
One issue that might come up is that a record with a space in it would not be returned. Are you looking for records like that?
I'm not sure about unexpected results from DATALENGTH. I would use the ISNULL method so that SQL Server doesn't need to spend time calculating the length of the record being compared. I don't know the performance difference between the two, just a gut feeling.
if your "not empty" condition encompasses spaces then i would use the nullif
select case when nullif(' ', '') is null then 'y' else 'n' end
y
declare #d varchar(50)
set #d = null
select case when nullif(#d, '') is null then 'y' else 'n' end
y
I would use one of the following:
where coalesce(field_name, '') <> ''
or
where field_name <> '' or field_name is not null
or
where field_name <> ''
The first is standard SQL (coalesce() is standard, isnull() is not). The last is not the most obvious, but NULL will fail the comparison and it allows the use of indexes.
RTRIM(LTRIM(ISNULL(FIELD_NAME, ''))) <> '' will handle spaces and NULLS

How to write case in sql server?

In sqlserver, I write a query in that i use "case" but it is giving error, this is my case.
(case when sm.SegCode =0 then '' else sm.SegCode = 7 end)
please help me.
Thanks for all for giving response, actually I have a parameter #id. Now I want to check when it is not zero I check that condition sm.segcode else if #id is zero then I don't want to check the condition that is sm.segcode = #id.
There are two issues with the statement you showed:
the syntactic error of else sm.SegCode = 7
the attempted mixing of types with the empty string and the int
Try this instead:
case when sm.SegCode = 0 then '' else '7' end
Of course that is partially a guess, because I'm not sure exactly what you are trying to achieve by setting the result to either an empty string or the integer 7.
this would be syntactically correct:
case sm.SegCode when '0' then '' else '7' end
or
case sm.SegCode when 0 then NULL else 7 end
if that columns allows NULL's that is
you can see more about case when in the documentation: http://msdn.microsoft.com/en-us/library/ms181765.aspx
Always try to return Same DATA TYPE value from Case statement, seems your first condistion returns VARCHAR whereas the else section returns INT, it's not possible, so best to convert each value to VARCHAR, so 7 will be '7' in else statement, thanks
(CASE
WHEN sm.SegCode = 0 THEN ''
ELSE '7' END)

TSQL CASE LTRIM (RTRIM NULL

SQL Syntax is still something I am learning. I am getting the error noted below the this snippet of code.
SELECT
CASE WHEN LTRIM(RTRIM(cLehmanNo)) =' ' THEN NULL
WHEN cLehmanNo IS NOT NULL THEN REPLACE ( cLehmanNo,SUBSTRING (cLehmanNo,PATINDEX( '%[^a-zA-Z0-9 '''''']%',cLehmanNo),1), ' ' )
END asLOAN_NUMBER
,CASE WHEN LTRIM(RTRIM(cMERS)) =' ' THEN NULL
WHEN cMERS IS NOT NULL THEN REPLACE ( cMERS,SUBSTRING (cMERS,PATINDEX( '%[^a-zA-Z0-9 '''''']%',cMERS),1), ' ' )
END asMERS_ID
and 100+ more of same.
Msg 8133, Level 16, State 1, Line 1
None of the result expressions in a CASE specification can be NULL.
What am I doing wrong? How do I keep the gist of the statement and not get this crazy error?
This happens when it can't infer the type.
e.g.
SELECT CASE WHEN 1 = 2 THEN NULL ELSE NULL END
But this works
SELECT CASE WHEN 1 = 2 THEN NULL ELSE replace(NULL,'','') END
so I doubt the error is from the code you have shown us (You are using string functions and the following quick test shows that it will assume that to be varchar(8000))
SELECT CASE WHEN 1 = 2 THEN NULL ELSE REPLACE(NULL,'','') END a
INTO t /*Creates column of datatype varchar(8000)*/
You need to convert NULL to a correct type matching the overall values, e.g. CONVERT(VARCHAR(10), NULL), otherwise the server can't deduce which type to make the resulting value.
The error message actually means that all results in one of your case expressions are null. You have an expression like:
case when something then null when something then null end
At least one of the results has to be something other than null. You could circumvent this, but most likely there is a mistake in the query, as a case exression that always returns the same result is pointless.
The error message has been changed to:
At least one of the result expressions
in a CASE specification must be an
expression other than the NULL
constant.
SELECT
CASE WHEN LTRIM(RTRIM(cLehmanNo)) =' ' THEN NULL
WHEN cLehmanNo IS NOT NULL THEN REPLACE ( cLehmanNo,SUBSTRING (cLehmanNo,PATINDEX( '%[^a-zA-Z0-9 '''''']%',cLehmanNo),1), ' ' )
ELSE ''
END asLOAN_NUMBER
,CASE WHEN LTRIM(RTRIM(cMERS)) =' ' THEN NULL
WHEN cMERS IS NOT NULL THEN REPLACE ( cMERS,SUBSTRING (cMERS,PATINDEX( '%[^a-zA-Z0-9 '''''']%',cMERS),1), ' ' )
ELSE ''
END asMERS_ID