添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

I have a float column with numbers of different length and I'm trying to convert them to varchar.

Some values exceed bigint max size, so I can't do something like this

cast(cast(float_field as bigint) as varchar(100))

I've tried using decimal, but numbers aren't of the same size, so this doesn't help too

CONVERT(varchar(100), Cast(float_field as decimal(38, 0)))

Any help is appreciated.

UPDATE:

Sample value is 2.2000012095022E+26.

Another note: this pads on the left with spaces. If this is a problem combine with LTRIM:

SELECT LTRIM(STR(float_field, 25, 5))
                @Martin Smith, It seems to work, but the same way as decimal, so I'm not sure if it's the real value(last ten digits are zero). I guess, that the real value was lost. Thank you!
– hgulyan
                Sep 15, 2010 at 9:44
                @hgulyan -the last ten digits are zero because that is what the last parameter is for in the Str function.  The number of digits after the decimal point.  Did you read the link i posted?  Change the zero to 10.  Select LTRIM(Str(float_field, 38, 10))
– codingbadger
                Sep 15, 2010 at 9:52
                I wish there was a warning in SSMS "hey, when you convert that erroneous float telephone field to text, be prepared to get a nice telephone number with scientific notation! we are not smart enough to ltrim(str) first"...
– pkExec
                Mar 26, 2015 at 18:34

The only query bit I found that returns the EXACT same original number is

CONVERT (VARCHAR(50), float_field,128)

See http://www.connectsql.com/2011/04/normal-0-microsoftinternetexplorer4.html

The other solutions above will sometimes round or add digits at the end

UPDATE: As per comments below and what I can see in https://msdn.microsoft.com/en-us/library/ms187928.aspx:

CONVERT (VARCHAR(50), float_field,3)

Should be used in new SQL Server versions (Azure SQL Database, and starting in SQL Server 2016 RC3)

+1 for @adinas, the float value is converted as it but with the exception of 0 float value being converted as 0.0E0. I needed to convert the float field to varchar as I need to display NA when NULL and 0 as it is. I achieved this by adding CASE statement in the query as below; CASE WHEN float_field IS NULL THEN 'NA' WHEN float_field = 0 THEN '0' ELSE CONVERT(VARCHAR, float_field, 128) END AS float_As_VChar – fujiFX Mar 2, 2015 at 3:15 According to the document on Microsoft - msdn.microsoft.com/en-us/library/ms187928.aspx, the 128 syntax is included for legacy reasons and may be depreceated in a future version – Mike Turner Apr 12, 2016 at 18:00 128 is deprecated but 3 seems to be the replacement for it in the most recent SQL Server releases. – user3524983 Apr 17, 2016 at 17:45 the suggestion to use CONVERT (VARCHAR(50), float_field,128) was not exact and introduced rounding error CONVERT (VARCHAR(50), float_field,3) did not – CervEd Jan 2, 2021 at 10:34

this is the solution I ended up using in sqlserver 2012 (since all the other suggestions had the drawback of truncating fractional part or some other drawback).

declare @float float = 1000000000.1234;
select format(@float, N'#.##############################');

output:

1000000000.1234

this has the further advantage (in my case) to make thousands separator and localization easy:

select format(@float, N'#,##0.##########', 'de-DE');

output:

1.000.000.000,1234
                This will remove the digits after the decimal, if any. Hence, this solution is not accurate.
– RushabhG
                Feb 13, 2017 at 11:56
                I don't get it. Field value is 2.2000012095022E+26. What's the solution? There isn't any?
– hgulyan
                Sep 15, 2010 at 9:12
                you cannot get more digits by converting to string than there are digits stored in the original value.
– devio
                Sep 15, 2010 at 9:18
                There was some kind of problem with the data. I just need to update that value with a 15 digit float. I'll accept your answer, because it describes main problem I had with this data. Thank you.
– hgulyan
                Sep 15, 2010 at 9:46
select @test
set @test1 = convert (decimal(10,5), @test)
select cast((@test1) as varchar(12))
Select  LEFT(cast((@test1) as varchar(12)),LEN(cast((@test1) as varchar(12)))-1)
  

Returns nvarchar if one of the input arguments is of the nvarchar data type; otherwise, REPLACE returns varchar.
Returns NULL if any one of the arguments is NULL.

tests:
null ==> [NULL]
1.11 ==> 1.11
1.10 ==> 1.1
1.00 ==> 1
0.00 ==> 0
-1.10 ==> -1.1
0.00001 ==> 1e-005
0.000011 ==> 1.1e-005

If you use a CLR function, you can convert the float to a string that looks just like the float, without all the extra 0's at the end.

CLR Function

[Microsoft.SqlServer.Server.SqlFunction(DataAccess = DataAccessKind.Read)]
[return: SqlFacet(MaxSize = 50)]
public static SqlString float_to_str(double Value, int TruncAfter)
  string rtn1 = Value.ToString("R");
  string rtn2 = Value.ToString("0." + new string('0', TruncAfter));
  if (rtn1.Length < rtn2.Length) { return rtn1; } else { return rtn2; }

Example

create table #temp (value float)
insert into #temp values (0.73), (0), (0.63921), (-0.70945), (0.28), (0.72000002861023), (3.7), (-0.01), (0.86), (0.55489), (0.439999997615814)
select value,
       dbo.float_to_str(value, 18) as converted,
       case when value = cast(dbo.float_to_str(value, 18) as float) then 1 else 0 end as same
from   #temp
drop table #temp

Output

value                  converted                  same
---------------------- -------------------------- -----------
0.73                   0.73                       1
0                      0                          1
0.63921                0.63921                    1
-0.70945               -0.70945                   1
0.28                   0.28                       1
0.72000002861023       0.72000002861023           1
3.7                    3.7                        1
-0.01                  -0.01                      1
0.86                   0.86                       1
0.55489                0.55489                    1
0.439999997615814      0.439999997615814          1

Caveat

All converted strings are truncated at 18 decimal places, and there are no trailing zeros. 18 digits of precision is not a problem for us. And, 100% of our FP numbers (close to 100,000 values) look identical as string values as they do in the database as FP numbers.

Modified Axel's response a bit as it for certain cases will produce undesirable results.

DECLARE @MyFloat [float];
SET @MyFloat = 1000109360.050;
SELECT REPLACE(RTRIM(REPLACE(REPLACE(RTRIM((REPLACE(CAST(CAST(@MyFloat AS DECIMAL(38,18)) AS VARCHAR(max)), '0', ' '))), ' ', '0'),'.',' ')),' ','.')
DECLARE @F FLOAT = 1000000000.1234;
SELECT @F AS Original, CAST(FORMAT(@F, N'#.##############################') AS VARCHAR) AS Formatted;
SET @F = 823399066925.049
SELECT @F AS Original, CAST(@F AS VARCHAR) AS Formatted
UNION ALL SELECT @F AS Original, CONVERT(VARCHAR(128), @F, 128) AS Formatted
UNION ALL SELECT @F AS Original, CAST(FORMAT(@F, N'G') AS VARCHAR) AS Formatted;
SET @F = 0.502184537571209
SELECT @F AS Original, CAST(@F AS VARCHAR) AS Formatted
UNION ALL SELECT @F AS Original, CONVERT(VARCHAR(128), @F, 128) AS Formatted
UNION ALL SELECT @F AS Original, CAST(FORMAT(@F, N'G') AS VARCHAR) AS Formatted;

I just came across a similar situation and was surprised at the rounding issues of 'very large numbers' presented within SSMS v17.9.1 / SQL 2017.

I am not suggesting I have a solution, however I have observed that FORMAT presents a number which appears correct. I can not imply this reduces further rounding issues or is useful within a complicated mathematical function.

T SQL Code supplied which should clearly demonstrate my observations while enabling others to test their code and ideas should the need arise.

WITH Units AS 
   SELECT 1.0 AS [RaisedPower] , 'Ten' As UnitDescription
   UNION ALL
   SELECT 2.0 AS [RaisedPower] , 'Hundred' As UnitDescription
   UNION ALL
   SELECT 3.0 AS [RaisedPower] , 'Thousand' As UnitDescription
   UNION ALL
   SELECT 6.0 AS [RaisedPower] , 'Million' As UnitDescription
   UNION ALL
   SELECT 9.0 AS [RaisedPower] , 'Billion' As UnitDescription
   UNION ALL
   SELECT 12.0 AS [RaisedPower] , 'Trillion' As UnitDescription
   UNION ALL
   SELECT 15.0 AS [RaisedPower] , 'Quadrillion' As UnitDescription
   UNION ALL
   SELECT 18.0 AS [RaisedPower] , 'Quintillion' As UnitDescription
   UNION ALL
   SELECT 21.0 AS [RaisedPower] , 'Sextillion' As UnitDescription
   UNION ALL
   SELECT 24.0 AS [RaisedPower] , 'Septillion' As UnitDescription
   UNION ALL
   SELECT 27.0 AS [RaisedPower] , 'Octillion' As UnitDescription
   UNION ALL
   SELECT 30.0 AS [RaisedPower] , 'Nonillion' As UnitDescription
   UNION ALL
   SELECT 33.0  AS [RaisedPower] , 'Decillion' As UnitDescription
SELECT UnitDescription
   ,              POWER( CAST(10.0 AS FLOAT(53)) , [RaisedPower] )                                                             AS ReturnsFloat
   ,        CAST( POWER( CAST(10.0 AS FLOAT(53)) , [RaisedPower] )  AS NUMERIC (38,0) )                                        AS RoundingIssues
   , STR(   CAST( POWER( CAST(10.0 AS FLOAT(53)) , [RaisedPower] )  AS NUMERIC (38,0) ) ,   CAST([RaisedPower] AS INT) + 2, 0) AS LessRoundingIssues
   , FORMAT(      POWER( CAST(10.0 AS FLOAT(53)) , [RaisedPower] )  , '0')                                                     AS NicelyFormatted
FROM Units
ORDER BY [RaisedPower]
        

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.