将numeric数据类型转换为numeric的算术溢出错误

时间:2013-12-13 06:12:35

标签: sql sql-server-2008 tsql

我在表格中有以下列

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位数?

我也得到了

  

将numeric数据类型转换为数字

的算术溢出错误

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

的列的表中
INSERT INTO TNAME2(SIZE, PRICE, TOTAL)
   SELECT 
       SIZE, PRICE, SIZE * PRICE AS TOTAL 
   FROM 
       TNAME

5 个答案:

答案 0 :(得分:1)

试试这个。

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

答案 1 :(得分:1)

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

OR

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

答案 2 :(得分:1)

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

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中进行其他类型的舍入,则必须创建自己的函数。

答案 3 :(得分:0)

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

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

答案 4 :(得分:0)

试试这个

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

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