【问题标题】:Arithmetic overflow error converting numeric datatype to numeric将数值数据类型转换为数值的算术溢出错误
【发布时间】:2013-12-31 20:26:26
【问题描述】:

我在表格中有以下列

SIZE NUMERIC(14,5)    
PRICE NUMERIC(14,5)    

当我执行这个select 查询时,

SELECT SIZE,
PRICE,
SIZE*PRICE AS TOTAL 
FROM TNAME

我得到了结果:

1.00000 90.00000    90.0000000000
1.00000 90.00000    90.0000000000
1.00000 90.00000    90.0000000000
1.00000 100.00000   100.0000000000
1.00000 30.00000    30.0000000000

我想知道为什么第三列返回小数点后 10 位?

我也明白了

将数值数据类型转换为数值时出现算术溢出错误

将结果插入另一个具有相同数据类型的相同列的表中

INSERT INTO TNAME2(SIZE, PRICE, TOTAL)
   SELECT 
       SIZE, PRICE, SIZE * PRICE AS TOTAL 
   FROM 
       TNAME

【问题讨论】:

  • 我想知道为什么第三列返回小数点后 10 位? 那应该是什么?
  • 两个因素的乘积在逻辑上会导致更高的精度。如果四舍五入,可能会丢失信息。

标签: sql sql-server-2008 tsql


【解决方案1】:

试试这个。

SELECT SIZE,
PRICE,
CAST(SIZE*PRICE AS numeric(14,5))AS TOTAL 
FROM TNAME

【讨论】:

  • 插入检查表TNAME2和TName的表定义时没有错误。
  • @Snehal:请检查我的编辑。第三列在TNAME 中不可用,这是一个计算列,我想将其值插入TNAME2 表的列TOTAL NUMERIC(15,5)
【解决方案2】:
INSERT  INTO TNAME2
SELECT    SIZE ,
Price ,
CAST(SIZE * PRICE AS NUMERIC(15, 5))
FROM      TNAME

INSERT  INTO TNAME2 (SIZE,Price,TOTAL)
SELECT    SIZE ,
Price ,
CAST(SIZE * PRICE AS NUMERIC(15, 5)) AS TOTAL
FROM      TNAME

【讨论】:

    【解决方案3】:

    关于第一个问题,小数位数,没有错。这是我们在学校学习的基本的日常乘法:将两个十进制数相乘产生一个数字,其十进制位数与操作数的十进制位数之和一样多。整数位数最多为操作数整数位数之和。

    10.11 乘以12.13 得到122.6343。如果 SQL Server 违反了这个基本规则并任意截断结果,那将是非常尴尬的。

    因此,当您尝试将产品存储在接受较少数字的列中时,您会收到溢出错误。 SQL Server 不会自动更改位数,因为无法确定正确的操作。

    有一个lot of ways 你可以处理这个,这取决于你愿意承受的精度损失:

    • 截断多余的数字,即将它们扔掉,最多接受一个单位的损失。如果您存储总计,这可能会变成一大笔钱。
    • 四舍五入到所需的位数。听起来很直观,但是中间值呢,即在您的情况下为 0.00005?它应该是 0.0001 还是 0.0000?所以我们有
    • 四舍五入,其中 0.5 变为 1,导致每个条目最多损失 0.5
    • 向下,当它变​​为0时,损失相同
    • 四舍五入到偶数或奇数,即四舍五入到最接近的奇数或偶数,平均而言,这会产生最小的损失。虽然这听起来很奇怪,但它在 IEEE 754 中定义的标准。它也被称为banker's rounding,因为它用于簿记以最大程度地减少因截断而造成的损失。

    如果您想存储更少的数字,您需要决定是否需要截断多余的数字或如何对数字进行四舍五入,然后在代码中自行完成。

    在您的情况下,您可以将CAST 用于所需精度的数字。这将执行四舍五入,其中 0.00005 变为 0.0001,例如:

    INSERT INTO TNAME2(SIZE, PRICE, TOTAL)
    SELECT 
       SIZE, PRICE, CAST(SIZE * PRICE as numeric(14,5)) AS TOTAL 
    FROM 
       TNAME
    

    SQLFiddle here

    如果位数不超过 14,这将起作用,否则您将不得不更改表格字段的类型。

    如果您想在 SQL 中进行其他类型的舍入,则必须创建自己的函数。

    【讨论】:

      【解决方案4】:

      得到以下有用的链接。 Multiplication of numerics 根据此链接,您可以尝试如下查询

      SELECT SIZE,
      PRICE,
      CAST(SIZE*PRICE AS numeric(28,5))AS TOTAL 
      FROM TNAME
      

      【讨论】:

        【解决方案5】:

        试试这个

        SELECT SIZE,PRICE,CONVERT(numeric(14,5), SIZE*PRICE) AS TOTAL 
        FROM TNAME
        

        在插入中写同样的查询,它必须工作

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2021-10-29
          • 1970-01-01
          • 1970-01-01
          • 2013-05-27
          相关资源
          最近更新 更多