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  
user572984
fonte
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.

adam0101
fonte
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

Dan
fonte
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

Benoy John
fonte
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.

Bharat
fonte
1
TRY_CAST recebe uma expressão, cujo valor é convertido. Não apenas strings como você coloca.
TT.