Die IDENTITY Eigenschaft ist eine oft genutzte Methode eine eindeutige Kennzeichnung eines Datensatzes zu erreichen. Sie wird in der Regel für eine Spalte vom Datentyp INTEGER verwendet. Damit stehen ca. 2,1 Mrd. Werte zur Verfügung. Doch was passiert eigentlich, wenn man an die Grenzen des INTEGER Gültigkeitsbereiches stößt...
Bevor wir uns der Ausgangsfrage widmen, zunächst ein kleines Repetitorium in Sachen IDENTITY Eigenschaft und numerische Datentypen im SQL Server.
Die IDENTITY Eigenschaft kann für Spalten vom Typ INTEGER oder DECIMAL mit Scale 0 definiert werden. Damit stehen folgende Wertebereiche zur Verfügung:
TINYINT |
0 - 255 |
SMALLINT |
-32.768 - 32.767 |
INT |
-2.147.483.648 - 2.147.483.647 |
BIGINT |
-2^63 - 2^63-1 |
Darüber hinaus steht der DECIMAL Datentyp zur Verfügung. Und damit ein Gültigkeitsbereich von -10^38 - 10^38-1.
So, mit diesem Wissen im Hintergrund, können wir uns wieder der eigentlichen Frage widmen. Was passiert, wenn unser IDENTITY Wert Gefahr läuft, einen Gültigkeitsbereich zu überschreiten?
Ausprobieren bringt folgendes Ergebnis:
CREATE TABLE id_overflow
(
col1 INT identity(2147483647,1)
)
go
INSERT INTO id_overflow DEFAULT VALUES
INSERT INTO id_overflow DEFAULT VALUES
SELECT * FROM id_overflow
DROP TABLE id_overflow
(1 row(s) affected)
Server: Msg 8115, Level 16, State 1, Line 2
Arithmetic overflow error converting IDENTITY to data type int.
Arithmetic overflow occurred.
Obiges Skript erstellt eine Tabelle mit einer einzigen Spalte vom Typ INTEGER. Da wir jetzt keine Lust haben über 2 Mrd. Datensätze einzugeben, kürzen wir dies ab, indem wir den Startwert für die IDENTITY Eigenschaft auf den positiven Maximalwert für INTEGER setzen. Der erste eingefügte Datensatz erhält diesen Maximalwert zugeteilt. Nichts Ungewöhnliches passiert. Der Datensatz wird eingefügt. Der nächste Datensatz hingegen sprengt den Rahmen eines INTEGERs, verursacht also einen Überlauf und läßt den Batch abbrechen.
Also offensichtlich fängt SQL Server nicht an, von vorne zu zählen oder eventuell vorhandene Löcher in der IDENTITY Sequenz zu stopfen.
Was kann man nun in einem solchen Fall machen?
Am einfachsten ist es wohl, den Datentypen dieser Spalte auf BIGINT oder DECIMAL(38,0) zu ändern.
CREATE TABLE id_overflow
(
col1 INT IDENTITY(2147483647,1)
)
go
INSERT INTO id_overflow DEFAULT VALUES
ALTER TABLE id_overflow
ALTER COLUMN col1 BIGINT
INSERT INTO id_overflow DEFAULT VALUES
SELECT * FROM id_overflow
DROP TABLE id_overflow
col1
--------------------
2147483647
2147483648
(2 row(s) affected)
Weiss man bereits im Vorfeld, dass die Tabelle eine derart grosse Anzahl von Zeilen aufnehmen soll, kann man auch folgendes machen:
CREATE TABLE bigint_t
(
col1 BIGINT IDENTITY(-9223372036854775808, 1)
)
go
INSERT INTO bigint_t DEFAULT VALUES
SELECT * FROM bigint_t
DROP TABLE bigint_t
col1
--------------------
-9223372036854775808
(1 row(s) affected)
oder die DECIMAL(38,0) Variante:
CREATE TABLE decimal_t
(
col1 DECIMAL(38,0) IDENTITY(-99999999999999999999999999999999999999, 1)
)
GO
INSERT INTO decimal_t DEFAULT VALUES
SELECT * FROM decimal_t
DROP TABLE decimal_t
col1
----------------------------------------
-99999999999999999999999999999999999999
(1 row(s) affected)
Der Eine oder Andere mag sich vielleicht durch die negativen Zahlen in seinem ästhetischen Empfinden gestört fühlen, Fakt aber ist, daß dies einem dann für längere Zeit Ruhe geben sollte.