1

我有一个表,其中的付款存储在一个类型的列中VARCHAR

这是来自该领域的示例数据:

10.01
55.11

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

所以,我有这个:

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

转换为REAL(不能转换为BIGINTfrom VARCHAR),乘以 100 然后转换为BIGINT

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

示例:'10.11'转换为1010,10.151014

简单的测试方法:

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

查询的结果是1014

我通过将转换从REALtoFLOAT和删除转换为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 也是如此,但 float 适用于整个范围。

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

4

2 回答 2

3

你得到了转换差异,因为就像你说的那样,REAL这不是一个精确的数字......

您可能会看到 和 之间的差异REALFLOAT因为每种类型都有不同的尾数,这将导致精度损失不同。我相信您可以找到一个不同的数字,这会导致在使用FLOAT.

如果您想了解更多这些浮点类型的内部工作原理,请查看每个计算机科学家应该了解的关于浮点运算的知识

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

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

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

接下来,为什么不能直接从VARCHARto转换BIGINT这是一个完全有效的转换

DECLARE @amt VARCHAR(50)
SET @amt = ' 1001'
SELECT CONVERT(BIGINT, @amt*100) as PaymentAmount
于 2013-01-29T18:34:26.920 回答
3
declare @amt varchar(1000)
set @amt = '10.15'

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

SQL小提琴

于 2013-01-29T18:34:42.507 回答