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

时间:2016-03-09 16:18:57

标签: sql sql-server double decimal rounding

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

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

 SELECT ROUND(0.997721736173984, 2) as RoundedNum

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

我的问题是,由于这是一个动态构建的SQL字符串,它不像我们用数据类型声明一个SQL变量并在ROUND函数中使用它,我们只是构建字符串 - 所以是什么确切地说,0.997721736173984的数据类型是默认的吗?那么什么是试图返回的数据类型呢?我猜一个小数(不确定精度或比例),并且当它试图返回舍入时精度或比例现在是不同的价值,但我只想确定。

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

2 个答案:

答案 0 :(得分:4)

如果您执行此代码:

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)

答案 1 :(得分:0)

您可以使用SQL_VARIANT_PROPERTY功能查找数据类型。

SELECT
    SQL_VARIANT_PROPERTY(x.y, 'BaseType')   AS DataType,
    SQL_VARIANT_PROPERTY(x.y, 'Precision')  AS Precision,
    SQL_VARIANT_PROPERTY(x.y, 'Scale')      AS Scale
FROM
    (
        VALUES
            (0.997721736173984)
    ) AS x(y)
;

在这种情况下,你有一个数字(15,15)。由于所有可用空间都分配给了比例,因此无法舍入为1。

使用CAST明确设置数据类型将解决您的问题。

    SELECT
        ROUND(CAST(0.997721736173984 AS NUMERIC(16, 15)), 2)