Om du får felmeddelandet "Msg 8115, Level 16 Arithmetic overflow error converting IDENTITY till datatyp... ”-fel i SQL Server, beror det förmodligen på att du försöker infoga data i en tabell när dess IDENTITY
kolumnen har nått sin datatyps gräns.
En IDENTITY
kolumnen ökar automatiskt värdet som infogas med varje ny rad. Om värdet som infogas ligger utanför intervallet för kolumnens datatyp kommer ovanstående fel att uppstå.
Exempel på felet
Här är ett exempel på kod som resulterar i felet:
INSERT INTO t1 VALUES ('Dog');
Resultat:
Msg 8115, Level 16, State 1, Line 1 Arithmetic overflow error converting IDENTITY to data type tinyint.
I det här fallet, min IDENTITY
kolumnen använder tinyint
datatyp, som har ett intervall på 0 till 255. Felet innebär att IDENTITY
kolumnen försöker infoga ett värde som är högre än 255.
Detta inträffar vanligtvis när vi redan har infogat 255 rader i kolumnen och nu försöker vi infoga den 256:e raden.
Så här ser min tabell ut när jag väljer alla rader med IDENTITY
kolumnen är större än 250
:
SELECT * FROM t1
WHERE c1 > 250;
Resultat:
+------+------+ | c1 | c2 | |------+------| | 251 | Ant | | 252 | Cow | | 253 | Bat | | 254 | Duck | | 255 | Bull | +------+------+
I det här fallet, c1
är min IDENTITY
kolumn (som råkar vara typ tinyint
). Vi kan se den IDENTITY
har tidigare genererat 255
för kolumnen, så nästa värde som försöker infogas är 256
(förutsatt att ett ökningsvärde är 1
och inga tidigare misslyckade inlägg). Detta kommer att orsaka ovanstående fel, eftersom 256 är utanför intervallet för en tinyint
.
Samma problem kan uppstå med datatyper av smallint
(maximalt värde på 32 767) eller int
(högsta värde av 2 147 483 647). Det kan också hända med bigint
om du har infogat tillräckligt många rader (över 9 223 372 036 854 775 807).
Men IDENTITY
värdet matchar inte alltid antalet infogade rader. Du kan ställa in ett startvärde när du skapar en IDENTITY
kolumn, och du kan också ställa in ett inkrementvärde. Därför kan du lätt nå den övre gränsen mycket tidigare än antalet insättningar som utförs på bordet, beroende på frö- och inkrementvärden.
Att radera rader från en tabell återställer inte heller IDENTITY
värde (även om trunkering av en tabell gör det).
Därför kan du fortfarande uppleva ovanstående fel även när det finns mycket färre rader i tabellen än vad IDENTITY
kolumns datatyp kan föreslå.
Lösning
En lösning är att ändra datatypen för IDENTITY
kolumn. Till exempel, om det är smallint
, ändra den till int
. Eller om det redan är int
, ändra det till bigint
.
En annan möjlig lösning skulle vara att återställa IDENTITY
utsäde till ett lägre värde. Detta skulle bara fungera om du antingen har tagit bort många rader från tabellen eller om det ursprungliga startvärdet var mycket högre än 1
.
Till exempel, om IDENTITY
kolumnen är redan en int
, men IDENTITY
seed började på säg 2,000,000,000
, kan du återställa IDENTITY
seed till 1
, vilket skulle göra det möjligt för ytterligare 2 miljarder rader att infogas.
Användbara funktioner
Här är några funktioner som kan vara till stor hjälp för att identifiera det här problemet:
IDENT_CURRENT()
– returnerar det senast genererade identitetsvärdet för en angiven tabell eller vy i en identitetskolumn.@@IDENTITY
– Returnerar det senast infogade identitetsvärdet i den aktuella sessionen.IDENT_SEED()
– Returnerar det ursprungliga fröet för en identitetskolumn.IDENT_INCR()
– Returnerar ökningsvärdet för en identitetskolumn.
Här är också tre sätt att få en kolumns datatyp om du inte är säker på vad kolumnens datatyp är.
Samma fel i olika scenarier
Samma fel (Msg 8115) kan också uppstå (med ett lite annorlunda felmeddelande) när du försöker explicit konvertera mellan datatyper och det ursprungliga värdet ligger utanför intervallet för den nya typen. Se Fixa "Arithmetic overflow-fel vid konvertering av int till datatyp numeric" i SQL Server för att åtgärda detta.
Det kan också inträffa när du använder en funktion som SUM()
på en kolumn, och beräkningen resulterar i ett värde som ligger utanför intervallet för kolumntypen. Se Fixa "Arithmetic overflow-fel vid konvertering av uttryck till datatyp int" i SQL Server för att åtgärda detta.