INSERT pour ajouter des lignes dans une table
L'instruction INSERT sert à insérer de nouvelles lignes dans une table SQLite. La syntaxe reste courte et prévisible :
Trois choses à repérer :
INSERT INTO books— la table cible.(title, author, year)— les colonnes pour lesquelles vous fournissez des valeurs.VALUES (...)— les valeurs, dans le même ordre que la liste des colonnes.
id n'apparaît pas dans la liste des colonnes, donc SQLite lui attribue une valeur automatiquement (c'est un INTEGER PRIMARY KEY, qui récupère le rowid). Toute colonne omise prend sa valeur par défaut, ou NULL si aucune n'est définie.
Listez toujours vos colonnes
Vous pouvez omettre la liste des colonnes et fournir une valeur pour chacune d'elles, dans l'ordre de leur déclaration :
-- Fonctionne, mais fragile :
INSERT INTO books VALUES (NULL, 'Dune', 'Frank Herbert', 1965);
Surtout pas. Dès que quelqu'un ajoute une colonne à books, toutes les requêtes de ce style cassent ou se mettent à insérer les valeurs dans la mauvaise colonne. Mieux vaut nommer explicitement les colonnes :
Lister explicitement les colonnes, c'est aussi une forme de documentation : la requête se lit toute seule, sans avoir besoin d'aller fouiller dans la définition de la table.
Insérer plusieurs lignes en SQLite
Pour insérer plusieurs lignes en une seule requête, il suffit d'enchaîner les tuples de valeurs :
C'est plus propre que trois INSERT séparés, et SQLite traite l'ensemble comme une seule instruction. Cela dit, le vrai gain de performance pour les chargements en masse vient de l'enveloppement des insertions dans une transaction — j'y reviens juste après.
Insertions en masse : à envelopper dans une transaction
Par défaut, chaque INSERT constitue sa propre transaction. SQLite déclenche un fsync à la fin de chacune, et c'est précisément ce qui rend les boucles naïves lentes — pas les insertions elles-mêmes.
Regroupez-les :
Un seul fsync au lieu de cinq. Sur des milliers de lignes, on parle facilement de deux ou trois ordres de grandeur de différence. Et si quoi que ce soit plante en cours de route, le ROLLBACK annule tout le lot d'un coup.
C'est la recette pour faire un insert en masse. Que vous attaquiez SQLite depuis Python, Node ou Rust, le principe est le même : encadrez votre boucle avec BEGIN / COMMIT.
INSERT ... SELECT : copier depuis une autre table
Plutôt que de fournir des valeurs en dur, vous pouvez remplir une table à partir d'une requête :
Les colonnes renvoyées par le SELECT sont associées par position à la liste de colonnes du INSERT. Les noms n'ont pas à correspondre — seul l'ordre compte. C'est la méthode classique pour archiver des lignes, alimenter des tables de reporting ou recopier un sous-ensemble de données lors d'une migration.
DEFAULT VALUES et colonnes omises
Si une colonne possède une clause DEFAULT, vous pouvez tout simplement l'omettre de la liste des colonnes : SQLite se chargera d'y mettre la valeur par défaut.
created_at reçoit le timestamp courant puisqu'on n'en a pas fourni. Si vous voulez une ligne entièrement composée de valeurs par défaut — pratique pour créer des lignes provisoires — utilisez la forme DEFAULT VALUES :
Deux nouvelles lignes sont créées, toutes les deux avec value = 0 et un id attribué automatiquement.
INSERT OR IGNORE : ignorer les doublons
Lorsqu'une ligne enfreint une contrainte UNIQUE ou PRIMARY KEY, le comportement par défaut est d'interrompre la requête en renvoyant une erreur :
Error: UNIQUE constraint failed: users.email
INSERT OR IGNORE remplace ce comportement par « ignorer silencieusement la ligne fautive » :
Trois lignes sont conservées. Le doublon est écarté sans erreur. C'est la façon idiomatique en SQLite d'exprimer « insérer si n'existe pas » pour des données de seed simples — pas besoin de faire un SELECT au préalable, ni de gérer une exception.
INSERT OR REPLACE : écraser les doublons
INSERT OR REPLACE supprime la ligne en conflit et insère la nouvelle à sa place :
Attention à un piège : REPLACE, c'est DELETE + INSERT, pas UPDATE. Si la ligne supprimée avait des clés étrangères pointant vers elle avec ON DELETE CASCADE, les enregistrements enfants sautent aussi. Et toute colonne que vous n'incluez pas dans le nouvel INSERT retombe sur sa valeur par défaut — elle ne conserve pas l'ancienne valeur.
Pour la plupart des cas du genre « mettre à jour si existe, sinon insérer », ce qu'il vous faut vraiment, c'est un vrai upsert avec ON CONFLICT ... DO UPDATE. Ça fait l'objet d'une page dédiée.
Récapitulatif express
INSERT INTO table (cols) VALUES (...)— la forme de base. Listez toujours les colonnes.- Pour insérer plusieurs lignes, on enchaîne les tuples séparés par des virgules après
VALUES. - Pour les vrais imports en masse, encadrez vos inserts avec
BEGIN/COMMIT. INSERT INTO ... SELECT ...recopie les lignes issues d'une requête.DEFAULT VALUEScrée une ligne uniquement à partir des valeurs par défaut ; les colonnes omises retombent elles aussi sur leur valeur par défaut.INSERT OR IGNOREignore les lignes qui posent conflit ;INSERT OR REPLACEles écrase (via delete + insert).
La suite : UPDATE
Insérer des lignes, ce n'est que la moitié du chemin. L'autre moitié, c'est modifier des lignes qui existent déjà — incrémenter un compteur, corriger une faute, marquer une commande comme expédiée. C'est le rôle d'UPDATE, et il a ses propres réflexes à acquérir (en particulier la clause WHERE). On voit ça juste après.
Questions fréquentes
Comment insérer une ligne dans SQLite ?
On utilise INSERT INTO table (col1, col2) VALUES (val1, val2);. Lister les colonnes n'est pas obligatoire, mais c'est vivement conseillé : la requête continuera de fonctionner même si vous ajoutez une colonne plus tard. Sans liste de colonnes, vous devez fournir une valeur pour chaque colonne, dans l'ordre de déclaration.
Comment insérer plusieurs lignes d'un coup en SQLite ?
Il suffit d'enchaîner plusieurs tuples entre parenthèses après VALUES, séparés par des virgules : INSERT INTO t (a, b) VALUES (1, 2), (3, 4), (5, 6);. Pour de vrais imports en masse (des milliers de lignes), encapsulez les insertions dans une transaction unique avec BEGIN et COMMIT — c'est de là que vient le gain de performance, pas de la syntaxe multi-lignes elle-même.
À quoi sert INSERT OR IGNORE en SQLite ?
INSERT OR IGNORE ignore silencieusement les lignes qui violeraient une contrainte UNIQUE, PRIMARY KEY ou NOT NULL, au lieu de déclencher une erreur. La ligne en conflit est tout simplement écartée et la requête continue avec les autres. Pratique quand vous voulez un comportement « insérer si pas déjà présent » sans faire un test d'existence séparé.
Pourquoi j'obtiens 'UNIQUE constraint failed' lors d'un INSERT ?
SQLite a trouvé une ligne existante avec la même valeur dans une colonne UNIQUE ou PRIMARY KEY. Soit la valeur est réellement un doublon, soit vous relancez un script de seed. Passez à INSERT OR IGNORE pour ignorer les doublons, à INSERT OR REPLACE pour les écraser, ou utilisez ON CONFLICT ... DO UPDATE (upsert) pour un contrôle plus fin.