En SQLite, un AUTOINCREMENT
colonne est celle qui utilise une valeur automatiquement incrémentée pour chaque ligne insérée dans la table.
Il existe plusieurs façons de créer un AUTOINCREMENT
colonne :
- Vous pouvez le créer implicitement lorsque vous définissez la colonne comme
INTEGER PRIMARY KEY
. - Vous pouvez le créer explicitement avec le
AUTOINCREMENT
mot-clé. L'un des inconvénients de cette méthode est qu'elle utilise du CPU, de la mémoire, de l'espace disque et une surcharge d'E/S disque supplémentaires.
Les deux méthodes font que la colonne utilise une valeur incrémentielle chaque fois qu'une nouvelle ligne est insérée avec NULL
dans cette colonne.
Cependant, il existe quelques différences subtiles entre le fonctionnement de chaque méthode.
Sans le mot-clé AUTOINCREMENT
Lorsque vous déclarez une colonne en tant que INTEGER PRIMARY KEY
, il s'incrémentera automatiquement. Par conséquent, vous n'avez pas réellement besoin d'utiliser le AUTOINCREMENT
mot-clé pour avoir une colonne qui utilise une valeur qui s'incrémente automatiquement pour chaque ligne.
Lorsque vous faites cela, tout NULL
les valeurs sont converties dans le ROWID
actuel . En d'autres termes, si vous insérez NULL
dans cette colonne, il sera converti dans le ROWID
actuel .
En fait, la façon dont cela fonctionne est que la colonne devient un alias pour le ROWID
. Vous pouvez accéder au ROWID
valeur en utilisant l'un des quatre noms ; le nom de la colonne, ROWID
, _ROWID_
, ou OID
.
Un avantage d'omettre le AUTOINCREMENT
mot-clé est qu'il réduit la surcharge du processeur, de la mémoire, de l'espace disque et des E/S de disque.
Un inconvénient important cependant est que vous ne pouvez pas garantir que toutes les lignes seront incrémentées dans l'ordre croissant. Cela est dû à la façon dont l'auto-incrémentation fonctionne en omettant le AUTOINCREMENT
mot-clé par rapport à l'utilisation de ce mot-clé.
Lorsque vous omettez le AUTOINCREMENT
mot-clé, une fois ROWID
est égal au plus grand nombre entier possible (9223372036854775807), SQLite essaiera de trouver un ROWID
positif non utilisé au hasard.
Cependant, tant que vous n'utilisez jamais le maximum de ROWID
valeur et vous ne supprimez jamais l'entrée dans la table avec le plus grand ROWID
, cette méthode générera un ROWID
unique croissant de manière monotone s.
Avec le mot clé AUTOINCREMENT
Vous pouvez également créer explicitement des colonnes auto-incrémentées. Pour cela, utilisez le AUTOINCREMENT
mot-clé.
Lorsque vous utilisez cette méthode, un algorithme légèrement différent est utilisé pour déterminer la valeur auto-incrémentée.
Lorsque vous utilisez le AUTOINCREMENT
mot-clé, le ROWID
choisi pour la nouvelle ligne est supérieur d'au moins un au plus grand ROWID
qui n'a jamais existait auparavant dans cette même table.
En d'autres termes, il ne reviendra pas en arrière et ne réutilisera pas le ROWID
précédemment supprimé. valeurs. Une fois le plus grand ROWID
possible a été inséré, aucune nouvelle insertion n'est autorisée. Toute tentative d'insertion d'une nouvelle ligne échouera avec un SQLITE_FULL
erreur.
Par conséquent, l'utilisation de cette méthode garantit que le ROWID
s augmentent de manière monotone. En d'autres termes, vous pouvez compter sur cette méthode pour avoir ROWID
s dans l'ordre croissant.
Cela ne signifie pas que les valeurs seront toujours incrémentées de 1. Cela signifie simplement qu'ils ne diminueront jamais.
Exemple
Voici un exemple pour illustrer la différence entre la définition implicite et explicite d'une colonne à incrémentation automatique.
CREATE TABLE Cats(
CatId INTEGER PRIMARY KEY,
CatName
);
CREATE TABLE Dogs(
DogId INTEGER PRIMARY KEY AUTOINCREMENT,
DogName
);
INSERT INTO Cats VALUES
( NULL, 'Brush' ),
( NULL, 'Scarcat' ),
( NULL, 'Flutter' );
INSERT INTO Dogs VALUES
( NULL, 'Yelp' ),
( NULL, 'Woofer' ),
( NULL, 'Fluff' );
SELECT * FROM Cats;
SELECT * FROM Dogs;
Premier résultat :
CatId CatName ---------- ---------- 1 Brush 2 Scarcat 3 Flutter DogId DogName ---------- ---------- 1 Yelp 2 Woofer 3 Fluff
Supprimons maintenant la dernière ligne de chaque tableau, insérons à nouveau les lignes, puis sélectionnons le résultat :
DELETE FROM Cats WHERE CatId = 3;
DELETE FROM Dogs WHERE DogId = 3;
INSERT INTO Cats VALUES ( NULL, 'New Flutter' );
INSERT INTO Dogs VALUES ( NULL, 'New Fluff' );
SELECT * FROM Cats;
SELECT * FROM Dogs;
Résultat :
CatId CatName ---------- ---------- 1 Brush 2 Scarcat 3 New Flutter DogId DogName ---------- ---------- 1 Yelp 2 Woofer 4 New Fluff
Pour récapituler, les Chats la table a été créée sans l'AUTOINCREMENT
mot-clé, et les Chiens la table a été créée avec l'AUTOINCREMENT
mot-clé.
Après avoir supprimé la dernière ligne des Chats table, le prochain INSERT
l'opération a donné le même ROWID
réutilisé pour cette ligne.
Cependant, les Chiens le tableau était différent. Il a été créé avec le AUTOINCREMENT
mot-clé et donc il ne peut pas réutiliser la valeur précédente. Il passe simplement à la valeur suivante, laissant un espace dans la numérotation.
ID de ligne maximal
Nous pouvons pousser l'exemple précédent un peu plus loin et insérer une nouvelle ligne en utilisant explicitement le maximum ROWID
possibles.
INSERT INTO Cats VALUES ( 9223372036854775807, 'Magnus' );
INSERT INTO Dogs VALUES ( 9223372036854775807, 'Maximus' );
SELECT * FROM Cats;
SELECT * FROM Dogs;
Résultat :
CatId CatName -------------------- -------------------- 1 Brush 2 Scarcat 3 New Flutter 9223372036854775807 Magnus DogId DogName -------------------- -------------------- 1 Yelp 2 Woofer 4 New Fluff 9223372036854775807 Maximus
OK, donc les deux tables utilisent le plus grand nombre entier possible comme leur plus grand ROWID
valeurs.
Voyons ce qui se passe lorsque j'essaie d'insérer une nouvelle ligne dans chaque table (sans spécifier explicitement une valeur pour les colonnes à incrémentation automatique).
Insérer dans les Chats tableau :
INSERT INTO Cats VALUES ( NULL, 'Scratchy' );
SELECT * FROM Cats;
Résultat :
CatId CatName -------------------- -------------------- 1 Brush 2 Scarcat 3 New Flutter 267244677462397326 Scratchy 9223372036854775807 Magnus
Alors les chats le tableau a réussi. Cependant, notez que la nouvelle valeur d'auto-incrémentation est inférieure à la valeur précédente (elle n'a pas d'autre option).
Sans aucune autre colonne pour enregistrer la date/heure à laquelle la ligne a été insérée/mise à jour, on pourrait supposer à tort que Magnus a été inséré après Scratchy .
Essayons maintenant d'insérer une nouvelle ligne dans les Chiens tableau :
INSERT INTO Dogs VALUES ( NULL, 'Lickable' );
Résultat :
Error: database or disk is full
Nous obtenons donc un résultat différent des Chats tableau.
J'ai eu cette erreur parce que le plus grand ROWID
possible est déjà utilisé dans la table, et parce que cette table a été créée avec le AUTOINCREMENT
mot-clé, il ne reviendra pas en arrière et ne recherchera pas un ROWID
inutilisé valeur.
SELECT * FROM Dogs;
Résultat :
DogId DogName -------------------- -------------------- 1 Yelp 2 Woofer 4 New Fluff 9223372036854775807 Maximus
De plus, je continuerai à avoir cette erreur, même si je supprime Maximus du tableau (c'est-à-dire le chien avec le maximum de ROWID
valeur).
Essayons :
DELETE FROM Dogs WHERE DogId = 9223372036854775807;
INSERT INTO Dogs VALUES ( NULL, 'Lickable' );
Résultat :
Error: database or disk is full
Donc, non seulement nous obtenons une erreur, mais j'ai également supprimé Maximus :
SELECT * FROM Dogs;
Résultat :
DogId DogName -------------------- -------------------- 1 Yelp 2 Woofer 4 New Fluff
Il est important de noter que cela se produira même si je change le ROWID
valeur à une valeur inférieure. Le fait que j'ai déjà utilisé un ROWID de 9223372036854775807 signifie que AUTOINCREMENT
n'augmentera plus automatiquement.
C'est parce que AUTOINCREMENT
utilise uniquement des valeurs supérieures d'au moins une valeur à toute valeur ayant déjà existé dans cette même table .
À partir de maintenant, si je voulais continuer à insérer des valeurs dans cette colonne, je devrais insérer explicitement la valeur. Cela suppose que je n'ai pas déjà 9223372036854775807 lignes dans le tableau.
Réinsérons Maximus avec un ROWID
inférieur et réessayez :
INSERT INTO Dogs VALUES ( 5, 'Maximus' );
SELECT * FROM Dogs;
Résultat :
DogId DogName -------------------- -------------------- 1 Yelp 2 Woofer 4 New Fluff 5 Maximus
Essayons maintenant d'insérer Lickable encore une fois, en utilisant AUTOINCREMENT
:
INSERT INTO Dogs VALUES ( NULL, 'Lickable' );
Résultat :
Error: database or disk is full
Ainsi, même si j'ai supprimé la ligne contenant le maximum de ROWID
valeur de 9223372036854775807, il toujours m'empêche d'auto-incrémenter la colonne.
C'est exactement comme ça qu'il a été conçu. Le ROWID
maximal a déjà été dans cette table et donc AUTOINCREMENT
ne s'incrémentera pas automatiquement à nouveau dans cette table.
La seule façon d'ajouter une nouvelle ligne à cette table est d'insérer manuellement le ROWID
valeur.
INSERT INTO Dogs VALUES (6, 'Lickable');
SELECT * FROM Dogs;
Résultat :
DogId DogName -------------------- -------------------- 1 Yelp 2 Woofer 4 New Fluff 5 Maximus 6 Lickable