Supprimer des données en SQL, ça semble simple — jusqu'au jour où vous exécutez la mauvaise commande en production. TRUNCATE, DELETE et DROP sont trois commandes SQL de suppression, mais elles n'ont ni le même périmètre, ni le même comportement transactionnel, ni les mêmes conséquences. Confondre les deux premières vous coûtera du temps ; confondre la troisième avec les autres peut vous coûter votre base entière.
Cet article clarifie chaque commande, explique quand l'utiliser, et vous donne les réflexes pour ne plus hésiter — en entretien comme en situation réelle.
📌 Ce qu'il faut retenir
DELETEsupprime des lignes sélectivement, peut être annulé avecROLLBACK, et déclenche les triggersTRUNCATEvide une table entière, est souvent non-transactionnel selon le SGBD, et est bien plus rapideDROPsupprime la table elle-même (structure + données), une action définitive dans la plupart des cas- Le choix entre les 3 dépend du besoin : filtrage, réinitialisation ou destruction complète de l'objet
DELETE : la suppression chirurgicale ligne par ligne
DELETE est la commande la plus flexible des trois. Elle supprime les lignes d'une table selon une condition définie dans une clause WHERE. Sans WHERE, elle supprime toutes les lignes — mais en les traitant une par une.
-- Supprimer les commandes annulées depuis plus de 6 mois
DELETE FROM commandes
WHERE statut = 'annulé'
AND date_creation < CURRENT_DATE - INTERVAL '6 months';
Chaque suppression est journalisée dans le log des transactions. Cela signifie qu'un ROLLBACK peut annuler l'opération tant que la transaction n'est pas commitée. C'est la raison pour laquelle DELETE est plus lent sur de grands volumes : le moteur SQL écrit chaque suppression dans le journal.
DELETE déclenche également les triggers BEFORE DELETE et AFTER DELETE définis sur la table. Si votre architecture repose sur des triggers d'audit, cette commande les respecte. Pour approfondir ce sujet, consultez notre guide sur les triggers SQL.
DELETE avec JOIN : des suppressions conditionnées par d'autres tables
Il est possible de combiner DELETE avec une jointure pour supprimer des lignes en fonction d'une table liée. Cette syntaxe varie selon le SGBD — MySQL, PostgreSQL et SQL Server ont chacun leur approche. Nous l'avons détaillée dans l'article dédié au DELETE avec JOIN.
TRUNCATE : vider une table à grande vitesse
TRUNCATE TABLE supprime toutes les lignes d'une table en une seule opération, sans passer ligne par ligne. Le moteur libère les pages de données directement, sans journalisation individuelle de chaque ligne.
-- Vider complètement la table de logs temporaires
TRUNCATE TABLE logs_temporaires;
Le gain de performance est significatif sur les grandes tables. Une table de 50 millions de lignes peut être vidée en quelques secondes avec TRUNCATE, là où un DELETE sans WHERE prendrait plusieurs minutes.
Ce que TRUNCATE ne fait pas
TRUNCATE ne déclenche pas les triggers de suppression dans la plupart des SGBD. PostgreSQL est une exception notable : depuis la version 8.4, il supporte les triggers AFTER TRUNCATE. En revanche, MySQL et SQL Server n'activent pas les triggers sur TRUNCATE.
Par défaut, TRUNCATE remet également à zéro les compteurs AUTO_INCREMENT (ou SERIAL en PostgreSQL), ce que DELETE ne fait pas.
⚠️ Attention
Dans PostgreSQL, TRUNCATE est transactionnel et peut être annulé avec ROLLBACK. Dans MySQL (avec InnoDB), un TRUNCATE provoque un commit implicite, ce qui rend l'annulation impossible. Vérifiez le comportement de votre SGBD avant d'exécuter cette commande en production.
TRUNCATE et les clés étrangères
TRUNCATE échoue si la table est référencée par une clé étrangère active depuis une autre table. Il faut d'abord vider les tables dépendantes, ou désactiver temporairement les contraintes. En PostgreSQL, l'option CASCADE permet de propager le vidage aux tables liées :
TRUNCATE TABLE utilisateurs CASCADE;
À utiliser avec une extrême prudence — la cascade peut vider des tables que vous n'aviez pas anticipées.
DROP : supprimer l'objet SQL lui-même
DROP TABLE ne supprime pas des lignes : il supprime la table dans son intégralité — sa structure, ses données, ses index, ses contraintes et ses triggers associés.
-- Supprimer définitivement la table de staging
DROP TABLE IF EXISTS staging_import;
La clause IF EXISTS évite une erreur si la table n'existe pas. C'est une bonne pratique dans les scripts de migration.
DROP s'applique également aux autres objets SQL : DROP VIEW, DROP INDEX, DROP DATABASE, DROP SCHEMA. Dans tous les cas, l'action est destructrice et généralement irréversible (hors backup ou corbeille spécifique à certains SGBD comme Oracle Flashback).
💡 Bon à savoir
En entretien technique, les recruteurs testent souvent votre connaissance du comportement transactionnel de ces commandes. Savoir que DELETE est toujours annulable, que TRUNCATE dépend du SGBD, et que DROP est définitif montre une vraie maturité sur la gestion des données.
Comparatif complet des 3 commandes
| Critère | DELETE | TRUNCATE | DROP |
|---|---|---|---|
| Cible | Lignes sélectivement | Toutes les lignes | La table entière (structure + données) |
| Clause WHERE | ✅ Oui | ❌ Non | ❌ Non |
| Transactionnel | ✅ Toujours | ⚠️ Selon le SGBD | ❌ Généralement non |
| Déclenche les triggers | ✅ Oui | ⚠️ PostgreSQL seulement | ❌ Non |
| Remet à zéro AUTO_INCREMENT | ❌ Non | ✅ Oui (selon SGBD) | N/A (table supprimée) |
| Performance sur grand volume | 🐢 Lente | 🚀 Très rapide | 🚀 Instantané |
| Récupération possible | ✅ Via ROLLBACK | ⚠️ PostgreSQL uniquement | ❌ Backup requis |
| Compatible clés étrangères actives | ⚠️ Si pas de dépendance | ❌ Échec ou CASCADE | ❌ Échec ou CASCADE |
