SQL ROUND - 算术溢出的实际原因是什么?

标签 sql sql-server double decimal rounding

我的任务是在工作中调试一些旧代码,并遇到了一个问题。该代码是用 VB6 编写的,我们有一个名为 RoundIt() 的函数,它接受一个值,然后将其四舍五入到小数点后两位。令人惊讶的是,该函数(我在 VB6 方面没有太多经验,所以我假设它可能只是该语言的限制)构建一个要执行的 SQL 字符串,以便对值进行四舍五入。

因此,在代码中我们有一个 double 型变量,我将其称为 myVal。在这种特殊情况下,我们收到错误,因为 myVal 的值为 0.997721736173984,并且构建的字符串变为

 SELECT ROUND(0.997721736173984, 2) as RoundedNum

这会导致消息“将表达式转换为数据类型数字时出现算术溢出错误”。据我了解,这是由于值试图舍入为 1 但无法这样做,因为现在返回的数据类型与 ROUND 函数中输入的数据类型不同,而这些数据类型必须相同。

我的问题是,由于这是一个动态构建的 SQL 字符串,因此我们不像使用数据类型声明 SQL 变量并在 ROUND 函数中使用它,我们只是构建字符串 - 那么什么默认情况下的数据类型到底是0.997721736173984?那么尝试返回的数据类型是什么?我猜测是小数(不确定精度或小数位数),并且当它尝试返回四舍五入时,精度或小数位数现在不同值,但我只是想确定一下。

我并不是要求避免算术溢出,或确定不同服务器上的差异,因此这个问题与建议的内容不重复。我的问题是动态构建的 SQL 字符串的输入/输出是什么数据类型,以及为什么这会导致算术溢出错误(如果根据下面的注释,它们具有相同的数据类型)。

最佳答案

如果执行此代码:

select 0.097721736173984 RoundedNum
into #temp

exec tempdb.dbo.sp_help '#temp'

您会发现它将您的文字数字解释为数字(15,15)。

Column_name Type    Computed  Length Prec  Scale Nullable  TrimTrailingBlanks  FixedLenNullInSource  Collation
----------- ------- --------- ------ ----- ----- --------- ------------------- --------------------- ---------
RoundedNum  numeric no        9      15    15    no        (n/a)               (n/a)                 NULL

这意味着您只能使用 15 位数字,并且所有 15 位都必须位于小数点右侧。当您舍入此数字时,它不再适合数据类型,因此会返回错误。

您可以通过显式转换文字来修复它。如:

select round(convert(float,0.997721736173984),2) RoundedNum

您可以选择您想要的任何数据类型,只要它捕获所有预期的有效数字即可。 Float 为您提供了最大的范围灵活性,但需要权衡潜在的准确性损失。如果您知道要四舍五入的所有数字都将小于 1 并且不超过 15 位数字,则 numeric(16,15) 将保存您的原始四舍五入数字。使用数字类型时,您只需考虑数字所属的范围,并确保已分配足够的空间来容纳所有可能的结果。

以下是有关 SQL Server 如何解析表达式中的数字数据类型的一些更有用的信息:

Precision, Scale, and Length (Transact-SQL)

关于SQL ROUND - 算术溢出的实际原因是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35896964/

相关文章:

java - 如何将 List<Object> 转换为逗号分隔的字符串

c# - Excel 导入期间连接到 SQL Server 时因用户错误导致登录失败

c# - 使用继承的自定义 IDataReader 从 IDbCommand 读取

sql-server - 不可信约束

c++ - C++-使用泰勒级数逼近估算cos(x)

java - 安全的?将 Excel 函数转换为 Web 脚本

php - MySQL 错误 - 插入时出现 "You have an error in your SQL syntax"

c# - 如何处理大多数小数不能用二进制准确表示的事实?

java - 生成一系列值之间的随机 double - Java

mysql - 根据连接数量/满足条件的情况拆分或识别记录