Y a-t-il un incrément automatique dans sqlite?

109

J'essaye de créer une table avec une auto-incrémentation primary keydans Sqlite3 . Je ne sais pas si cela est vraiment possible, mais j'espère ne devoir désigner que les autres domaines.

Par exemple:

CREATE TABLE people (id integer primary key auto increment, first_name varchar(20), last_name varchar(20));

Ensuite, quand j'ajoute une valeur, j'espérais n'avoir qu'à faire:

INSERT INTO people
VALUES ("John", "Smith");

Est-ce seulement possible?

Je cours sqlite3sous cygwinWindows 7.

ewok
la source

Réponses:

167

Vous en obtenez un gratuitement, appelé ROWID. C'est dans chaque table SQLite que vous le demandiez ou non.

Si vous incluez une colonne de type INTEGER PRIMARY KEY, cette colonne pointe vers (est un alias pour) la colonne ROWID automatique.

ROWID (quel que soit le nom que vous appelez) se voit attribuer une valeur chaque fois que vous INSÉRER une ligne, comme vous vous en doutez. Si vous affectez explicitement une valeur non NULL sur INSERT, il obtiendra cette valeur spécifiée au lieu de l'incrémentation automatique. Si vous attribuez explicitement une valeur NULL sur INSERT, il obtiendra la prochaine valeur d'incrémentation automatique.

Aussi, vous devriez essayer d'éviter:

 INSERT INTO people VALUES ("John", "Smith");

et utilise

 INSERT INTO people (first_name, last_name) VALUES ("John", "Smith");

au lieu. La première version est très fragile - si jamais vous ajoutez, déplacez ou supprimez des colonnes dans votre définition de table, INSERT échouera ou produira des données incorrectes (avec les valeurs dans les mauvaises colonnes).

Larry Lustig
la source
53
ROWID n'est pas tout à fait la même chose qu'un véritable auto-incrémentation car la valeur SAME peut être générée plusieurs fois. Par exemple, avec une table vide, l'insertion de 3 lignes donne à la 3ème ligne un ROWID de 3 comme prévu. Cependant, insérez 2 lignes, supprimez la dernière et insérez une autre, donne à la 3ème ligne insérée un ROWID de 2, tout comme la 2ème ligne. Il existe donc un problème sérieux évident si les tables référencent des ROWID dans une table où des suppressions se produisent et où des suppressions ou une annulation de ROWID ne sont pas également effectuées dans les tables associées.
Nick
10
Au cas où cela ne serait pas évident à partir de la réponse, vous pouvez utiliser ROWID dans votre déclaration de sélection, par exempleselect rowid from people;
Colin D
@Nick juste pour compléter votre idée: l'auto-incrémentation est donc une mesure de sécurité. Et nous ne parlons pas de deux lignes entrant en collision dans ROWID.
YoussefDir
69

Oui, c'est possible. Selon la FAQ SQLite :

Une colonne déclarée INTEGER PRIMARY KEYs'incrémentera automatiquement.

Matt Hulse
la source
12
La mise en garde, comme mentionné par Uku, et également expliqué dans la documentation, est que vous devez passer un NULL pour l'ID pour que cela fonctionne.
Matt Hulse
22
Vous ne devez utiliser un NULL que si vous omettez la liste des colonnes à INSERT - jamais une bonne pratique. Si vous spécifiez les colonnes, vous pouvez simplement omettre la colonne à incrémentation automatique et elle recevra la valeur suivante.
Larry Lustig
5
Autre mise en garde: écrivez "INTEGER ..." exactement comme indiqué ci-dessus. Un raccourci "INT ..." ne fonctionnera PAS.
Marcin Wojnarski
27

À partir d'aujourd'hui - juin 2018


Voici ce que la documentation officielle de SQLite a à dire sur le sujet (gras et italique sont à moi):

  1. Le mot clé AUTOINCREMENT impose une surcharge supplémentaire de CPU, de mémoire, d'espace disque et d'E / S disque et doit être évité s'il n'est pas strictement nécessaire. Ce n'est généralement pas nécessaire.

  2. Dans SQLite, une colonne de type INTEGER PRIMARY KEY est un alias pour le ROWID (sauf dans les tables WITHOUT ROWID) qui est toujours un entier signé 64 bits.

  3. Sur un INSERT, si la colonne ROWID ou INTEGER PRIMARY KEY ne reçoit pas explicitement une valeur, elle sera remplie automatiquement avec un entier inutilisé, généralement un de plus que le plus grand ROWID actuellement utilisé. Cela est vrai que le mot clé AUTOINCREMENT soit utilisé ou non.

  4. Si le mot clé AUTOINCREMENT apparaît après INTEGER PRIMARY KEY , cela modifie l'algorithme d'attribution automatique des ROWID pour empêcher la réutilisation des ROWID pendant la durée de vie de la base de données. En d'autres termes, le but d'AUTOINCREMENT est d'empêcher la réutilisation des ROWID de lignes précédemment supprimées.


la source
11

Avez-vous lu ceci? Comment créer un champ AUTOINCREMENT.

INSERT INTO people
VALUES (NULL, "John", "Smith");
Uku Loskit
la source
Donc ce que vous dites, c'est que ce que j'essaie de faire n'est pas possible, mais je peux en quelque sorte simuler. J'ai besoin d'utiliser un null dans l'insertion?
ewok
1
vous n'avez rien à faire mais insérez toujours NULL comme id, cela explique simplement comment sqlite le fait en interne.
Uku Loskit
7
NULL sur INSERT est uniquement nécessaire si vous ne spécifiez pas la liste des colonnes à insérer (dans ce cas, vous avez besoin d' un certain nombre de valeurs correspondant exactement le nombre de colonnes et vous devez utiliser NULL comme un espace réservé). Mais faire un INSERT sans spécifier la liste des colonnes n'est jamais une bonne pratique. Si vous spécifiez la liste des colonnes, omettez simplement la colonne d'auto-incrémentation et la valeur NULL, et vous obtiendrez le résultat attendu.
Larry Lustig
4

Il ne faut pas spécifier de AUTOINCREMENTmot clé à proximité PRIMARY KEY. Exemple de création d'une clé primaire auto-incrémentée et d'insertion:

$ sqlite3 ex1

CREATE TABLE IF NOT EXISTS room(room_id INTEGER PRIMARY KEY, name VARCHAR(25) NOT NULL, home_id VARCHAR(25) NOT NULL);

INSERT INTO room(name, home_id) VALUES ('test', 'home id test');

INSERT INTO room(name, home_id) VALUES ('test 2', 'home id test 2');

SELECT * FROM room;

va donner:

1|test|home id test
2|test 2|home id test 2
Denis Kutlubaev
la source
4

En plus de rowid, vous pouvez définir votre propre champ d'incrémentation automatique, mais ce n'est pas recommandé. C'est toujours une meilleure solution lorsque nous utilisons rowid qui est automatiquement augmenté.

Le AUTOINCREMENTmot-clé impose une surcharge de CPU, de mémoire, d'espace disque et d'E / S disque et doit être évité s'il n'est pas strictement nécessaire. Ce n'est généralement pas nécessaire.

Lisez ici pour des informations détaillées.

sonvx
la source
apparemment, rowid n'est pas toujours automatiquement augmenté, voir le commentaire de Nick
rogerdpack
1
Pas vrai. L'incrémentation automatique est meilleure à certains égards, car elle ne réutilise pas les identifiants - une exigence assez importante pour de nombreux systèmes.
O'Rooney du
4

SQLite AUTOINCREMENT est un mot clé utilisé pour l'incrémentation automatique d'une valeur d'un champ dans la table. Nous pouvons incrémenter automatiquement une valeur de champ en utilisant le mot-clé AUTOINCREMENT lors de la création d'une table avec un nom de colonne spécifique pour l'incrémenter automatiquement.

Le mot clé AUTOINCREMENT ne peut être utilisé qu'avec le champ INTEGER. Syntaxe:

L'utilisation de base du mot clé AUTOINCREMENT est la suivante:

CREATE TABLE table_name(
   column1 INTEGER AUTOINCREMENT,
   column2 datatype,
   column3 datatype,
   .....
   columnN datatype,
);

Par exemple, voir ci-dessous: Considérez que la table COMPANY doit être créée comme suit:

sqlite> CREATE TABLE TB_COMPANY_INFO(
   ID INTEGER PRIMARY KEY   AUTOINCREMENT,
   NAME           TEXT      NOT NULL,
   AGE            INT       NOT NULL,
   ADDRESS        CHAR(50),
   SALARY         REAL
);

Maintenant, insérez les enregistrements suivants dans la table TB_COMPANY_INFO:

INSERT INTO TB_COMPANY_INFO (NAME,AGE,ADDRESS,SALARY)
VALUES ( 'MANOJ KUMAR', 40, 'Meerut,UP,INDIA', 200000.00 );

Maintenant, sélectionnez l'enregistrement

SELECT *FROM TB_COMPANY_INFO
ID      NAME            AGE     ADDRESS             SALARY
1       Manoj Kumar     40      Meerut,UP,INDIA     200000.00
mkumar0304
la source
2

Je sais que cette réponse est un peu tardive.
Mon but pour cette réponse est que tout le monde puisse s'y référer s'ils rencontrent ce type de défi avec SQLite maintenant ou dans le futur et qu'ils ont du mal avec cela.

Maintenant, en repensant à votre requête, cela devrait être quelque chose comme ça.

CREATE TABLE people (id integer primary key autoincrement, first_name varchar(20), last_name varchar(20));

Cela fonctionne de mon côté. Ainsi,

entrez la description de l'image ici

Juste au cas où vous travaillez avec SQLite, je vous suggère de consulter DB Browser pour SQLite . Fonctionne également sur différentes plates-formes.

Kent Aguilar
la source
0

Ce que vous faites est correct, mais la syntaxe correcte pour 'auto incrémentation' doit être sans espace:

CREATE TABLE people (id integer primary key autoincrement, first_name string, last_name string);

(Veuillez également noter que j'ai changé vos varchars en chaînes. C'est parce que SQLite transforme en interne un varchar en chaîne, alors pourquoi s'embêter?)

alors votre insert doit être, en langage SQL aussi standard que possible:

INSERT INTO people(id, first_name, last_name) VALUES (null, 'john', 'doe');

s'il est vrai que si vous omettez id, il sera automatiquement incrémenté et attribué, je préfère personnellement ne pas me fier à des mécanismes automatiques qui pourraient changer à l'avenir.

Une note sur l'auto-incrémentation: bien que, comme beaucoup l'ont souligné, cela ne soit pas recommandé par les utilisateurs de SQLite, je n'aime pas la réutilisation automatique des identifiants des enregistrements supprimés si l'auto-incrémentation n'est pas utilisée. En d'autres termes, j'aime que l'identifiant d'un enregistrement supprimé n'apparaisse plus jamais.

HTH

Luca Nanetti
la source
À cet égard, je partage totalement ce que dit O'Rooney.
Luca Nanetti