SQLite
 sql >> Base de données >  >> RDS >> SQLite

Comment fonctionne AUTOINCREMENT dans SQLite

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