【发布时间】:2016-05-11 20:54:22
【问题描述】:
我们正在对从一个 SQL Server 迁移到另一个 SQL Server 的数据进行一些验证。我们正在验证的一件事是某些数字数据已正确传输。数值数据在新系统中存储为浮点数据类型。
我们知道浮点数据类型存在许多问题,不能保证精确的数字准确性,并且不能对浮点数据使用精确相等比较。我们无法控制数据库架构或数据类型,这些都是单独的问题。
在这种特定情况下,我们尝试做的是验证某些比率值是否已正确传输。具体的数据验证规则之一是所有的比率都应该在小数点右边不超过4位。
因此,例如,有效比率如下所示:
.7542
1.5423
无效的比率是:
.12399794301
12.1209377
我们要做的是计算小数点右侧的位数,并找出浮点值右侧超过四位的所有情况。我们一直在使用 SUBSTRING、LEN、STR 和其他几个函数来实现这一点,我相信如果我们将数字字段类型为十进制并将其转换为 char,它会起作用。 但是,我们在尝试将 float 转换为 char 值时发现 SQL Server 似乎总是在两者之间转换为十进制。例如,在 SQL Server 企业管理器中查询时,相关字段会显示此值:
1.4667
尝试使用 SQL Server 推荐的函数转换为字符串:
LTRIM(RTRIM(STR(field_name, 22, 17)))
返回这个值:
1.4666999999999999
我期望 如果 SQL Server 直接从 float 转换为 char 的值(然后我们可以从中修剪尾随零):
1.4667000000000000
SQL Server 中是否有任何方法可以直接从浮点数转换为字符,而无需经过中间转换为十进制的过程?我们还尝试了 CAST 和 CONVERT 函数,得到的结果与 STR 函数相似。
涉及的 SQL Server 版本:SQL Server 2012 SP2
谢谢。
【问题讨论】:
-
我猜这个值实际上是
1.4666999999999999。当您在企业管理器中选择它时,它会为您四舍五入。 -
假设这些数字根据 IEEE 754 标准在内部存储为 64 位浮点数,则 1.4667 将存储为(完全)对应于十进制数 1.466699999999999892708046900224871933460235595703125 的二进制表示。正确四舍五入到小数点后 16 位,即 1.4666999999999999,这正是你得到的。或许你可以四舍五入到更少的小数位,这样最后这些小错误就会被隐藏?
-
谢谢大家。我相信你们俩都是正确的,问题的根源是 a) 没有可以表示为浮点数的精确数字 1.4667 和 b) 企业管理器实际上在显示这些数字之前对其进行了四舍五入。 (stackoverflow.com/questions/8099575/…) 提供了更多关于 SQL Server 管理工作室中舍入的背景知识。我们正在尝试使用链接文章中提到的其他 SQL 客户端(例如 SQLCMD)来验证我们获得的输出。
标签: sql sql-server string floating-point