Convert empty nchar to numeric value - sql

I'm using SQL Server 2019.
select convert(bigint, ' ')
returns 0
select convert(numeric, ' ')
returns:
Error converting data type varchar to numeric.
Can anyone tell me why the behaviour between these two datatypes is different? I would have expected, that the second example returns 0 or 0.00.

From CAST and CONVERT:
"SQL Server also returns an error when an empty string (" ") is converted to numeric or decimal."
It's the documented behavior, that's why.

It's just the way it is implemented. Casting an empty string or a string with only spaces to an INT data type will result in 0. Some people regard this as logical behavior, others don't.
For a DECIMAL type, the same cast fails.
However, this is only true for spaces! Trying to cast other whitespace characters like tabs, carriage return or linefeed characters to an INT type will also fail.
If you want failed casts to return NULL instead of producing an error, you can use TRY_CONVERT instead:
select try_convert(numeric, ' ')
If you want both to behave in the same way (whether that would mean both returning NULL or both returning 0 or 0.0 respectively) you need to somehow work your way around it.
To have the cast to INT return NULL, you could e.g. combine TRY_CONVERT with NULLIF:
select try_convert(bigint, nullif(' ', ''))
This will also produce NULL for strings containing only (any number of) spaces.
If on the other hand, you prefer to see 0.0 results for empty strings or strings containing only spaces when casting to NUMERIC, you can filter these out explicitly:
select case when val like ' ' or val = '' then 0.0
else try_convert(numeric(5,1), val)
end as val
from strings
This db<>fiddle shows what results the different queries yield for various whitespace and non-whitespace string input.

Related

Error when a field is declared as NULL in where clause

We have a query running on sybase and we get the below error for certain account numbers but works for others
sqlanywhere error 1009145: Data type conversion not possible integer(10,0) to varchar(6,0)
(oselib/hos_dfe.cxx 13811)
So i started debugging it and found out the error was coming from a field in the format of an int( values are like 20,200,721). This field is declared as NULl in the where statment like FieldA is NULL.
So when i changed to STR(FieldA) it started to work and it all good now.
But my question is why would that cause the above error. Its an integer and the statement is only checking for values which are null and the values in the db are [NULL].
Any ideas why that is happening with this field?
This is NOT an integer: '10,000'. It is a string with digits and commas.
This is NOT an integer: '10000'. It is a string with just digits.
Sybase can only convert strings that are all digits to integers, and commas are not digits. (Okay, it can also handle leading negative signs too.) You can remove the commas using replace():
cast(replace(col, ',', '') as int)

Sql Server using Convert and Replace together in the same statement

I wanted to double check my logic for a query in SQL Server.
The idea is that I am able to feed the following values and it will make sure the result is a decimal with four trailing digits.
Possible values for #LABORQTY:
1,200
1,200.42
1200 (Integer)
1200.42
1200 (As a String)
1200.42 (As a String)
When the value is a string, it will give the error:
Error converting data type nvarchar to numeric.
Here is my code:
CONVERT(DECIMAL(12, 4), REPLACE(#LABORQTY, ',', ''))
The output each time though should be decimal:
1200.4200
Your question is really confused, but I'll answer according to the following parameters:
#laborqty is a VARCHAR
#laborqty may somehow come to contain any of the following values:
'1200'
'1200.42'
'1,200'
'1,200.42'
In which case CONVERT(DECIMAL(12, 4), REPLACE(#LABORQTY, ',', '')) will indeed produce a decimal with up to 4 digits of fractional precision. Whether your query tool/programming language will output it as 1200.4200 or not is another matter entirely; it might well just output 1200.42 and drop the trailing zeroes
If you're getting Error converting data type varchar to numeric. still, there is some other character data (not comma) in your numeric string
If you definitely want the trailing zeroes, format it into a string before you output
FORMAT(CONVERT(decimal(12,4), '1200.42'), '0.0000')
This will generate a string with 4 trailing zeroes
you can use :
select CAST ( REPLACE( '1,200.4' , ',','') AS decimal(17,4))

What does this statement mean in SQL? (isnull(cast(field_name as CHAR), '') = ")

I am new to SQL and I am looking at established queries that we have, can anyone explain what this statement means in the WHERE clause
(isnull(cast(field_name as CHAR), '') = '').
Breaking down each statement:
CAST(field_name AS CHAR) converts the field_name column to a CHAR
This value is then passed as the first argument to the ISNULL() with the second being an empty string ''.
ISNULL(CAST(field_name AS CHAR), '')
This takes the result of the cast, and if it's a NULL value, returns '' instead.
Finally, it checks if that result is equal to ''.
Essentially, it's checking for NULL or empty string values in one fell swoop.
juergen d is correct. I'd add that it tries to cast the field to alphanumeric before it checks if it is null or blank. If the field's data type has no defined conversion to type CHAR, the query will error out. Have a look at this regarding conversions/casts.
T-SQL Data Types and Conversion Info

SQL Server's ISNUMERIC function

I need to checking a column where numeric or not in SQL Server 2012.
This my case code.
CASE
WHEN ISNUMERIC(CUST_TELE) = 1
THEN CUST_TELE
ELSE NULL
END AS CUSTOMER_CONTACT_NO
But when the '78603D99' value is reached, it returns 1 which means SQL Server considered this string as numeric.
Why is that?
How to avoid this kind of issues?
Unfortunately, the ISNUMERIC() function in SQL Server has many quirks. It's not exactly buggy, but it rarely does what people expect it to when they first use it.
However, since you're using SQL Server 2012 you can use the TRY_PARSE() function which will do what you want.
This returns NULL:
SELECT TRY_PARSE('7860D399' AS int)
This returns 7860399
SELECT TRY_PARSE('7860399' AS int)
https://msdn.microsoft.com/en-us/library/hh213126.aspx
Obviously, this works for datatypes other than INT as well. You say you want to check that a value is numeric, but I think you mean INT.
Although try_convert() or try_parse() works for a built-in type, it might not do exactly what you want. For instance, it might allow decimal points, negative signs, and limit the length of digits.
Also, isnumeric() is going to recognize negative numbers, decimals, and exponential notation.
If you want to test a string only for digits, then you can use not like logic:
(CASE WHEN CUST_TELE NOT LIKE '%[^0-9]%'
THEN CUST_TELE
END) AS CUSTOMER_CONTACT_NO
This simply says that CUST_TELE contains no characters that are not digits.
Nothing substantive to add but a couple warnings.
1) ISNUMERIC() won't catch blanks but they will break numeric conversions.
2) If there is a single non-numeric character in the field and you use REPLACE to get rid of it you still need to handle the blank (usually with a CASE statement).
For instance if the field contains a single '-' character and you use this:
cast(REPLACE(myField, '-', '') as decimal(20,4)) myNumField
it will fail and you'll need to use something like this:
CASE WHEN myField IN ('','-') THEN NULL ELSE cast(REPLACE(myField, '-', '') as decimal(20,4)) END myNumField

SQL List Function Removing Precision

I am using the LIST function to create a ';' delimited list of values. The type is numeric (19,2). For some reason the precision appears to be ignored when using the list function. When performing a simple select on this column the values look good, ie "12.00". However, if I use a LIST() my results are of format "12.000000"
This is my LIST usage:
LIST(case when tblWOService.PricePerVehicle is null then ' ' else CONVERT(decimal(19,2),tblWOService.PricePerVehicle end,';')
The CONVERT does not change the result. Any ideas?
Thanks!
Have you tried explicitly converting your empty string?
LIST(
case when tblWOService.PricePerVehicle is null then CONVERT(decimal(19,2),' ')
else CONVERT(decimal(19,2),tblWOService.PricePerVehicle) end,';'
)
I've run into a similar datatype issue with CASE statements in T-SQL.