Sayıyı sayısal veri türüne çevirirken aritmetik taşma hatası


91

Bu sorguyu her çalıştırdığımda şu hata mesajını alıyorum:

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

Ancak, oluşturma tablosunu (7,0) olarak değiştirirsem, hata mesajını almıyorum, ancak verilerimin ondalık olarak görüntülenmesine ihtiyacım var. 8,3 denedim çalışmıyor.

Bunu yapmama yardım edebilecek biri var mı? Herhangi bir yardım çok takdir edilecektir.

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  

11
Bunu
düzeltmeye

4
SQL'inizi burada çevrimiçi biçimlendiriciye attım. dpriver.com/pp/sqlformat.htm Yine de manuel bir düzenleme ile yapabilirdi.
Martin Smith

3
biçimlendirici seçeneği neden yerleşik değil?
adolf sarımsak

12
Microsoft, dinliyorsanız, "Msg 8115, Level 16, State 8, Line 1 Aritmetik taşma hatası sayısal veri türüne sayısal dönüştürülüyor." dönüştürülemeyen orijinal değer belirtilerek geliştirilebilir. Bu, 100 milyar satırlık bir tablo yüklerken ve hangi değerin rahatsız edici olduğunu anlamaya çalışırken çok yardımcı olur. Bir SELECT'in sütun numarasını eklemek yine aynı derecede yararlı olacaktır. ÖRNEĞİN. SEÇİN CAST (12345678910 ondalık (12,0)), CAST (12345678910 ondalık (12,2)) ... "Değer: 12345678910 Sütun: 2" dizesini hata mesajına ekleyin.
wwmbes

Yanıtlar:


208

Benim tahminim 99999.99'dan büyük bir sayıyı ondalık alanlarınıza sıkıştırmaya çalıştığınızdır. (8,3) bunu değiştirme şey yapmak için gitmiyor 99999.999 daha 's büyüktür eğer - Eğer basamak sayısını artırmak için gerekmez önce ondalık. Bunu, hassasiyeti artırarak yapabilirsiniz (bu, ondalıktan önceki ve sonraki toplam basamak sayısıdır). Kaç ondalık basamağı saklayacağınızı değiştirmeniz gerekmedikçe ölçeği aynı bırakabilirsiniz. Deneyin decimal(9,2)ya decimal(10,2)da her neyse.

Bunu yorumlayarak test edebilir insert #tempve select ifadesinin size hangi sayıları verdiğini görebilir ve sütununuzun kaldırabileceğinden daha büyük olup olmadıklarını görebilirsiniz.


18
Otomatik oluşturulmuş hesapları olan kişilerden gelen soruları yanıtlamakla uğraşmam; nerede olduklarını anlamıyorlar ve düzelttikten sonra geri dönmüyorlar. @ user572984: MERHABA !? EVDE HERKES? <dokunur ekranı> Hayır, öyle düşünmedim.
Ola Tuvesson

Ondalık sayı noktasını çıkardım, bu yüzden büyüdü. Teşekkürler!
Wellington Lorindo

Kontrol Database field lengthetmek için eşittir DataTableAdaptersaklı yordam kendine özgü parametre Uzunluk - bu özel sütunun Uzunluk
Elshan

3
@OlaTuvesson, neyse ki, User572984 uzun bir süre ve muhtemelen bunu asla görmeyecek olsa da, bugün (8 Ekim 2020) itibariyle 270.000'den fazla kez görüntülendi! Yani, UnknownUser'a geri ödendiğinde, 270.000 kadar SO kullanıcısına fayda sağlandı!
Dan

85

Bu konuya rastlayan ve yanlış bilgi alan diğerleri (iş arkadaşım gibi) için çok önemli bir şeyi açıklığa kavuşturmam gerektiğini hissediyorum.

Verilen yanıt ("Ondalık (9,2) veya ondalık (10,2) veya her neyse.") Doğrudur, ancak neden ("ondalıktan önceki basamak sayısını artırın") yanlıştır.

ondalık (p, s) ve sayısal (p, s) hem bir Kesinlik ve bir Ölçek belirtir . "Kesinlik" ondalık basamağın solundaki basamak sayısı değil, sayının toplam kesinliğidir.

Örneğin: ondalık (2,1) 0,0 ila 9,9'u kapsar, çünkü hassasiyet 2 basamaklıdır (00 ila 99) ve ölçek 1'dir. Ondalık (4,1) 000,0 ila 999,9 ondalık (4,2) 00,00 ila 99,99 ondalık (4,3) 0.000 ile 9.999'u kapsar


7
Hassasiyeti artırmak ve Ölçeği aynı bırakarak, olan ondalık önceki hane sayısının artırılması. Yani söylediklerim yanlış değil ama nasıl yanlış anlaşılabileceğini anlıyorum. Öyle söyledim çünkü OP aslında sorunu sadece ölçeği artırarak çözmeye çalışıyordu, ama siz haklısınız; artırılması gereken toplam hassasiyettir.
adam0101

1

Boyutu ondalıktan (9,2) ondalığa (7,2) düşürmek istiyorsanız, ondalık sayıya (7,2) sığması için daha büyük değerlere sahip mevcut verileri hesaba katmanız gerekecektir. Ya silmeniz gerekecek, bu sayılar yeni boyutunuza uyacak şekilde kısaltılacaktır. Güncellemeye çalıştığınız alan için veri yoksa, otomatik olarak sorunsuz bir şekilde yapacaktır.


0

TRY_CAST işlevini, CAST işleviyle tamamen aynı şekilde kullanın. TRY_CAST bir dizge alır ve bunu AS anahtar sözcüğünden sonra belirtilen bir veri türüne dönüştürmeye çalışır. Dönüştürme başarısız olursa, TRY_CAST başarısız olmak yerine NULL döndürür.


1
TRY_CAST, değeri atılan bir ifade alır. Söylediğin gibi sadece dizeler değil.
TT.

Bu, rutinin hatasız tamamlanmasına izin verse de, eksik veri pahasına olacaktır. Hatanın amacı, eksik verileri önlemek için müdahale gerektiğini belirtmektir. Çözümünüz ancak sonucun mevcut olup olmadığını gerçekten umursamıyorsanız işe yarar.
Dan

-2

tamsayı sütununda saklamak istediğiniz değerinizi kontrol edin. Bunun tamsayı aralığından daha büyük olduğunu düşünüyorum. tamsayı aralığından daha büyük bir değer saklamak istiyorsanız. bigint veri türünü kullanmalısınız


OP, söz konusu sütunun Sayısal olduğunu, Tamsayı olmadığını belirtir ("Sayıyı sayısal veri türüne dönüştürürken aritmetik taşma hatası" hata mesajıyla belirtildiği gibi) ve en çok gönderilen yanıt bunu doğru bir şekilde ele alır. Cevabınız sorunu doğru bir şekilde tanımlar (sonucu saklamak için yetersiz yer) ancak sorunun asıl amacını kaçırır.
Dan
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.