ข้อผิดพลาดทางคณิตศาสตร์มากเกินไปในการแปลงตัวเลขเป็นตัวเลขชนิดข้อมูล


91

ฉันได้รับข้อความแสดงข้อผิดพลาดนี้ทุกครั้งที่เรียกใช้แบบสอบถามนี้:

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  

11
ฉันจะไม่เริ่มจัด
ระเบียบมันด้วยซ้ำ

4
ฉันรวบรวม SQL ของคุณผ่านฟอร์แมตเตอร์ออนไลน์ที่นี่ dpriver.com/pp/sqlformat.htmยังสามารถทำได้ด้วยการจัดระเบียบด้วยตนเอง
Martin Smith

3
เหตุใดจึงไม่มีตัวเลือกของฟอร์แมตเตอร์ในตัว?
อดอล์ฟกระเทียม

12
Microsoft หากคุณกำลังฟังข้อความแสดงข้อผิดพลาด "Msg 8115, Level 16, State 8, Line 1 Arithmetic overflow error Conversion numeric to data type numeric" สามารถปรับปรุงได้โดยการระบุค่าดั้งเดิมที่ไม่สามารถแปลงได้ ซึ่งจะช่วยได้มากเมื่อโหลดตาราง 100 พันล้านแถวและพยายามทำความเข้าใจว่าค่าใดที่ไม่เหมาะสม การเพิ่มหมายเลขคอลัมน์ของ SELECT จะมีประโยชน์อีกครั้ง เช่น. เลือกแคสต์ (12345678910 เป็นทศนิยม (12,0)), แคสต์ (12345678910 เป็นทศนิยม (12,2)) ... เพิ่มสตริง: "ค่า: 12345678910 คอลัมน์: 2" ในข้อความแสดงข้อผิดพลาด
wwmbes

คำตอบ:


208

ฉันเดาว่าคุณกำลังพยายามบีบตัวเลขที่มากกว่า 99999.99 ลงในช่องทศนิยมของคุณ การเปลี่ยนเป็น (8,3) จะไม่ทำอะไรเลยหากมันมากกว่า 99999.999 คุณต้องเพิ่มจำนวนหลักก่อนทศนิยม คุณสามารถทำได้โดยเพิ่มความแม่นยำ (ซึ่งก็คือจำนวนหลักทั้งหมดก่อนและหลังทศนิยม) คุณสามารถปล่อยมาตราส่วนให้เท่าเดิมได้เว้นแต่คุณจะต้องเปลี่ยนจำนวนทศนิยมที่จะจัดเก็บ ลองdecimal(9,2)หรือdecimal(10,2)หรืออะไรก็ตาม

คุณสามารถทดสอบสิ่งนี้ได้โดยการแสดงความคิดเห็นinsert #tempและดูตัวเลขที่คำสั่ง select ให้คุณและดูว่ามีขนาดใหญ่กว่าที่คอลัมน์ของคุณสามารถจัดการได้หรือไม่


18
ฉันจะไม่รบกวนการตอบคำถามจากผู้ที่มีบัญชีที่สร้างขึ้นโดยอัตโนมัติ พวกเขาไม่เข้าใจว่าพวกเขาอยู่ที่ไหนและพวกเขาจะไม่กลับมาอีกเลยเมื่อพวกเขาได้รับการแก้ไขแล้ว @ user572984: สวัสดี!? บ้านทุกคน? <หน้าจอแตะ>ไม่ไม่คิดอย่างนั้น
Ola Tuvesson

ฉันได้ลบจุดของเลขฐานสิบมันจึงใหญ่ขึ้น ขอบคุณ!
Wellington Lorindo

ตรวจสอบDatabase field lengthเท่ากับเพื่อให้DataTableAdapterได้ความยาวของคอลัมน์นั้น - พารามิเตอร์เฉพาะของ Stored Procedure ความยาว
Elshan

3
@OlaTuvesson โชคดีที่แม้ว่า User572984 จะยาวและมีแนวโน้มว่าจะไม่เคยเห็นสิ่งนี้ ณ วันนี้ (8 ต.ค. 2020) มีผู้เข้าชมมากกว่า 270K ครั้ง! ดังนั้นในการจ่ายเงินคืนให้กับ UnknownUser จึงเป็นประโยชน์ต่อผู้ใช้ SO มากถึง 270K!
แดน

85

ฉันรู้สึกว่าต้องชี้แจงสิ่งที่สำคัญอย่างหนึ่งสำหรับคนอื่น ๆ (เช่นเพื่อนร่วมงานของฉัน) ที่เจอกระทู้นี้และได้รับข้อมูลที่ไม่ถูกต้อง

คำตอบที่ให้ ("ลองทศนิยม (9,2) หรือทศนิยม (10,2) หรืออะไรก็ได้") ถูกต้อง แต่เหตุผล ("เพิ่มจำนวนหลักก่อนทศนิยม") ไม่ถูกต้อง

ทศนิยม (P, S) และตัวเลข (P, S) ทั้งระบุความแม่นยำและเครื่องชั่งน้ำหนัก "ความแม่นยำ" ไม่ใช่จำนวนหลักทางด้านซ้ายของทศนิยม แต่เป็นความแม่นยำทั้งหมดของตัวเลขแทน

ตัวอย่างเช่นทศนิยม (2,1) ครอบคลุม 0.0 ถึง 9.9 เนื่องจากความแม่นยำคือ 2 หลัก (00 ถึง 99) และมาตราส่วนคือ 1. ทศนิยม (4,1) ครอบคลุม 000.0 ถึง 999.9 ทศนิยม (4,2) ครอบคลุม 00.00 ถึง ทศนิยม 99.99 (4,3) ครอบคลุม 0.000 ถึง 9.999


7
การเพิ่มความแม่นยำและการปล่อยมาตราส่วนให้เท่ากันแสดงว่าคุณกำลังเพิ่มจำนวนหลักก่อนทศนิยม ดังนั้นสิ่งที่ฉันพูดไม่ผิด แต่ฉันเห็นว่ามันอาจเข้าใจผิดได้อย่างไร ฉันพูดแบบนั้นเพราะเดิมที OP พยายามแก้ไขปัญหาโดยการเพิ่มสเกล แต่คุณถูกต้อง มันคือความแม่นยำทั้งหมดที่ต้องเพิ่มขึ้น
adam0101

1

หากคุณต้องการลดขนาดเป็นทศนิยม (7,2) จากทศนิยม (9,2) คุณจะต้องคำนึงถึงข้อมูลที่มีอยู่ซึ่งมีค่ามากกว่าเพื่อให้พอดีกับทศนิยม (7,2) คุณจะต้องลบตัวเลขเหล่านั้นโดยตัดทอนให้พอดีกับขนาดใหม่ของคุณ หากไม่มีข้อมูลสำหรับฟิลด์ที่คุณพยายามอัปเดตข้อมูลจะดำเนินการโดยอัตโนมัติโดยไม่มีปัญหา


0

ใช้ฟังก์ชัน TRY_CAST ในลักษณะเดียวกับฟังก์ชัน CAST TRY_CAST รับสตริงและพยายามแคสต์เป็นประเภทข้อมูลที่ระบุไว้หลังคีย์เวิร์ด AS หากการแปลงล้มเหลว TRY_CAST จะส่งกลับค่า NULL แทนที่จะล้มเหลว


1
TRY_CAST ใช้นิพจน์ซึ่งเป็นค่าที่ร่าย ไม่ใช่แค่สตริงอย่างที่คุณวางไว้
TT.

แม้ว่าจะอนุญาตให้กิจวัตรดำเนินการโดยไม่มีข้อผิดพลาด แต่ก็ต้องเสียค่าใช้จ่ายของข้อมูลที่ขาดหายไป จุดประสงค์ของข้อผิดพลาดคือเพื่อระบุว่าจำเป็นต้องมีการแทรกแซงเพื่อป้องกันข้อมูลที่หายไป วิธีแก้ปัญหาของคุณจะใช้ได้ผลก็ต่อเมื่อคุณไม่สนใจว่าผลลัพธ์จะเป็นจริงหรือไม่
แดน

-2

ตรวจสอบค่าของคุณที่คุณต้องการเก็บไว้ในคอลัมน์จำนวนเต็ม ฉันคิดว่านี่เป็นช่วงของจำนวนเต็มมากกว่า ถ้าคุณต้องการเก็บค่าที่มากกว่าช่วงจำนวนเต็ม คุณควรใช้ประเภทข้อมูล bigint


OP บ่งชี้ว่าคอลัมน์ที่เป็นปัญหาเป็นตัวเลขไม่ใช่จำนวนเต็ม (ตามที่ระบุโดยข้อความแสดงข้อผิดพลาด "Arithmetic overflow error Conversion numeric to data type numeric) คำตอบของคุณระบุปัญหาได้อย่างถูกต้อง (มีพื้นที่ไม่เพียงพอในการจัดเก็บผลลัพธ์) แต่พลาดจุดประสงค์เดิมของคำถาม
แดน
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.