Why do I have to cast a float to a decimal and then a decimal into a varchar? - sql

Please see the DDL below:
create table #TestFloat (id int, floattest float)
insert into #TestFloat values (1,65478)
insert into #TestFloat values (1,65478888)
insert into #TestFloat values (1,42)
How would I cast the float values to a varchar? I have tried this:
select top 1 cast(floattest as varchar(15)) from #TestFloat
which produces this:
6.54789e+007
and this:
select top 1 id,Str(floattest, 15, 0) from #TestFloat
' 65478'
I have put quotes in the above to demonstrate that it is casted into a char.
This works (taken from this question: How to convert Float to Varchar in SQL):
select CAST(CAST(floattest AS DECIMAL(20)) AS VARCHAR(20)) from #TestFloat
Why do I have to cast into a decimal first?

How about
SELECT FORMAT(floattest,'R') FROM #TestFloat
(Or 'G' or 'N' depending on your use)
https://msdn.microsoft.com/library/dwhawy9k.aspx
or
SELECT LTRIM(STR(floattest,8,0)) FROM #TestFloat
(Pick your precision and scale to suit but watch out for rounding)
https://msdn.microsoft.com/en-AU/library/ms189527.aspx
You also ask "why"? You should probably have a read of the MSDN pages on SQL Server types starting here: https://msdn.microsoft.com/en-AU/library/ms187752.aspx and this answer Difference between numeric, float and decimal in SQL Server

You can use convert function in sql server
select top 1 CONVERT (NVARCHAR(15),floattest) from #TestFloat

First cast to decimal and then to varchar.
Query
SELECT CAST
(
CAST(floattest AS DECIMAL(25,0))
AS VARCHAR(MAX)
)
FROM #TestFloat;
SQL Fiddle demo

Related

How do I convert a float to varchar without loss of decimal places? SQL Server 2012

SQL Server 2012: converting a float to varchar is removing decimal places.
For example:
select convert(varchar, cast(834.7833 as float))
returns a varchar with 834.783.
How do I convert a float to varchar without loss of decimal places?
This is a similar question to this unanswered question:
How does convert(varchar, float) decide how many decimal places to keep?
Why do you need to do a CAST(... AS FLOAT) at all??
Try these snippets - they return the full number of decimal points:
SELECT
CONVERT(VARCHAR(20), 834.7833)
SELECT
CAST(834.7833 AS VARCHAR(20))
Both of these output this result:
834.7833

How to convert to decimal when data is number but not convert when data is text?

I am using SQL Server 2008 r2.
There are 31 fields (D1-D31) as varchar and keep 2 format data as number and text such as 'SD' and '123.456'.
I use the command for Data Base Expert of Crystal Report like this.
select
case
when D1 in('SD') then d1
when D1 is NULL then ''
else convert(decimal(7,2),d1)
end
.
.
.
case D2-D31
from Rec2019 where ID ='P0009'
It's show Error converting data type varchar to numeric.
How to fix it ? please..
A column has one datatype so you cannot place DECIMAL and VARCHAR values inside same column. I think you want to round numeric-ish values. In that case you can use the following:
CASE
WHEN ISNUMERIC(d1) = 1 AND d1 NOT IN ('+', '-', '$') THEN CAST(CAST(d1 AS DECIMAL(7, 2)) AS VARCHAR(9))
WHEN d1 IS NULL THEN ''
ELSE d1
END
Demo on db<>fiddle
For SQL Server 2008, you can check using ISNUMERIC, where as SQL Server 2012+ have TRY_CONVERT or TRY_CAST to make it simple like following.
TRY_CONVERT(decimal(7,2), D1)
Since ISNUMERIC had some small downsides, for instance with scientific notation of numbers, I would use TRY_CAST, like this: (note: SQLServer 2012+)
CREATE TABLE #T (ColA VARCHAR (10))
INSERT INTO #T VALUES ('1'), ('A'), ('2');
SELECT *, TRY_CAST (ColA AS DECIMAL (4,2)) AS Numb
FROM #T
Sidenote: One column has one data-type, you cannot combine datatypes in one column in SQL Server.
To convert when the data is number, and not convert when the data is text, you can check the type with the isnumeric function.
select
case when isnumeric(D1) then convert(decimal(7,2), D1) else null end as D1_asnumeric
from XXX

Sql convert string with comma separator to double

How can I convert '-35,321.42' to '35321.42' in sql ?
thanks
One method is to just convert it to money:
select cast('-35,321.42' as money)
If you want this in a different type, then you can convert that:
select cast(cast('-35,321.42' as money) as decimal(10, 2))
For instance.
The equivalent of "double" in SQL Server is float (see here), so you can do:
select cast(cast('-35,321.42' as money) as float)

tSQL - Conversion from varchar to numeric works for all but integer

I have a table with numbers in a varchar(255) field. They're all greater than one and have multiple decimal places. I'd like to convert them to integers. According to every web site I've consulted, including this one on StackOverflow, either of these should work:
SELECT CAST(VarcharCol AS INT) FROM MyTable
SELECT CONVERT(INT, VarcharCol) FROM MyTable
These both work for me for every kind of numeric value but integer - I can convert to float, decimal, etc. just fine, but trying to convert to integer gives me the following error:
Conversion failed when converting the varchar value '7082.7758172'
to data type int.
I've worked around the problem by converting to data type Decimal(6,0), which works fine. But just for my education, can anyone tell me why converting to data type int (or integer) gives me an error? Thanks.
Converting a varchar value into an int fails when the value includes a decimal point to prevent loss of data.
If you convert to a decimal or float value first, then convert to int, the conversion works.
Either example below will return 7082:
SELECT CONVERT(int, CONVERT(decimal(12,7), '7082.7758172'));
SELECT CAST(CAST('7082.7758172' as float) as int);
Be aware that converting to a float value may result, in rare circumstances, in a loss of precision. I would tend towards using a decimal value, however you'll need to specify precision and scale values that make sense for the varchar data you're converting.
Actually whether there are digits or not is irrelevant. The . (dot) is forbidden if you want to cast to int. Dot can't - logically - be part of Integer definition, so even:
select cast ('7.0' as int)
select cast ('7.' as int)
will fail but both are fine for floats.
Presumably, you want to convert values before the decimal place to an integer. If so, use case and check for the right format:
SELECT (case when varcharcol not like '%.%' then cast(varcharcol as int)
else cast(left(varcharcol, chardindex('.', varcharcol) - 1) as int)
end) IntVal
FROM MyTable;
Try this
declare #v varchar(20)
set #v = 'Number'
select case when isnumeric(#v) = 1 then #v
else #v end
and
declare #v varchar(20)
set #v = '7082.7758172'
select case when isnumeric(#v) = 1 then #v
else convert(numeric(18,0),#v) end
Try this query:
SELECT cast(column_name as type) as col_identifier FROM tableName WHERE 1=1
Before comparing, the cast function will convert varchar type value to integer type.
SELECT
convert(numeric(18,5),Col1), Col2
FROM DBname.dbo.TableName
WHERE isnumeric(isnull(Col1,1)) <> 0

SQL IsNumeric Returns True but SQL Reports 'Conversion Failed'

Assuming the following data:
Column1 (data type: varchar(50))
--------
11.6
-1
1,000
10"
Non-Numeric String
I have a query, which is pulling data from this column and would like to determine if the value is a number, then return it as such in my query. So I am doing the following
SELECT CASE
WHEN IsNumeric(Replace(Column1, '"', '')) = 1 THEN Replace(Column1, '"', '')
ELSE 0
END AS NumericValue
SQL is reporting back:
Conversion failed when converting the varchar value '11.6' to data type int.
Why? I have also tried to force cast this:
SELECT CASE
WHEN IsNumeric(Replace(Column1, '"', '')) = 1 THEN cast(Replace(Column1, '"', '') AS float)
ELSE 0
END AS NumericValue
And I got:
Error converting data type varchar to float.
You need to replace comma with a period:
CAST(REPLACE(column, ',', '.') AS FLOAT)
SQL Server outputs decimal separator defined with locale, but does not unterstand anything but a period in CASTs to numeric types.
First convert the string to money, then covert it to any other numeric format since money type gives a true numeric string always. You will never see an error then.
Try the following in your query, and you'll know what I am talking about. Both will return 2345.5656. The Money datatype is rounded to 4 decimal places, and hence the casting causes rounding to 4 decimal places.
SELECT CAST('2,345.56556' as money), CAST('$2,345.56556' as money)
Cast( cast('2,344' as money) as float) will work perfectly or
cast( cast('2,344' as money) as decimal(7,2)) will also work.
Even cast(CAST('$2,345.56556' as money) as int ) will work perfectly rounding it to nearest integer.
There are many issues with SQL isnumeric. For example:
select isnumeric('1e5')
This will return 1 but in many languages if you try to convert it to a number it will fail. A better approach is to create your own user defined function with the parameters you need to check for:
http://www.tek-tips.com/faqs.cfm?fid=6423
ISNUMERIC returns 1 when the input expression evaluates to a valid integer, floating point number, money or decimal type;
So the problem is it is a valid number but not a valid int.
Kyle,
I think this solves the problem. The problem lies in the fact that the ELSE clause initializes your result to be an INTEGER. By making an explicit typecast to FLOAT and adding the suggestion of Quassnoi, it seems to work.
DECLARE #MyTable TABLE (Column1 VARCHAR(50))
INSERT INTO #MyTable VALUES('11.6')
INSERT INTO #MyTable VALUES('-1')
INSERT INTO #MyTable VALUES('1,000')
INSERT INTO #MyTable VALUES('10" ')
INSERT INTO #MyTable VALUES('Non-Numeric String')
SELECT CASE WHEN ISNUMERIC(REPLACE(Column1,'"','')) = 1 THEN REPLACE(REPLACE(Column1,'"',''), ',', '.') ELSE CAST(0 AS FLOAT) END
FROM #MyTable
Regards,
Lieven
IsNumeric(' ') also returns 1, but then CAST as int blows up. Brendan above says write your own function. He is correct.
This solution does not work in all cases (specifically numbers with money and/or thousand separators). Concatenate an exponent representation to the end of the number which is represented by a string...ISNUMERIC() works fine from there. Examples below:
-- CURRENT ISNUMERIC RESULTS
SELECT ISNUMERIC('11.6'); --1
SELECT ISNUMERIC ('-1'); --1
SELECT ISNUMERIC('1,000'); --1
SELECT ISNUMERIC('10"'); --0
SELECT ISNUMERIC('$10'); --1
-- NEW ISNUMERIC RESULTS
SELECT ISNUMERIC('11.6'+'e+00'); --1
SELECT ISNUMERIC ('-1'+'e+00'); --1
SELECT ISNUMERIC('1,000'+'e+00'); --0
SELECT ISNUMERIC('10"'+'e+00'); --0
SELECT ISNUMERIC('$10'+'e+00'); --0
This, at the very least, standardizes the format for using the REPLACE() function.
I have just meet this issue.
You can try this solution if you don't mind about limitation of decimal length.
CONVERT(numeric, CONVERT(money, '.'))
NOTE:
It is supported in SQL Server 2008 or above.
Money range is : -922,337,203,685,477.5808 to 922,337,203,685,477.5807 - four decimals.