SQL Server - 浮点数与 varchar

Posted

技术标签:

【中文标题】SQL Server - 浮点数与 varchar【英文标题】:SQL Server - float vs varchar 【发布时间】:2019-11-28 14:53:45 【问题描述】:

在 SQL Server 中,我将十进制数据存储在表中(从不用于连接或过滤)。此十进制数据是可变的 - 80% 的时间它具有单个数字值(1、4、5),其余 20% 具有 16 位小数(0.8999999761581421、3.0999999046325684)。

我想知道是否可以使用varchar 而不是float 节省任何存储空间,或者我是否应该坚持使用float,因为这是数字数据?

【问题讨论】:

decimal float“我有十进制数据”真的是指“我有浮点数据”吗?如果不是,您的数据实际上是decimal 而不是float?无论哪种方式,都不要使用varchar 来存储数字数据。 @varun 。 . .这在我看来很可疑。我猜整数是某种代码,小数是真实值——数据不应该混合在一个列中。 无论您是保留FLOAT 还是使用DECIMAL,都不要使用字符串类型来存储数字数据,无论存储考虑如何。 唯一 可能合适的时间是,如果您非常具体地需要存储从外部系统接收到的数据完全,因为您得到它,一个字符一个字符,即使它也有数值。这显然不是其中一种情况。如果存储甚至是一个问题,您应该在数据类型之前考虑行和页面压缩之类的事情,因为混淆字符串和数字是一个巨大的痛苦来源。 【参考方案1】:

始终使用最合适的数据类型!由于这显然是 数字 数据 - 请使用数字类型。这将允许例如对值求和,按这些值排序 - 这些是数字 - 所以对待和存储它们!!

如果您需要支持分数,可以使用 FLOATREAL,但它们因舍入错误等而臭名昭著。使用 DECIMAL(p,s) 可以避免这些陷阱 - 它稳定、精确,不易出现舍入误差。所以这将是我合乎逻辑的选择。

请参阅official MS docs for DECIMAL,了解有关如何定义p(精度 - 总位数)和s(刻度 - 小数点后的位数)的详细信息.

顺便说一句:这些存储在更少字节中,而varchar 列的大小足以容纳这些值!

【讨论】:

如果此数值数据用于任何数值计算,我同意您的看法。但事实并非如此。它是科学价值之一,并按原样显示在报告中。那么,您仍然建议使用小数而不是 varchar 吗?因为我的理解是 float 会占用固定数量的字节,这与 varchar 不同。谢谢! @varun: YES!!!!!! 正如我所提到的 - decimal 很可能会使用 FEWER b> 空间而不是可比较的 varchar - 更有理由选择 numerical 数据类型 @varun:等到你突然不得不按这些列之一对 SELECT 进行排序 - 如果你为此使用 varchar - 祝你好运! -这只会导致无休止和不必要的悲伤和头痛 - 不要这样做。如果它看起来像一个数字,嘎嘎声像一个数字,闻起来像一个数字 - 它是一个数字,那么你应该无论如何将它处理和存储作为一个数字 【参考方案2】:

这是一个有趣的观察:

从数学值0.9开始

将其转换为二进制数。出于同样的原因,1/3 不能用以 10 为底的有限位数表示,数字 0.9 也不能用以 2 为底的有限位数表示。确切的数学值是:

0.1 1100 1100 1100 1100 1100 1100 1100 ... 永远重复“1100”。

让我们将此值存储在 IEEE-754 单精度浮点值中。 (在 SQL Server 中,这称为REAL 类型)。为此,我们必须舍入到 23 个有效位。结果是:

0.1 1100 1100 1100 1100 1100 11 

将其转换为精确的十进制等效值,您会得到:

0.89999997615814208984375

将其四舍五入到小数点后 16 位。你得到:

0.8999999761581421

巧合的是,您作为示例显示的值。

如果你对3.1做同样的事情,你会得到3.0999999046325684

有没有可能你所有的输入都是简单的小数点后一位数字,已经存储为浮点值,然后转换回十进制?

【讨论】:

以上是关于SQL Server - 浮点数与 varchar的主要内容,如果未能解决你的问题,请参考以下文章

无法将 varchar 转换为浮点数

在 SQL Server 2008 中将数据从浮点类型的 Excel 导入 varchar

RODBC 将浮点数作为 SQL Server 中的字符

浮点数在数据库 Sql Server 中存储为 Real

为啥 SQL 浮点数与 C# 浮点数不同

将 Varchar 转换为浮点数失败