Błąd przepełnienia arytmetycznego podczas konwersji wartości liczbowych na typ danych liczbowych


88

Za każdym razem, gdy wykonuję to zapytanie, otrzymuję ten komunikat o błędzie:

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

Ale jeśli zmienię tabelę tworzenia na (7,0), nie otrzymuję komunikatu o błędzie, ale potrzebuję, aby moje dane były wyświetlane jako ułamek dziesiętny. Próbowałem 8,3 nie działa.

Czy jest ktoś, kto może mi w tym pomóc? Każda pomoc będzie bardzo mile widziana.

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
Nie zamierzam nawet zaczynać tego porządkować
m.edmondson

3
Wrzuciłem twój SQL przez program formatujący online tutaj. dpriver.com/pp/sqlformat.htm Nadal można by to zrobić z ręcznym porządkowaniem.
Martin Smith

3
dlaczego nie ma wbudowanej opcji programu formatującego?
czosnek adolfa

6
Microsoft, jeśli nasłuchujesz, pojawia się komunikat o błędzie „Msg 8115, poziom 16, stan 8, wiersz 1 Błąd przepełnienia arytmetycznego podczas konwersji wartości liczbowych na typ danych liczbowych”. można poprawić, wskazując oryginalną wartość, której nie można przekonwertować. To bardzo by pomogło podczas ładowania tabeli zawierającej 100 miliardów wierszy i próby zrozumienia, która wartość jest urażona. Dodanie numeru kolumny SELECT byłoby równie przydatne. NA PRZYKŁAD. SELECT CAST (12345678910 as decimal (12,0)), CAST (12345678910 as decimal (12,2)) ... dodaj ciąg: „Wartość: 12345678910 Kolumna: 2” do komunikatu o błędzie.
wwmbes

Odpowiedzi:


206

Domyślam się, że próbujesz wcisnąć liczbę większą niż 99999,99 do pól dziesiętnych. Zmiana na (8,3) nic nie da, jeśli jest większa niż 99999,999 - musisz zwiększyć liczbę cyfr przed przecinkiem. Możesz to zrobić, zwiększając precyzję (czyli całkowitą liczbę cyfr przed i po przecinku). Możesz pozostawić tę samą skalę, chyba że musisz zmienić liczbę miejsc po przecinku do przechowywania. Spróbuj decimal(9,2)lub decimal(10,2)czy cokolwiek innego.

Możesz to sprawdzić, wykomentowując insert #tempi zobaczyć, jakie liczby podaje instrukcja select i sprawdzić, czy są większe niż może obsłużyć Twoja kolumna.


17
Nie zawracałbym sobie głowy odpowiadaniem na pytania od osób z kontami generowanymi automatycznie; nie rozumieją, gdzie są i nie wracają, gdy już to zrobią. @ user572984: HELLO !? KTOŚ W DOMU? <dotknięcia ekranu> Nie, nie sądzę.
Ola Tuvesson

Usunąłem kropkę liczby dziesiętnej, więc stała się większa. Dzięki!
Wellington Lorindo

Sprawdź, czy Database field lengthrówna się w celu uzyskania DataTableAdaptertej konkretnej kolumny Długość - określony parametr procedury przechowywanej Długość
Elshan

1
@OlaTuvesson, na szczęście, chociaż User572984 jest długi i prawdopodobnie nigdy go nie zobaczy, na dzień dzisiejszy (8 października 2020 r.) Obejrzano go ponad 270 000 razy! Tak więc, zwracając go UnknownUser, skorzystało z niego aż 270 000 użytkowników SO!
Dan

83

Czuję, że muszę wyjaśnić jedną bardzo ważną rzecz dla innych (na przykład mojego współpracownika), którzy natknęli się na ten wątek i otrzymali niewłaściwe informacje.

Podana odpowiedź („Spróbuj dziesiętnie (9,2) lub dziesiętnie (10,2) lub cokolwiek innego”) jest poprawna, ale powód („zwiększ liczbę cyfr przed przecinkiem”) jest błędny.

dziesiętne (p, s) i numeryczne (p, s) określają precyzję i skalę . „Precyzja” nie jest liczbą cyfr po lewej stronie przecinka, ale całkowitą dokładnością liczby.

Na przykład: dziesiętne (2,1) obejmuje od 0,0 do 9,9, ponieważ dokładność wynosi 2 cyfry (od 00 do 99), a skala wynosi 1. dziesiętne (4,1) obejmuje od 000,0 do 999,9 dziesiętne (4,2) obejmuje od 00,00 do 99,99 dziesiętnie (4,3) obejmuje od 0,000 do 9,999


7
Poprzez zwiększenie precyzji i pozostawiając skala taka sama, to jest zwiększenie liczby cyfr przed przecinku. Więc to, co powiedziałem, nie jest złe, ale widzę, że można to źle zrozumieć. Powiedziałem to w ten sposób, ponieważ PO pierwotnie próbował rozwiązać problem, po prostu zwiększając skalę, ale masz rację; to całkowita precyzja, którą należy zwiększyć.
adam0101

1

Jeśli chcesz zmniejszyć rozmiar do dziesiętnego (7,2) od dziesiętnego (9,2), będziesz musiał uwzględnić istniejące dane z wartościami większymi, aby zmieścić się w dziesiętnym (7,2). Albo będziesz musiał usunąć te liczby, przyciąć je w celu dopasowania do nowego rozmiaru. Jeśli nie ma danych dla pola, które próbujesz zaktualizować, zrobi to automatycznie bez problemów


0

Użyj funkcji TRY_CAST w dokładnie taki sam sposób, jak funkcja RZUCANIE. TRY_CAST pobiera ciąg i próbuje rzutować go na typ danych określony po słowie kluczowym AS. Jeśli konwersja nie powiedzie się, TRY_CAST zwraca NULL zamiast niepowodzenia.


1
TRY_CAST przyjmuje wyrażenie, którego wartość jest rzutowana. Nie tylko struny, jak to ująłeś.
TT.

Chociaż pozwoliłoby to na zakończenie procedury bez błędów, odbyłoby się to kosztem brakujących danych. Celem błędu jest wskazanie, że wymagana jest interwencja, aby zapobiec brakującym danych. Twoje rozwiązanie zadziałałoby tylko wtedy, gdy naprawdę nie obchodzi Cię, czy wynik jest obecny, czy nie.
Dan

-2

sprawdź swoją wartość, którą chcesz przechowywać w kolumnie całkowitej. Myślę, że to jest większe niż zakres liczby całkowitej. jeśli chcesz przechowywać wartość większą niż zakres liczb całkowitych. powinieneś użyć typu danych bigint


OP wskazuje, że dana kolumna jest liczbowa, a nie całkowita (na co wskazuje komunikat o błędzie „Błąd przepełnienia arytmetycznego podczas konwersji wartości liczbowych na typ danych liczbowych.”), A najwyżej opublikowana odpowiedź jest poprawna. Twoja odpowiedź poprawnie identyfikuje problem (niewystarczające miejsce na zapisanie wyniku), ale pomija pierwotną intencję pytania.
Dan
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.