Erreur de dépassement arithmétique lors de la conversion numérique en type de données numérique

88

Je reçois ce message d'erreur chaque fois que j'exécute cette requête:

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

Mais si je change la table de création en (7,0), je ne reçois pas le message d'erreur, mais j'ai besoin que mes données soient affichées sous forme décimale. J'ai essayé 8,3 ne fonctionne pas.

Y a-t-il quelqu'un qui peut m'aider à travailler ceci? Toute aide sera grandement appréciée.

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
la source
9
Je ne vais même pas commencer à ranger ça
m.edmondson
3
J'ai jeté votre SQL via le formateur en ligne ici. dpriver.com/pp/sqlformat.htm Pourrait encore faire avec un rangement manuel.
Martin Smith
3
pourquoi l'option d'un formateur n'est-elle pas intégrée?
adolf garlic
6
Microsoft, si vous écoutez, le message d'erreur «Msg 8115, niveau 16, état 8, ligne 1 erreur de dépassement arithmétique lors de la conversion numérique en type de données numérique». pourrait être améliorée en indiquant la valeur d'origine qui n'a pas pu être convertie. Cela aiderait beaucoup lors du chargement d'une table de 100 milliards de lignes et en essayant de comprendre quelle valeur était offensante. L'ajout du numéro de colonne d'un SELECT serait à nouveau tout aussi utile. PAR EXEMPLE. SELECT CAST (12345678910 comme décimal (12,0)), CAST (12345678910 comme décimal (12,2)) ... ajoutez la chaîne: «Valeur: 12345678910 Colonne: 2» au message d'erreur.
wwmbes

Réponses:

206

Je suppose que vous essayez de presser un nombre supérieur à 99999,99 dans vos champs décimaux. Le changer en (8,3) ne fera rien s'il est supérieur à 99999,999 - vous devez augmenter le nombre de chiffres avant la virgule. Vous pouvez le faire en augmentant la précision (qui correspond au nombre total de chiffres avant et après la virgule). Vous pouvez laisser l'échelle la même, sauf si vous devez modifier le nombre de décimales à stocker. Essayez decimal(9,2)ou decimal(10,2)ou quoi que ce soit.

Vous pouvez tester cela en commentant le insert #tempet voir quels nombres l'instruction select vous donne et voir s'ils sont plus grands que ce que votre colonne peut gérer.

adam0101
la source
17
Je ne prendrais pas la peine de répondre aux questions des personnes ayant des comptes générés automatiquement; ils ne comprennent pas où ils sont et ils ne reviennent pas une fois qu'ils ont eu leur dose. @ user572984: BONJOUR !? QUELQU'UN À LA MAISON? <écran tactile> Non, je ne pense pas.
Ola Tuvesson
J'avais enlevé le point du nombre décimal, donc il est devenu plus grand. Merci!
Wellington Lorindo
Vérifiez Database field lengthégal à DataTableAdapterla longueur de cette colonne spécifique - Paramètre spécifique de la procédure stockée Longueur
Elshan
1
@OlaTuvesson, heureusement, bien que User572984 soit long et ne le verra probablement jamais, à partir d'aujourd'hui (8 octobre 2020), il a été vu plus de 270K fois! Ainsi, en le remboursant à UnknownUser, il a bénéficié à pas moins de 270 000 utilisateurs SO!
Dan
83

Je sens que je dois clarifier une chose très importante, pour les autres (comme mon collègue) qui sont tombés sur ce fil et ont obtenu les mauvaises informations.

La réponse donnée ("Essayez décimal (9,2) ou décimal (10,2) ou autre.") Est correcte, mais la raison ("augmenter le nombre de chiffres avant la décimale") est fausse.

décimal (p, s) et numérique (p, s) spécifient tous deux une précision et une échelle . La «précision» n'est pas le nombre de chiffres à gauche de la décimale, mais plutôt la précision totale du nombre.

Par exemple: decimal (2,1) couvre 0,0 à 9,9, car la précision est de 2 chiffres (00 à 99) et l'échelle est de 1. décimal (4,1) couvre 000,0 à 999,9 décimal (4,2) couvre 00,00 à 99,99 décimal (4,3) couvre 0,000 à 9,999

Dan
la source
7
En augmentant la précision et en laissant l'échelle même, vous êtes en augmentant le nombre de chiffres avant la virgule. Ce que j'ai dit n'est donc pas faux, mais je vois comment cela pourrait être mal compris. Je l'ai dit de cette façon parce que le PO essayait à l'origine de résoudre le problème en augmentant simplement l'échelle, mais vous avez raison; c'est la précision totale qui doit être augmentée.
adam0101
1

Si vous souhaitez réduire la taille en décimal (7,2) à partir de décimal (9,2), vous devrez tenir compte des données existantes avec des valeurs supérieures pour tenir dans décimal (7,2). Soit vous devrez supprimer ces numéros, soit les tronquer pour les adapter à votre nouvelle taille. S'il n'y avait pas de données pour le champ que vous essayez de mettre à jour, il le fera automatiquement sans problème

Benoy John
la source
0

Utilisez la fonction TRY_CAST exactement de la même manière que la fonction CAST. TRY_CAST prend une chaîne et essaie de la convertir en un type de données spécifié après le mot clé AS. Si la conversion échoue, TRY_CAST renvoie un NULL au lieu d'échouer.

Bharat
la source
1
TRY_CAST prend une expression dont la valeur est castée. Pas seulement des cordes comme vous le dites.
TT.
Bien que cela permettrait à la routine de se terminer sans erreur, ce serait au prix de données manquantes. Le but de l'erreur est d'indiquer qu'une intervention est nécessaire pour éviter les données manquantes. Votre solution ne fonctionnerait que si vous ne vous souciez vraiment pas de savoir si le résultat est présent ou non.
Dan
-2

vérifiez votre valeur que vous souhaitez stocker dans une colonne entière. Je pense que c'est plus grand que la plage d'entiers. si vous souhaitez stocker une valeur supérieure à la plage entière. vous devez utiliser le type de données bigint

Prince heureux
la source
L'OP indique que la colonne en question est numérique et non entière (comme indiqué par le message d'erreur «Erreur de dépassement arithmétique lors de la conversion numérique en type de données numérique»), et la première réponse publiée résout ce problème correctement. Votre réponse identifie correctement le problème (espace insuffisant pour stocker le résultat) mais manque l'intention initiale de la question.
Dan