转换存储在SQL Server中的VARCHAR字段中的数字

时间:2013-01-29 18:17:20

标签: sql-server

我的付款表存储在VARCHAR

类型的列中

这是来自该字段的示例数据:

10.01
55.11

最近,作为新请求的一部分,我们必须从VARCHAR列中存储的数字中删除小数点。

所以,我有这个:

CONVERT(BIGINT, CONVERT(REAL, RTRIM(LTRIM(@amt))) * 100) as PaymentAmount

转换为REAL(无法从BIGINT转换为VARCHAR),再乘以100,然后转换为BIGINT

现在问题是,有时,在转换过程中,最终结果会减少1美分。

示例:'10.11'转换为101010.15转换为1014

简单的测试方法:

SELECT CONVERT(BIGINT, CONVERT(REAL, RTRIM(LTRIM(10.15))) * 100) as PaymentAmount

查询结果为1014

我修改了此问题,方法是将转化从REAL更改为FLOAT,然后将转化转换为BIGINT

另一种解决方法是使用CAST,如下所示:

CAST(@amt as float)*100  as PaymentAmount

我使用10.0010.99的数字进行转换,在100个值的范围内,错误的数字是:

  • 10.11转换为1010
  • 10.15转换为1014
  • 10.19转换为1018
  • 10.23转换为1022

该范围内的所有其他值都很好。奇怪的是,11.11可以很好地转换为1111

所以问题是,为什么这样做并且模式是什么?从DataType MSDN REAL不是一个精确的数字,但FLOAT也是如此,但浮点数适用于整个范围。

编辑:我没有提到varchar的大小为1000。

2 个答案:

答案 0 :(得分:3)

您收到了转化差异,因为正如您所说,REAL不是一个确切的数字......

您可能会发现REALFLOAT之间存在差异,因为每种类型都有不同的尾数,这会导致精度损失不同。我确定您可以找到一个不同的数字,这会在使用FLOAT时导致类似的精度损失。

如果您想了解这些浮点类型的更多内部工作原理,请查看What Every Computer Scientist Should Know About Floating-Point Arithmetic

但除了转换差异之外,你的解决方案还有很多......

如果这些是付款...为什么要将金额存储在VARCHAR字段中,不带小数点?这引入了此数据存在大量完整性问题的可能性。

接下来,MONEY data type不是一个更适合存储的数据类型......你知道吗...钱?

接下来,为什么您无法直接从VARCHAR转换为BIGINTThis is a perfectly valid conversion

DECLARE @amt VARCHAR(50)
SET @amt = ' 1001'
SELECT CONVERT(BIGINT, @amt*100) as PaymentAmount

答案 1 :(得分:3)

declare @amt varchar(1000)
set @amt = '10.15'

select cast(replace(@amt, '.', '') as bigint)

SQL Fiddle