SQL数字数据类型截断值?

时间:2011-10-27 08:20:13

标签: sql sql-server sql-server-2005 decimal numerical-methods

我真的希望那里有一位SQL大师可以帮助解决这个问题(如果之前已经回答过,我会道歉。我确实尝试找到类似的帖子,但无济于事):

declare @theanswer numeric(38,16)

select @theanswer = 0.01 / 0.0074464347
select @theanswer

以上结果为1.3429245542165000

但以下(对我来说看起来一样)

declare @val1 numeric(38,16);
declare @val2 numeric(38,16);

set @val1 = 0.01;
set @val2 = 0.0074464347;

select @val1/@val2

结果是1.342924并截断它?

有什么想法吗?

1 个答案:

答案 0 :(得分:3)

要获得结果的真实精度和比例(@ val1 / @ val2),我将执行此T-SQL脚本

DECLARE @val1 NUMERIC(38,16);
DECLARE @val2 NUMERIC(38,16);

SET @val1 = 0.01;
SET @val2 = 0.0074464347;

SELECT @val1/@val2
        ,SQL_VARIANT_PROPERTY(@val1/@val2, 'BaseType')  [BaseType]
        ,SQL_VARIANT_PROPERTY(@val1/@val2, 'Precision') [Precision]
        ,SQL_VARIANT_PROPERTY(@val1/@val2, 'Scale')     [Scale]

结果将是:

(No column name)    BaseType    Precision   Scale
1.342924            numeric         38          6

因此,结果精度为38,结果标度为6。 MSDN具有关于算术运算的精度和比例的一些细节。这些信息可以在这里找到:Precision, Scale, and Length (Transact-SQL)

Operation = e1 / e2
Result precision = p1 - s1 + s2 + max(6, s1 + p2 + 1)
Result scale * = max(6, s1 + p2 + 1)

使用这些公式,我们可以编写下一个T-SQL脚本来获得结果的理论精度和比例(@ val1 / @ val2):

SELECT   @p1 = 38   --or CONVERT(INT, SQL_VARIANT_PROPERTY(@val1, 'Precision'))
        ,@s1 = 16   --or CONVERT(INT, SQL_VARIANT_PROPERTY(@val1, 'Scale'))
        ,@p2 = 38   --or CONVERT(INT, SQL_VARIANT_PROPERTY(@val2, 'Precision'))
        ,@s2 = 16   --or CONVERT(INT, SQL_VARIANT_PROPERTY(@val2, 'Scale'));

--SELECT    @p1 [@p1], @s1 [@s1], @p2 [@p2], @s2 [@s2];

SELECT  @p_result = @p1 - @s1 + @s2 +   CASE 
                                            WHEN 6 >= @s1 + @p2 + 1 THEN 6 
                                            WHEN 6 < @s1 + @p2 + 1 THEN @s1 + @p2 + 1 
                                        END
        ,@s_result =    CASE 
                            WHEN 6 >= @s1 + @p2 + 1 THEN 6 
                            WHEN 6 < @s1 + @p2 + 1 THEN @s1 + @p2 + 1 
                        END;

SELECT  @p_result [@p_result], @s_result [@s_result];

结果是:

@p_result   @s_result
93          55

因此,对于此算术运算(@ val1 / @ val2),在theory中,精度和比例为9355,但实际精度和比例为{{1} }和38。 实际精度为38,因为结果精度和比例绝对最大值为38

关于实际结果量表(6)MSDN,目前尚不清楚:“当结果精度大于38时,相应的比例缩小,以防止结果的整数部分被截断“

为了看“相应的比例是如何降低的”我使用具有相同比例的6值执行了上述测试(脚本1用于实际精度和比例,脚本2用于理论精度和比例)但是不同的尺度(从16到38)。这些测试的结果是:

NUMERIC

检查这些结果:

1.我看到实际结果量表的算术级数:从22到6,步骤-1。

2.另外,如果@ val1和@ val2的标度是常数(/* Result prec. Result scale (T=theoretical value, R=real value) T-R T-R --@val1 and @val2 data type 49-38 33-22 --NUMERIC(16, 16) 51-38 34-21 --NUMERIC(17, 16) 53-38 35-20 --NUMERIC(18, 16) 55-38 36-19 --NUMERIC(19, 16) ... 61-38 39-16 --NUMERIC(22, 16) -- <-- data type for [real] result scale 16 ... 77-38 47-8 --NUMERIC(30, 16) 79-38 48-7 --NUMERIC(31, 16) 81-38 49-6 --NUMERIC(32, 16) 83-38 50-6 --NUMERIC(33, 16) 85-38 51-6 --NUMERIC(34, 16) ... 93-38 55-6 --NUMERIC(38, 16) */ ),则@ val1&amp;之间存在逆相关。 @ val2 precision(从16到32)和[real]结果比例(从16到6)。

3.如果@ val1和@ val2精度为32或更高(NUMERIC(...,16)),则[实际]结果标度始终为6 =&gt;这是你的情况。

4.如果需要更大的[真实]结果比例(超过6),则需要使用较低的精度@ val1 和@ val2:NUMERIC(32->38,16)

NUMERIC(22, 16)