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


88

每当我运行此查询时,我都会不断收到此错误消息:

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  

9
我什至不打算开始整理一下
m.edmondson 2011年

3
我通过此处的在线格式化程序删除了您的SQL。dpriver.com/pp/sqlformat.htm仍然可以手动整理。
马丁·史密斯

3
为什么没有内置格式化程序的选项?
阿道夫·大蒜

6
Microsoft,如果您正在收听,则错误消息为“ Msg 8115,级别16,状态8,行1将数字转换为数据类型数字的算术溢出错误”。可以通过指示无法转换的原始值来改进。当装入一个1000亿行的表并尝试了解哪个值有问题时,这将有很大帮助。添加SELECT的列号将同样有用。例如。SELECT CAST(12345678910作为小数(12,0)),CAST(12345678910作为小数(12,2))...将字符串:“ Value:12345678910 Column:2”添加到错误消息中。
wwmbes

Answers:


206

我的猜测是您试图将一个大于99999.99的数字压入十进制字段。如果将其更改为(8,3),则大于99999.999则无济于事-您需要增加小数点的位数。您可以通过提高精度(即小数点前后的位数)来实现。除非需要更改要存储的小数位数,否则可以将刻度保持不变。尝试decimal(9,2)decimal(10,2)或其他。

您可以通过注释掉进行测试,insert #temp并查看select语句为您提供的数字,并查看它们是否大于您的列可以处理的数字。


17
我不会理会那些使用自动生成帐户的人的问题;他们不了解他们在哪里,一旦解决了问题,他们就不会回来。@ user572984:你好!?有人在家吗?<拍子屏幕>不,不是这样。
奥拉·图维森

我已经去除了十进制数字的点,所以它变得更大了。谢谢!
惠灵顿洛林多2014年

检查是否Database field length等于DataTableAdapter该特定列的“长度”-存储过程的特定参数“长度”
Elshan 2015年

1
@OlaTuvesson,所幸的是,尽管User572984很长,而且可能永远不会看到这一点,但截至今天(2020年10月8日),它已被浏览超过270K次! 因此,在将其偿还给UnknownUser时,它使多达270K SO用户受益!

82

我觉得我需要澄清一件非常重要的事情,对于其他人(例如我的同事),他们遇到了这个问题并得到了错误的信息。

给出的答案(“尝试十进制(9,2)或十进制(10,2)或其他。”)是正确的,但是原因(“增加十进制前的位数”)是错误的。

小数(p,s)和数字(p,s)都指定了Precision和Scale。“精度”不是小数点左边的位数,而是数字的总精度。

例如:十进制(2,1)覆盖0.0到9.9,因为精度是2位数字(00到99)并且小数位是1。十进制(4,1)覆盖000.0到999.9十进制(4,2)覆盖了00.00到9.9 99.99十进制(4,3)覆盖0.000至9.999


7
通过提高精度和离开的规模一样,你小数点前增加位数。所以我说的没错,但是我确实知道它可能会被误解。我这样说是因为OP最初只是试图通过扩大规模来解决问题,但是您是正确的。这是需要提高的总精度。
adam0101

1

如果要将大小从小数(9,2)减小为小数(7,2),则必须考虑现有数据,其值应大于小数(7,2)。您将必须删除这些数字,然后将其截断以适合您的新大小。如果您尝试更新的字段没有数据,它将自动完成而不会出现问题


0

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


1
TRY_CAST采用一个表达式,其值是强制转换的。不只是您所说的字符串。
TT。

尽管这样做可以使例程完成而不会出错,但这是以丢失数据为代价的。该错误的目的是指示需要干预才能防止丢失数据。仅当您真的不在乎结果是否存在时,您的解决方案才有效。

-2

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


OP表示所讨论的列是数字列,而不是整数列(如错误消息“将数字转换为数据类型数字的算术溢出错误”所示),并且最上面的答案正确地解决了这一问题。您的答案正确地识别了问题(没有足够的空间存储结果),但是错过了问题的初衷。
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.