Jeśli otrzymujesz błąd „Msg 8115, Błąd przepełnienia arytmetycznego poziomu 16 podczas konwersji TOŻSAMOŚCI na typ danych… ” błąd w SQL Server, prawdopodobnie dlatego, że próbujesz wstawić dane do tabeli, gdy ich IDENTITY
kolumna osiągnęła limit typu danych.
IDENTITY
kolumna automatycznie zwiększa wartość wstawianą z każdym nowym wierszem. Jeśli wstawiana wartość jest poza zakresem typu danych kolumny, wystąpi powyższy błąd.
Przykład błędu
Oto przykład kodu, który powoduje błąd:
INSERT INTO t1 VALUES ('Dog');
Wynik:
Msg 8115, Level 16, State 1, Line 1 Arithmetic overflow error converting IDENTITY to data type tinyint.
W tym przypadku moja IDENTITY
kolumna używa tinyint
typ danych, który ma zakres od 0 do 255. Błąd implikuje, że IDENTITY
kolumna próbuje wstawić wartość wyższą niż 255.
Zwykle zdarza się to, gdy wstawiliśmy już 255 wierszy do kolumny, a teraz próbujemy wstawić 256 wiersz.
Oto jak wygląda moja tabela po zaznaczeniu wszystkich wierszy, w których IDENTITY
kolumna jest większa niż 250
:
SELECT * FROM t1
WHERE c1 > 250;
Wynik:
+------+------+ | c1 | c2 | |------+------| | 251 | Ant | | 252 | Cow | | 253 | Bat | | 254 | Duck | | 255 | Bull | +------+------+
W tym przypadku c1
to moja IDENTITY
kolumna (która jest typu tinyint
). Widzimy, że IDENTITY
wcześniej wygenerował 255
dla kolumny, więc następną wartością, która próbuje wstawić, jest 256
(przy założeniu przyrostu wartości 1
i żadnych wcześniej nieudanych wstawek). Spowoduje to powyższy błąd, ponieważ 256 jest poza zakresem tinyint
.
Ten sam problem może wystąpić w przypadku typów danych smallint
(maksymalna wartość 32 767) lub int
(maksymalna wartość 2.147.483.647). Może się to również zdarzyć w przypadku bigint
jeśli wstawiłeś wystarczającą liczbę wierszy (ponad 9 223 372 036 854 775 807).
Jednak IDENTITY
wartość nie zawsze odpowiada liczbie wstawionych wierszy. Możesz ustawić wartość inicjatora podczas tworzenia IDENTITY
kolumna, a także można ustawić wartość przyrostu. Dlatego możesz łatwo osiągnąć górną granicę znacznie wcześniej niż liczba wstawek wykonanych na stole, w zależności od wartości nasion i przyrostu.
Ponadto usunięcie wierszy z tabeli nie resetuje IDENTITY
wartość (chociaż robi to przycinanie tabeli).
Dlatego nadal możesz napotkać powyższy błąd, nawet jeśli w tabeli jest znacznie mniej wierszy niż IDENTITY
może sugerować typ danych kolumny.
Rozwiązanie
Jednym z rozwiązań jest zmiana typu danych IDENTITY
kolumna. Na przykład, jeśli jest smallint
, zmień go na int
. Lub jeśli to już jest int
, zmień go na bigint
.
Innym możliwym rozwiązaniem byłoby zresetowanie IDENTITY
nasiona do niższej wartości. To zadziała tylko wtedy, gdy usuniesz wiele wierszy z tabeli lub jeśli oryginalna wartość inicjatora byłaby znacznie wyższa niż 1
.
Na przykład, jeśli IDENTITY
kolumna jest już int
, ale IDENTITY
seed rozpoczął się od powiedzmy 2,000,000,000
, możesz zresetować IDENTITY
seed do 1
, co pozwoliłoby na wstawienie kolejnych 2 miliardów wierszy.
Pomocne funkcje
Oto kilka funkcji, które mogą być bardzo pomocne w identyfikacji tego problemu:
IDENT_CURRENT()
– zwraca ostatnią wartość tożsamości wygenerowaną dla określonej tabeli lub widoku w kolumnie tożsamości.@@IDENTITY
– Zwraca ostatnio wstawioną wartość tożsamości w bieżącej sesji.IDENT_SEED()
– Zwraca oryginalne źródło kolumny tożsamości.IDENT_INCR()
– Zwraca wartość przyrostu kolumny tożsamości.
Oto 3 sposoby na uzyskanie typu danych kolumny na wypadek, gdybyś nie był pewien, jaki jest typ danych kolumny.
Ten sam błąd w różnych scenariuszach
Ten sam błąd (komunikat 8115) może również wystąpić (z nieco innym komunikatem o błędzie) podczas próby jawnej konwersji między typami danych, gdy oryginalna wartość znajduje się poza zakresem nowego typu. Zobacz Napraw „Błąd przepełnienia arytmetycznego przy konwersji na typ danych liczbowych” w SQL Server, aby to naprawić.
Może się to również zdarzyć, gdy używasz funkcji, takiej jak SUM()
w kolumnie, a wyniki obliczeń są wartościami spoza zakresu typu kolumny. Zobacz Napraw „Błąd przepełnienia arytmetycznego podczas konwersji wyrażenia na typ danych int” w SQL Server, aby to naprawić.