我的付款表存储在VARCHAR
这是来自该字段的示例数据:
10.01
55.11
最近,作为新请求的一部分,我们必须从VARCHAR
列中存储的数字中删除小数点。
所以,我有这个:
CONVERT(BIGINT, CONVERT(REAL, RTRIM(LTRIM(@amt))) * 100) as PaymentAmount
转换为REAL
(无法从BIGINT
转换为VARCHAR
),再乘以100,然后转换为BIGINT
现在问题是,有时,在转换过程中,最终结果会减少1美分。
示例:'10.11'
转换为1010
,10.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.00
到10.99
的数字进行转换,在100个值的范围内,错误的数字是:
10.11
转换为1010
10.15
转换为1014
10.19
转换为1018
10.23
转换为1022
该范围内的所有其他值都很好。奇怪的是,11.11
可以很好地转换为1111
。
所以问题是,为什么这样做并且模式是什么?从DataType MSDN REAL不是一个精确的数字,但FLOAT也是如此,但浮点数适用于整个范围。
编辑:我没有提到varchar
的大小为1000。
答案 0 :(得分:3)
您收到了转化差异,因为正如您所说,REAL
不是一个确切的数字......
您可能会发现REAL
和FLOAT
之间存在差异,因为每种类型都有不同的尾数,这会导致精度损失不同。我确定您可以找到一个不同的数字,这会在使用FLOAT
时导致类似的精度损失。
如果您想了解这些浮点类型的更多内部工作原理,请查看What Every Computer Scientist Should Know About Floating-Point Arithmetic。
但除了转换差异之外,你的解决方案还有很多......
如果这些是付款...为什么要将金额存储在VARCHAR
字段中,不带小数点?这引入了此数据存在大量完整性问题的可能性。
接下来,MONEY
data type不是一个更适合存储的数据类型......你知道吗...钱?
接下来,为什么您无法直接从VARCHAR
转换为BIGINT
? This 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)