0

我正在研究一个使用浮点数据类型来存储应该只有两位小数(美元和美分)的值的数据库。

只要更新 float 列的人执行 ROUND,使用 float 似乎可以正常工作。当然,这并不总是发生,然后当 SUM 完成时,它总是与显示的内容相差几美分,因为显示被格式化为仅显示两个小数位。该数据库有数百个使用浮点数的表,能够自动对浮点数列进行舍入会很有帮助。

这可以做到吗?

可以在 INSERT 和 UPDATE 上使用 TRIGGER 在列上执行 ROUND 吗?

如果可以,您能否展示如何编写 TRIGGER 代码并推荐它?

还有其他想法吗?

我们正在使用SQL Server 2005

这是一篇提出问题的帖子,会计应用程序美元金额使用浮点数还是小数?,我喜欢这样的一个回应

“您真的应该考虑使用某种类型的定点/任意精度数字包(例如,Java BigNum、python 十进制模块),否则您将陷入痛苦的世界”。

4

3 回答 3

3

你可以做触发器,这根本不是不合理的使用它们。预插入和预更新触发器应该可以正常工作。

此外,您可以进行一次性修复,例如:

update tbl set column = round(column * 100) / 100

语法可能并不完美,但你应该明白。

但我不确定我是否理解您的“差了几分钱”的话。您必须将相当多的浮点数相加才能使错误累积到 0.01。您使用的列定义是什么?

当然,货币类型的十进制列定义之一会更好地获得完美的准确性,但您可能会失去 DBMS 之间的可移植性。

于 2009-02-05T11:05:12.917 回答
3

如果您可以控制系统,是否可以使用 DECIMAL /MONEY/NUMERIC 数据类型而不是 FLOAT?

毕竟,这是您提到的问题的重点。

如果不是这样,并且像我们许多人一样,您被迫生活在那个痛苦的世界中,那么您的触发建议会起作用。但是,我更愿意以不同的方式控制它...
- 不允许应用程序或用户直接对表进行写访问
- 通过 SP 强制访问

我还看到了一个系统,其中对一个(输入/保持)表进行了写访问。然后,该表上有一个触发器,可以将数据复制(并格式化/验证)到真实表中。

于 2009-02-05T11:15:45.500 回答
1

我不认为你可以通过四舍五入得到你想要的。对浮点数进行四舍五入将无法准确可靠地工作:无论您做什么,您都将尝试对二进制数应用十进制四舍五入,而除了 2 的幂之外,这对任何东西都不准确。

您只能通过使用专门为此目的设计的十进制数据类型来获得任意子整数数量的准确数据库存储的十进制表示。这些数据类型通常使用某种形式的压缩十进制存储(效率低于二进制),例如 2009 存储为0x2009.

如果使用CONVERT函数会发生什么?您是否尝试过使用类似的查询?

CONVERT(money, your_float_column)

从长远来看,我想我会考虑在我的表中添加一个具有所需类型的列,并通过插入后/更新触发器维护其值,然后随着时间的推移切换我的所有代码以使用该列。

然后我会追捕并惩罚那些认为将金额存储在浮动中是个好主意的人......

于 2009-02-05T13:16:16.257 回答