Erro de estouro aritmético ao converter numérico em tipo de dados numérico


87

Continuo recebendo esta mensagem de erro sempre que executo esta consulta:

Msg 8115, Level 16, State 8, Line 33
Arithmetic overflow error converting numeric to data type numeric.
The statement has been terminated.

Mas se eu alterar a tabela de criação para (7,0), não recebo a mensagem de erro. Mas preciso que meus dados sejam exibidos como decimais. Eu tentei 8,3 não funciona.

Existe alguém que pode me ajudar a resolver isso? Qualquer ajuda será muito apreciada.

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
Eu nem vou começar a arrumar isso
— m.edmondson

3
Joguei seu SQL através do formatador online aqui. dpriver.com/pp/sqlformat.htm Ainda poderia fazer com uma arrumação manual embora.
— Martin Smith

3
por que a opção de um formatador não está embutida?
— adolf garlic

5
Microsoft, se você estiver ouvindo, a mensagem de erro "Msg 8115, Nível 16, Estado 8, Linha 1 Erro de estouro aritmético ao converter numérico em tipo de dados numérico." poderia ser melhorado indicando o valor original que não pôde ser convertido. Isso ajudaria muito ao carregar uma tabela de 100 bilhões de linhas e tentar entender qual valor era ofensivo. Adicionar o número da coluna de um SELECT seria útil novamente. POR EXEMPLO. SELECIONE CAST (12345678910 como decimal (12,0)), CAST (12345678910 como decimal (12,2)) ... adicione a string: "Valor: 12345678910 Coluna: 2" à mensagem de erro.
— wwmbes de

Respostas:


203

Meu palpite é que você está tentando espremer um número maior que 99999,99 em seus campos decimais. Alterá-lo para (8,3) não fará nada se for maior que 99999.999 - você precisa aumentar o número de dígitos antes do decimal. Você pode fazer isso aumentando a precisão (que é o número total de dígitos antes e depois do decimal). Você pode deixar a escala igual, a menos que precise alterar quantas casas decimais armazenar. Tente decimal(9,2)ou decimal(10,2)ou qualquer outra coisa.

Você pode testar isso comentando o insert #tempe ver quais números a instrução select está fornecendo e ver se eles são maiores do que sua coluna pode suportar.


17
Eu não me importaria em responder a perguntas de pessoas com contas geradas automaticamente; eles não entendem onde estão e não voltam depois de terem sua dose. @ user572984: OLÁ !? ALGUEM EM CASA? <tela de toque> Não, acho que não.
— Ola Tuvesson

Eu havia tirado o ponto do número decimal, então ele ficou maior. Obrigado!
— Wellington Lorindo

Verifique Database field lengthigual para DataTableAdaptero Comprimento dessa coluna específica - Comprimento do parâmetro específico do Procedimento Armazenado
— Elshan

80

Sinto que preciso esclarecer uma coisa muito importante para outras pessoas (como meu colega de trabalho) que se depararam com este tópico e receberam as informações erradas.

A resposta dada ("Tente decimal (9,2) ou decimal (10,2) ou qualquer outra coisa.") Está correta, mas o motivo ("aumente o número de dígitos antes do decimal") está errado.

decimal (p, s) e numérico (p, s) especificam uma precisão e uma escala . A "precisão" não é o número de dígitos à esquerda do decimal, mas sim a precisão total do número.

Por exemplo: decimal (2,1) cobre 0,0 a 9,9, porque a precisão é de 2 dígitos (00 a 99) e a escala é 1. decimal (4,1) cobre 000,0 a 999,9 decimal (4,2) cobre 00,00 a 99,99 decimal (4,3) cobre 0,000 a 9,999


7
Aumentando a precisão e deixando a escala igual, você está aumentando o número de dígitos antes do decimal. Portanto, o que eu disse não está errado, mas vejo como pode ser mal interpretado. Eu disse dessa forma porque o OP estava originalmente tentando corrigir o problema apenas aumentando a escala, mas você está correto; é a precisão total que precisa ser aumentada.
— adam0101

1

Se você quiser reduzir o tamanho para decimal (7,2) de decimal (9,2), você terá que contabilizar os dados existentes com valores maiores para caber no decimal (7,2). Ou você terá que excluir esses números e truncá-los para caber no novo tamanho. Se não houver dados para o campo que você está tentando atualizar ele o fará automaticamente sem problemas


0

Use a função TRY_CAST exatamente da mesma maneira da função CAST. TRY_CAST pega uma string e tenta convertê-la em um tipo de dados especificado após a palavra-chave AS. Se a conversão falhar, TRY_CAST retorna um NULL em vez de falhar.


1
TRY_CAST recebe uma expressão, cujo valor é convertido. Não apenas strings como você coloca.
— TT.
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.