UPDATE pour modifier des lignes existantes
Là où INSERT sert à ajouter de nouvelles lignes, UPDATE permet de modifier celles qui sont déjà en base. La syntaxe est concise et mérite d'être retenue par cœur :
UPDATE table_name
SET column = value
WHERE condition;
Un exemple concret :
SET indique ce qui change. WHERE indique quelles lignes. Le reste de la table reste intact.
La clause WHERE : optionnelle en théorie, indispensable en pratique
Techniquement, WHERE est optionnelle. Concrètement, l'oublier est le meilleur moyen pour un dev junior de gâcher son après-midi :
UPDATE users SET status = 'inactive';
-- chaque utilisateur est désormais inactif
Sans filtre, toutes les lignes correspondent. Et SQLite s'exécutera sans broncher. Prenez l'habitude d'écrire le WHERE avant le SET — rien que ce réflexe vous évitera bien des catastrophes.
En cas de doute sur votre WHERE, testez d'abord la même condition avec un SELECT :
Même condition, deux requêtes. Le SELECT te sert de répétition générale.
Modifier plusieurs colonnes en une seule fois
Sépare les affectations par des virgules à l'intérieur d'un seul SET. Un seul SET, plusieurs colonnes mises à jour :
Un seul aller-retour vers la base, une ligne touchée, trois colonnes mises à jour. Inutile d'écrire trois UPDATE séparés quand un seul suffit.
Des expressions à droite du =
La valeur après = n'est pas obligée d'être un littéral. Ça peut être n'importe quelle expression — y compris une qui réutilise la valeur actuelle de la colonne :
price * 1.10 lit le prix actuel, le multiplie, puis réécrit le résultat dans la colonne. SQLite évalue la partie droite à partir des valeurs actuelles de la ligne avant d'appliquer les affectations de cette instruction, ce qui permet de référencer plusieurs colonnes sans crainte :
UPDATE products SET price = price * 1.10, stock = stock + price;
-- 'price' à droite ici correspond à l'ANCIEN prix, pas à celui qui vient d'être mis à jour.
UPDATE ... FROM : récupérer des valeurs depuis une autre table
Depuis SQLite 3.33, la commande UPDATE accepte une clause FROM, ce qui permet de faire des mises à jour entre plusieurs tables. C'est la façon la plus propre de synchroniser des données d'une table à une autre :
La sous-requête calcule les totaux par client ; le UPDATE externe rattache ensuite ces résultats à la table customers via id. Sans UPDATE ... FROM, il faudrait écrire une sous-requête corrélée pour chaque colonne — beaucoup plus verbeux.
Quelques règles à garder en tête :
- La table cible se place après
UPDATE, pas dans leFROM. - C'est la clause
WHEREqui fait la jointure — il n'y a pas de mot-cléONici. - Si la jointure peut correspondre à plusieurs lignes dans le
FROM, le résultat est indéterminé. Assurez-vous que vos clés de jointure produisent au maximum une correspondance par ligne cible.
RETURNING : voir ce qui a changé
Depuis SQLite 3.35+, on peut faire un UPDATE RETURNING pour récupérer les lignes modifiées dans la même requête. Très pratique quand l'application a besoin des nouvelles valeurs sans relancer un SELECT derrière :
Vous récupérez les lignes réellement modifiées, avec leurs nouvelles valeurs. Cela évite un aller-retour et élimine toute une catégorie de race conditions dans le code concurrent. Une page entière est consacrée à RETURNING plus loin dans ce chapitre.
UPDATE OR REPLACE : gérer les conflits de contraintes
Si votre mise à jour viole une contrainte UNIQUE, le comportement par défaut est d'interrompre l'instruction avec une erreur. La clause OR vous permet de choisir une autre stratégie :
Les options disponibles sont OR ABORT (par défaut), OR REPLACE, OR IGNORE, OR FAIL et OR ROLLBACK. La plus risquée, c'est REPLACE : elle supprime la ligne en conflit, ce qui peut déclencher des cascades via les clés étrangères. À n'utiliser que si vous voulez vraiment dire « s'il existe déjà une ligne avec cette valeur unique, jette-la ».
Pour la plupart des cas de type upsert, la syntaxe dédiée INSERT ... ON CONFLICT est nettement plus claire. Une page entière y est consacrée.
Encadrer les UPDATE risqués dans une transaction
Quand vous modifiez beaucoup de lignes ou que vous enchaînez plusieurs UPDATE qui doivent tous réussir ensemble, regroupez-les dans une transaction. Si quoi que ce soit part en vrille, vous pouvez revenir à l'état initial :
Si la seconde requête échoue (par exemple à cause d'une contrainte), le ROLLBACK annule la première. Sans transaction, vous vous retrouveriez avec un transfert à moitié fait — Ada perd 25, Boris ne reçoit rien. On consacrera tout un chapitre aux transactions plus loin ; pour l'instant, retenez juste qu'elles existent et que les mises à jour en masse devraient presque toujours se faire à l'intérieur d'une transaction.
Les pièges classiques
Voici une petite liste des trucs qui font trébucher tout le monde :
- Oublier le
WHERE— toutes les lignes y passent. Relisez votre requête à voix haute avant de l'exécuter. - Mauvais opérateur dans le
WHERE—WHERE status = NULLne renvoie rien. Il faut écrireIS NULL. On reviendra là-dessus dans la page sur les opérateurs. - Faire un UPDATE avec une sous-requête qui renvoie plusieurs lignes alors que vous en attendiez une seule. Utilisez
LIMIT 1ou une fonction d'agrégation, sinon vous aurez droit à des erreurs ou à des résultats inattendus. - Confondre UPDATE OR REPLACE et UPSERT.
OR REPLACEsupprime les lignes en conflit.INSERT ... ON CONFLICT DO UPDATEles modifie sur place. Ce sont deux opérations différentes.
La suite : DELETE
UPDATE modifie des lignes ; DELETE les supprime. La même rigueur sur le WHERE s'applique — et le même réflexe de « lancer un SELECT d'abord » vous évitera les mêmes catastrophes. C'est le sujet de la prochaine page.
Questions fréquentes
Quelle est la syntaxe de base d'UPDATE en SQLite ?
UPDATE nom_table SET colonne = valeur WHERE condition;. La clause SET liste les colonnes à modifier avec leurs nouvelles valeurs, et WHERE filtre les lignes concernées. Attention : si vous oubliez le WHERE, toutes les lignes de la table sont mises à jour.
Comment modifier plusieurs colonnes en une seule requête ?
Il suffit de séparer les affectations par des virgules dans la clause SET : UPDATE users SET name = 'Ada', email = 'ada@x.com' WHERE id = 1;. Une seule requête, un seul aller-retour vers la base, une ligne modifiée. Inutile de répéter SET pour chaque colonne.
SQLite permet-il de mettre à jour une table depuis une autre ?
Oui — UPDATE ... FROM (disponible depuis SQLite 3.33) permet de joindre une autre table ou une sous-requête dans l'UPDATE. La syntaxe est : UPDATE cible SET col = source.col FROM source WHERE cible.id = source.id;. C'est la façon la plus propre de recopier des valeurs entre tables.