转换数值到数值数据类型时出现算术溢出错误。

130
每次运行这个查询时,我都会收到这个错误信息:
Msg 8115, Level 16, State 8, Line 33
Arithmetic overflow error converting numeric to data type numeric.
The statement has been terminated.

但是如果我将创建表格的语句改为(7,0),我就不会收到错误信息。但是我需要我的数据以小数形式显示。我尝试了8,3,但不起作用。
DECLARE @StartDate AS DATETIME
DECLARE @StartDate_y AS DATETIME
DECLARE @EndDate AS DATETIME
DECLARE @temp_y AS DATETIME

SET @temp_y = Dateadd(yy, Datediff(yy, 0, Getdate()), 0)
SET @StartDate_y = Dateadd(dd, 1 - Datepart(dw, Dateadd("ww", -2, @temp_y)),
                                      Dateadd("ww", -2, @temp_y))
SET @StartDate = Dateadd(dd, 1 - Datepart(dw, Dateadd("ww", -2, Getdate())),
                                  Dateadd("ww", -2, Getdate()))
SET @EndDate = Dateadd(dd, 6, @StartDate)

--temp table to hold all cities in list
CREATE TABLE ##temp
  (
     city VARCHAR(50)
  )

INSERT INTO ##temp
VALUES     ('ABERDEEN'),
            ('CHESAPEAKE'),
            ('Preffered-Seafood/CHICAGO'),
            ('Preffered-Redist/CHICAGO'),
            ('CLACKAMAS'),
            ('COLUMBUS'),
            ('CONKLIN'),
            ('DENVER'),
            ('FORT WORTH'),
            ('HANOVER PARK'),
            ('JACKSONVILLE'),
            ('LAKELAND'),
            ('MONTGOMERY'),
            ('PFW-NORTHEAST'),
            ('PFW-SOUTHEAST'),
            ('RIVERSIDE'),
            ('TRENTON,CANADA'),
            ('VERNON')

--temp to hold data for the cities
CREATE TABLE #temp
  (
     city            VARCHAR(50),
     ytdshipments    INT,
     ytdtotalweight  DECIMAL(7, 2) NOT NULL,
     ytdtotalcharges DECIMAL (7, 2) NOT NULL
  --YTDRevperPound decimal (7,2) not null
  )

INSERT INTO #temp
SELECT ##temp.city,
       0,
       0,
       0
FROM   ##temp

INSERT #temp
-- YTD shipments/Charges/Weight by city
SELECT city = CASE
                WHEN nameaddrmstr_1.city IN( 'ABERDEEN', 'CHESAPEAKE', 'CHICAGO'
                                             ,
                                             'CLACKAMAS',
                                             'COLUMBUS', 'CONKLIN', 'DENVER',
                                             'FORT WORTH',
                                             'HANOVER PARK', 'JACKSONVILLE',
                                             'LAKELAND'
                                             ,
                                             'MONTGOMERY'
                                                    ,
                                             'RIVERSIDE', 'TRENTON', 'VERNON' )
              THEN
                CASE
                  WHEN
              nameaddrmstr_1.city = 'CHICAGO'
              AND h.shipr = 'PREFRESVS' THEN 'Preffered-Redist/CHICAGO'
                WHEN
              nameaddrmstr_1.city = 'TRENTON'
              AND nameaddrmstr_1.city = 'CA' THEN 'TRENTON,CANADA'
                ELSE
              nameaddrmstr_1.city
                END
                ELSE 'Other'
              END,
       ytdshipments = COUNT(CONVERT(VARCHAR(10), h.dateshipped, 101)),
       ytdtotalweight =SUM(CASE
                             WHEN h.totaldimwgt > h.totalwgt THEN h.totaldimwgt
                             ELSE h.totalwgt
                           END),
       ytdtotalcharges = SUM (cs.totalestrevcharges)
--YTDRevperPound = convert(decimal(7,2),sum (cs.TotalEstRevCharges )/sum( CASE WHEN h.TotalDimWGT > > h.TotalWGT THEN h.TotalDimWGT ELSE h.TotalWGT END ))
FROM   as400.dbo.hawb AS h WITH(nolock)
       INNER JOIN as400.dbo.chargesummary AS cs
         ON h.hawbnum = cs.hawbnum
       LEFT OUTER JOIN as400.dbo.nameaddrmstr AS nameaddrmstr_1
         ON h.shipr = nameaddrmstr_1.nameaddrcode
WHERE  h.dateshipped >= '01/01/2010'
       AND h.dateshipped <= '12/19/2010'
       --WHERE H.DateShipped >= >= @StartDate_y AND H.dateshipped <= @EndDate 
       AND h.cust IN( 'DARDENREED', 'MAINEDARDE', 'MBMRIVRSDE', 'MBMCOLUMBS',
                      'MBMLAKELND', 'MBMFTWORTH', 'SYGMACOLUM', 'SYGMANETW6',
                      'MAI215', 'MBMMNTGMRY' )
GROUP  BY CASE
  WHEN nameaddrmstr_1.city IN( 'ABERDEEN', 'CHESAPEAKE', 'CHICAGO', 'CLACKAMAS',
                               'COLUMBUS', 'CONKLIN', 'DENVER', 'FORT WORTH',
                               'HANOVER PARK', 'JACKSONVILLE', 'LAKELAND',
                               'MONTGOMERY'
                                      ,
                               'RIVERSIDE', 'TRENTON', 'VERNON' ) THEN CASE
                                                                         WHEN
nameaddrmstr_1.city = 'CHICAGO'
AND h.shipr = 'PREFRESVS' THEN 'Preffered-Redist/CHICAGO'
                                                                         WHEN
nameaddrmstr_1.city = 'TRENTON'
AND nameaddrmstr_1.city = 'CA' THEN 'TRENTON,CANADA'
                                                                         ELSE
nameaddrmstr_1.city
                                                                       END
  ELSE 'Other'
END

SELECT #temp.city                 AS city,
       MAX(#temp.ytdshipments)    AS ytdshipments,
       MAX(#temp.ytdtotalweight)  AS ytdtotalweight,
       MAX(#temp.ytdtotalcharges) AS ytdtotalcharges
FROM   #temp WITH(nolock)
       LEFT OUTER JOIN ##temp
         ON ##temp.city = #temp.city
GROUP  BY #temp.city

DROP TABLE #temp

DROP TABLE ##temp  

16
我甚至不会开始整理那个。 - m.edmondson
4
我把你的 SQL 代码放到这里的在线格式化工具中了。http://www.dpriver.com/pp/sqlformat.htm 不过仍需要手动整理一下。 - Martin Smith
3
为什么没有内置格式化程序的选项? - adolf garlic
50
如果微软在听着的话,“Msg 8115,Level 16,State 8,Line 1:Arithmetic overflow error converting numeric to data type numeric.” 这个错误信息可以通过指示不能转换的原始值来改进。这将有助于在加载一张拥有100亿行数据的表并试图理解哪个值是有问题时更加方便。添加选择列的列数也会再次增加实用性。例如,对于以下选择: SELECT CAST(12345678910 as decimal(12,0)), CAST(12345678910 as decimal(12,2)) …在错误信息中添加字符串:“Value: 12345678910 Column: 2”。 - wwmbes
7个回答

237
我的猜测是你尝试将大于99999.99的数字压缩到小数字段中。如果大于99999.999,则将其更改为(8,3)不会有任何作用-您需要增加小数点前的位数。您可以通过增加精度(即小数点前后的总位数)来实现这一点。您可以保持比例不变,除非您需要更改存储的小数位数。尝试使用decimal(9,2)decimal(10,2)或其他值。
您可以通过注释insert #temp并查看选择语句给出的数字以及它们是否大于列能够处理的数字来测试此操作。

27
我不会费心回答那些使用自动生成账户的人的问题;他们不理解自己正在哪里,也不会再来一次。@user572984: 喂!?有人吗? <敲屏幕> 没有,我就知道。 - Ola Tuvesson
我把小数点去掉了,所以它变大了。谢谢! - Wellington Lorindo
检查数据库字段长度是否等于DataTableAdapter中特定列的长度 - 存储过程的特定参数长度。 - Elshan
11
幸运的是,尽管User572984已经离开很长时间并且可能永远看不到这个消息,但截至今天(2020年10月8日),它已被浏览超过270,000次! 因此,在向UnknownUser回馈时,已使多达270K个Stack Overflow用户受益! - Daniel Bragg

128

我觉得我需要澄清一件非常重要的事情,对于那些(像我的同事)看到这个帖子并得到错误信息的人。

所给出的答案(“尝试decimal(9,2)decimal(10,2)或其他。”)是正确的,但原因(“增加小数点前的数字数量”)是错误的。

decimal(p,s)numeric(p,s)都指定精度和比例。 “精度”不是小数点左侧的数字数量,而是数字的总精度。

例如: decimal(2,1)覆盖 0.09.9,因为精度为2位数字(0099),比例为1

decimal(4,1)覆盖000.0999.9
decimal(4,2)覆盖00.0099.99
decimal(4,3)覆盖0.0009.999


10
通过提高精度而保持刻度不变,您会增加小数点前的数字位数。所以我说的话并没有错,但我可以理解为什么会被误解。我这样说是因为原先的问题是由于只增加了刻度而尝试修复问题的,但您是正确的,需要增加总精度。 - adam0101
1
哇!太感谢了,伙计.. 这个答案真的帮了我很多。 - Mosia Thabo
即使我使用了 decimal(9, 2) 和 decimal(10, 2),我仍然遇到了这个错误。但是 decimal(15, 2) 对我起作用。 - undefined

4

2

使用TRY_CAST函数的方式和CAST函数完全相同。TRY_CAST将一个字符串尝试转换为在AS关键字之后指定的数据类型。如果转换失败,TRY_CAST返回NULL而不是失败。


1
TRY_CAST接受一个表达式,其值被强制转换。不仅仅是字符串,正如你所说的那样。 - TT.
尽管这样做可以让程序不出错地完成,但代价是会有遗漏的数据。错误的目的在于指示需要干预以防止数据缺失。如果您真的不关心结果是否存在,那么您的解决方案才能奏效。 - Daniel Bragg
@d bragg,你说得很对,但是有时候拥有99.9%的数据比花一天时间寻找1个错误的数据点要更好。 - greg

1

如果你想将decimal(9,2)的大小减小到decimal(7,2),你需要考虑现有数据中值较大的情况以适应decimal(7,2)。你必须删除这些数字或将其截断以适应新的大小。如果该字段没有数据,则更新时会自动完成,没有问题。


0

我解决这些问题的方法是尝试隔离选择语句。

注释掉字段,直到您可以确定哪个字段实际上是有问题的。

一旦你可以说:Select from

然后你可以添加 Cast(field as numeric(4,6)) [tryMe]

这样就可以选择N行,然后引发错误。 然后你就可以把铸造下去,看看第N+1个值是什么。

结果通常是令人惊讶的…否则你就不会阅读这篇文章了!

今天我遇到一个问题,我正在计算税费,金额为 Numeric(7,4)。 问题最终是我有一个订单欠1000美元的税。

Numeric(7,4)只允许小数点左侧有3位数字。 噢!


-2

检查您要存储在整数列中的值。我认为这大于整数范围。如果您想存储大于整数范围的值,则应使用bigint数据类型


1
OP指出问题中的列是数字类型,而不是整数类型(如错误信息“转换数值型到数值型时算术溢出错误”的提示所示),置顶答案正确地解决了这个问题。您的答案正确地识别出了问题(存储结果的空间不足),但错过了问题的原始意图。 - Daniel Bragg

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接