Pokud se vám zobrazuje chyba „Zpráva 8115, aritmetická chyba přetečení úrovně 16 při převodu IDENTITY na datový typ… ” chyba na serveru SQL Server, je to pravděpodobně proto, že se pokoušíte vložit data do tabulky, když je IDENTITY
sloupec dosáhl limitu typu dat.
IDENTITY
sloupec automaticky zvýší hodnotu, která je vložena s každým novým řádkem. Pokud je vkládaná hodnota mimo rozsah datového typu sloupce, dojde k výše uvedené chybě.
Příklad chyby
Zde je příklad kódu, který vede k chybě:
INSERT INTO t1 VALUES ('Dog');
Výsledek:
Msg 8115, Level 16, State 1, Line 1 Arithmetic overflow error converting IDENTITY to data type tinyint.
V tomto případě moje IDENTITY
sloupec používá tinyint
datový typ, který má rozsah 0 až 255. Chyba znamená, že IDENTITY
sloupec se pokouší vložit hodnotu vyšší než 255.
K tomu obvykle dochází, když jsme do sloupce již vložili 255 řádků a nyní se pokoušíme vložit 256. řádek.
Takto vypadá moje tabulka, když vyberu všechny řádky, kde je IDENTITY
sloupec je větší než 250
:
SELECT * FROM t1
WHERE c1 > 250;
Výsledek:
+------+------+ | c1 | c2 | |------+------| | 251 | Ant | | 252 | Cow | | 253 | Bat | | 254 | Duck | | 255 | Bull | +------+------+
V tomto případě c1
je moje IDENTITY
sloupec (který je náhodou typu tinyint
). Vidíme, že IDENTITY
dříve vygeneroval 255
pro sloupec, takže další hodnota, která se pokusí vložit, je 256
(za předpokladu přírůstkové hodnoty 1
a žádné dříve neúspěšné vložky). To způsobí výše uvedenou chybu, protože 256 je mimo rozsah tinyint
.
Stejný problém může nastat u datových typů smallint
(maximální hodnota 32 767) nebo int
(maximální hodnota 2 147 483 647). Může se to stát také s bigint
pokud jste vložili dostatek řádků (více než 9,223,372,036,854,775,807).
Nicméně IDENTITY
hodnota se vždy neshoduje s počtem vložených řádků. Při vytváření IDENTITY
můžete nastavit počáteční hodnotu sloupec a můžete také nastavit hodnotu přírůstku. Proto můžete snadno dosáhnout horního limitu mnohem dříve, než je počet vložení provedených na stole, v závislosti na hodnotách seed a inkrementů.
Smazáním řádků z tabulky se také neresetuje IDENTITY
hodnotu (ačkoli zkrácení tabulky ano).
Proto se stále může objevit výše uvedená chyba, i když je v tabulce mnohem méně řádků, než kolik IDENTITY
datový typ sloupce může napovídat.
Řešení
Jedním z řešení je změnit datový typ IDENTITY
sloupec. Pokud je například smallint
, změňte jej na int
. Nebo pokud už je int
, změňte jej na bigint
.
Dalším možným řešením by bylo resetování IDENTITY
semeno na nižší hodnotu. To by fungovalo pouze v případě, že jste z tabulky odstranili mnoho řádků nebo pokud byla původní počáteční hodnota mnohem vyšší než 1
.
Pokud například IDENTITY
sloupec je již int
, ale IDENTITY
seed začínal na řekněme 2,000,000,000
, můžete resetovat IDENTITY
semeno na 1
, což by umožnilo vložit další 2 miliardy řádků.
Užitečné funkce
Zde jsou některé funkce, které mohou být velmi užitečné při identifikaci tohoto problému:
IDENT_CURRENT()
– vrátí poslední hodnotu identity vygenerovanou pro zadanou tabulku nebo pohled ve sloupci identity.@@IDENTITY
– Vrátí naposledy vloženou hodnotu identity v aktuální relaci.IDENT_SEED()
– Vrátí původní počáteční hodnotu sloupce identity.IDENT_INCR()
– Vrátí přírůstkovou hodnotu sloupce identity.
Zde jsou také 3 způsoby, jak získat datový typ sloupce v případě, že si nejste jisti, jaký je datový typ sloupce.
Stejná chyba v různých scénářích
Ke stejné chybě (Msg 8115) může dojít také (s mírně odlišnou chybovou zprávou), když se pokusíte explicitně převést mezi datovými typy a původní hodnota je mimo rozsah nového typu. Chcete-li to vyřešit, viz Oprava „Aritmetická chyba přetečení při převodu int na datový typ numeric“ v SQL Server.
Může také nastat, když použijete funkci jako SUM()
na sloupec a výsledkem výpočtu je hodnota, která je mimo rozsah typu sloupce. Chcete-li to vyřešit, viz Oprava „Aritmetická chyba přetečení při převodu výrazu na datový typ int“ v SQL Server.