Conversion failed when converting the nvarchar value 'These are comments for errors' to data type int - sql

I have been struggling to get this corrected for a while now. Below is the part of a query where I am getting the error in the MAX function and I am not able to understand why its trying to convert to data type INT. I would like to keep it as string as this particular column is for comments
MAX(CASE
WHEN ID = -416 AND Value IS NOT NULL
THEN Value
ELSE 'No Error'
END) AS Error_Comments
This particular table is still in test and hence for test purposes there is only one comment added for now which is
These are comments for errors
I also tried converting the case statement but it still gives the same error:
MAX(CONVERT(VARCHAR, CASE
WHEN ID = -416 AND Value IS NOT NULL
THEN Value
ELSE 'No Error'
END)) AS Error_Comments
I also tried this but didn't work: Value <> ''
I couldn't find the answer in any of the stackoverflow questions.

Try this:
declare #t table(ID int, value nvarchar(1000))
insert #t values(-416, 'These are comments for errors'),
(-416, null)
SELECT
COALESCE(MAX(CASE WHEN ID = -416 THEN value END), 'No Error') AS Error_Comments
FROM #t
Result:
These are comments for errors

It would seem that value is an integer. So, your case statement is returning different types, and SQL Server has decided that the type should be an integer. Your string doesn't convert.
So, do an explicit conversion:
MAX(CASE WHEN ID = -416 AND Value IS NOT NULL THEN cast(Value as varchar(255))
ELSE 'No Error'
END) AS Error_Comments
EDIT:
The comment makes a lot of sense. I suppose this should be:
COALESCE(CAST(CASE WHEN ID = -416 AND Value IS NOT NULL THEN VALUE END) as varchar(255)),
'No Error'
)

Related

TSQL CASE unexpectedly processing multiple THEN statements

I have a simple SQL CASE statement that I am trying to interpret the datatype of a variable and then converting it to said format. I have the following sample:
DECLARE #P1 varchar(10) = '2';
SELECT CASE 1
WHEN ISNUMERIC(#P1) THEN (CAST(#P1 AS INT))
WHEN ISDATE(#P1) THEN (CAST(#P1 AS DateTime))
ELSE 'N' END AS Test2P1
I would expect it to return an integer value of 2. However, this is what I get.
Test2P1
1900-01-03 00:00:00.000
However, if I modify the code to just display a character instead of CASTING the variable, I get a different result:
DECLARE #P1 varchar(10) = '2';
SELECT CASE 1
WHEN ISNUMERIC(#P1) THEN 'I'
WHEN ISDATE(#P1) THEN 'D'
ELSE 'N' END AS Test2P1
Then I get a result of: I
Taking this experiment one step further, if I leave the first test returning an 'I' but casting the date, then I get an error:
DECLARE #P1 varchar(10) = '2';
SELECT CASE 1
WHEN ISNUMERIC(#P1) THEN 'I'
WHEN ISDATE(#P1) THEN (CAST(#P1 AS DateTime))
ELSE 'N' END AS Test2P1
Msg 241, Level 16, State 1, Line 3
Conversion failed when converting date and/or time from character string.
It appears that SQL is evaluating multiple instances of THEN statements. However, the ISDATE expression does NOT return true. I am stumped.
In my research, I came across this article [SQL Performance] (https://sqlperformance.com/2014/06/t-sql-queries/dirty-secrets-of-the-case-expression) What he is saying in this article makes complete sense. But I do not see where it applies in this situation as I am never changing the value of the variable.
I have also wrapped my CASE statement in COALESCE(), but it does not appear to help. I wouldn't have expected it to, but I found multiple articles referencing this as a solution to similar problems. This seems like a very simple CASE statement, but I do not know where I am going wrong. Any help is greatly appreciated.
DateTime has a higher datatype precedence in SQL Server than INT does, so your whole CASE is getting cast as DATETIME. You can only return data of a single datatype in one column, thus the need for datatype precedence.
Here is the MSDN article showing precedence.
Although I can't think of a good reason to do this, you could force the case expression to return sql_variant, which can store multiple different types, eg:
DECLARE #P1 varchar(10) = '2';
SELECT CASE 1
when 0 then cast(null as sql_variant)
WHEN ISNUMERIC(#P1) THEN (CAST(#P1 AS INT))
WHEN ISDATE(#P1) THEN (CAST(#P1 AS DateTime))
ELSE 'N' END AS Test2P1

SQL "select case" gives unexpected output

For the love of god can someone please explain me what is going on here.
I am working on some stored procedure bug fixes, after a lot of struggle, I was able to find out where this strange bug is happening so I've made a simple example for the sake of demonstration.
Case 1
DECLARE #test VARCHAR(45) ='0001'
SELECT CASE 0
WHEN -1 THEN ''
WHEN 0 THEN #test
WHEN 1 THEN 12345
END AS 'output'
Case 2
DECLARE #test VARCHAR(45) ='0001'
SELECT CASE 0
WHEN -1 THEN ''
WHEN 0 THEN #test
END AS 'output'
Case 1: output is 1
Case 2: output is 0001 as expected
What happened to the zeros?
strangely it only removes zeros before the number (no matter what number comes at the end), for example DECLARE #test VARCHAR(45) ='1000' works fine, as far case is concerned it is clear that case is zero, if I remove WHEN 0 THEN #test output is null as expected.
Done some research, found only this.
I am using SQL SERVER RC1 2017 as well as SQL SMS.
Thank you for your time.
The difference here is that you have mutliple data types in your THEN/ELSE expressions. In your "CASE 1" you have both int and and varchar datatypes.
int has a higher Data type precedence (Transact-SQL) than a varchar, so the values are returned as an int.
Use the same datatype through out, and this works as you want it to:
DECLARE #test VARCHAR(45) ='0001';
SELECT CASE 0 WHEN -1 THEN ''
WHEN 0 THEN #test
WHEN 1 THEN '12345' --Note that the value in contained in single quotes
END AS [output];
This is because of data type precedence.
The CASE expression documentation says about the returned data type:
Returns the highest precedence type from the set of types in
result_expressions and the optional else_result_expression
Meaning it looks every set of types in the result expressions. Since you have one where the returned data is an INT, then the result of the whole CASE expression is INT (since it has a higher precedence than VARCHAR)
This is happening because the type of the value returned in your last case statement is numeric, so try to change it to
DECLARE #test VARCHAR(45) ='0001'
SELECT CASE 0
WHEN -1 THEN ''
WHEN 0 THEN #test
WHEN 1 THEN '12345'
END AS 'output'

String data right truncation DB2 error

I am receiving the error "String data right truncation" on db2 when I use this query
SELECT BILL_NUMBER, 'PAPERWORK BUT NOT COMPLETE', 'NONE', NULL, '00000',NULL,NULL,TOTAL_CHARGES, NULL FROM TLORDER WHERE
CURRENT_STATUS NOT IN ('COMPLETE','APPRVD','PAPERWISE','BILLD','EDIBILLED','CANCL') AND BILL_TO_CODE NOT LIKE CASE WHEN :INCLUDE_DED = 'No' THEN 'ROCD%' ELSE '1234kkh5656' END
AND EXISTS (SELECT 1 FROM LIST_CHECKIN_AUDIT A WHERE A.BILL_NUMBER = TLORDER.BILL_NUMBER FETCH FIRST 1 ROW ONLY)
AND SITE_ID = :SITE AND DELIVER_BY_END >= CURRENT TIMESTAMP - 3 MONTHS AND COALESCE(PICK_UP_DRIVER,'') = '' AND '00000' =:DRIVER_ID
However when I suppress this line I do not get the error.
AND BILL_TO_CODE NOT LIKE CASE WHEN :INCLUDE_DED = 'No' THEN 'ROCD%' ELSE '1234kkh5656' END
Thanks in advance!
I'd venture to guess that this happens when the value of the :INCLUDE_DED host variable exceeds 2 bytes in length. You do not supply the variable data type, so the query compiler derives it from the right side of the comparison, where the literal 'No' has the length of 2 bytes. If you then assign a value like 'Yes' to the host variable it has to be truncated.
Consider adding an explicit type information to the host variable reference, e.g.:
...WHEN CAST(:INCLUDE_DED AS VARCHAR(10)) = 'No'...
Use the data type appropriate for the range of possible values.
I would first check the datatype of the bill_to_code. You are returning '1234kkh5656' that may exceed the length of the datatype.

Conversion failed when converting the varchar value 645.00 to data type int

I am working on a SQL Query which performs some division operation on a column which is of type decimal(18,4) and should return a value of type decimal but for some reasons, It is giving me an error
Conversion failed when converting the varchar value 645.00 to data type int
I am not making any conversion to the value and yet I have no idea why that is trying to convert it to int.
My query part is as follows
CASE WHEN co.RequestID IS NOT NULL THEN cd.ConsDetQty/1000 WHEN nis.[867_key] IS NOT NULL
THEN q.Quantity/1000 ELSE q2.Quantity/1000 END AS 'Quantity'
May I know if I am wrong anywhere?
TRY THIS
CASE WHEN co.RequestID IS NOT NULL THEN CONVERT(DECIMAL(18,4),cd.ConsDetQty)/1000
WHEN nis.[867_key] IS NOT NULL THEN CONVERT(DECIMIAL(18,4),q.Quantity/1000
ELSE CONVERT(DECIMAL(18,4),q2.Quantity)/1000
END AS 'Quantity'
Your case statement is:
(CASE WHEN co.RequestID IS NOT NULL
THEN cd.ConsDetQty/1000
WHEN nis.[867_key] IS NOT NULL
THEN q.Quantity/1000
ELSE q2.Quantity/1000
END) AS Quantity
For this code to generate an error like that, cd.ConsDetQty, q.Quantity, or q2.Quantity is stored as a string rather than a number. You should fix the column, but you can quickly fix the query by doing:
(CASE WHEN co.RequestID IS NOT NULL
THEN cd.ConsDetQty/1000.0
WHEN nis.[867_key] IS NOT NULL
THEN q.Quantity/1000.0
ELSE q2.Quantity/1000.0
END) AS Quantity
That is a "quick-and-dirty" fix. I do not recommend having implicit conversions in real code. Better to do:
(CASE WHEN co.RequestID IS NOT NULL
THEN cast(cd.ConsDetQty as float)/1000.0
WHEN nis.[867_key] IS NOT NULL
THEN cast(q.Quantity as float)/1000.0
ELSE cast(q2.Quantity as float)/1000.0
END) AS Quantity

Why does the number 0 evaluate to a blank space

This is something that has baffled me before but I have never found an explanation for it. I have a column in a SQL Server 2008 database that is of type smallint. I want to look for any rows where the value is NULL or blank, so I say this:
SELECT *
FROM products
WHERE warranty_dom IS NULL
OR warranty_dom = ''
This returns rows with a value of 0
So why is 0 treated as the equivalent of '' ?
0 is not treated as '' per se. Instead, '' is implicitly cast to an integer, and that cast makes it 0.
Try it yourself:
SELECT CAST(0 AS varchar) -- Output: '0'
SELECT CAST('' AS smallint) -- Output: 0
Also, as mentioned elsewhere: If warranty_dom is of type smallint, then it's not possible for it to be blank in the first place.