HOWTO · MySQL

Comment supprimer toutes les tables dans MySQL

Supprimez en toute sécurité toutes les tables de base d’un schéma MySQL, gérez les clés étrangères et vérifiez le résultat.

Sur cette page

Pour supprimer toutes les tables tout en conservant la base MySQL, générez une instruction DROP TABLE vérifiée pour les objets BASE TABLE, exécutez-la dans la même session avec FOREIGN_KEY_CHECKS temporairement désactivé, puis vérifiez le résultat. Les définitions et les données sont supprimées définitivement : faites une sauvegarde et confirmez que le schéma est supprimable.

Choisir DROP TABLE pour cette opération

DROP TABLE supprime les tables ; DELETE supprime seulement les lignes et TRUNCATE vide une table. DROP DATABASE est plus large et ne convient que si vous souhaitez aussi supprimer le conteneur de base et ses objets. La suppression d’une table supprime ses déclencheurs et effectue un commit implicite : un rollback ne la rétablit pas.

Vous avez besoin du privilège DROP sur les tables concernées. Utilisez un schéma nommé, une sauvegarde ou une base de test connue, et conservez préparation, suppression et restauration sur la même connexion MySQL.

Générer une liste de tables de base entre guillemets

INFORMATION_SCHEMA.TABLES distingue une BASE TABLE d’une vue. Le filtre table_type = 'BASE TABLE' évite donc de traiter les vues à conserver comme des tables. La requête encadre aussi les identifiants d’accents graves et double un accent grave présent dans un nom de table.

Réglez group_concat_max_len selon le nombre et la longueur des noms. L’expression IF produit un message inoffensif pour un schéma vide au lieu d’exécuter DROP TABLE sans nom. Vérifiez la valeur générée dans @drop_sql avant une exécution proche de la production.

Supprimer les tables de base liées par clé étrangère dans une session

L’ordre des clés étrangères peut faire échouer des suppressions isolées. Enregistrez la valeur de session, désactivez les contrôles uniquement dans cette session contrôlée, exécutez l’instruction puis restaurez la valeur. Le fixture MySQL 8.4.11 ci-dessous crée deux tables liées et une vue, ne supprime que les tables et affiche les comptes avant et après.

#!/bin/sh
# Verify that a generated DROP TABLE statement removes FK-linked base tables.
# A view is retained deliberately so the fixture also proves the table/view boundary.
set -eu

fixture_tmp=$(mktemp -d)
trap 'kill "$server_pid" 2>/dev/null || true; rm -rf "$fixture_tmp"' EXIT INT TERM
mysqld --no-defaults --initialize-insecure --datadir="$fixture_tmp/data" --user=root >/dev/null 2>&1
mysqld --no-defaults --datadir="$fixture_tmp/data" --socket="$fixture_tmp/mysql.sock" \
  --pid-file="$fixture_tmp/mysql.pid" --skip-networking --user=root >/dev/null 2>&1 &
server_pid=$!
for _ in $(seq 1 30); do
  mysqladmin --no-defaults --socket="$fixture_tmp/mysql.sock" ping >/dev/null 2>&1 && break
  sleep 1
done
mysqladmin --no-defaults --socket="$fixture_tmp/mysql.sock" ping >/dev/null 2>&1

mysql --no-defaults --batch --raw --skip-column-names --socket="$fixture_tmp/mysql.sock" <<'SQL'
CREATE DATABASE drop_all_demo;
USE drop_all_demo;
CREATE TABLE parent (id INT PRIMARY KEY);
CREATE TABLE child (
  id INT PRIMARY KEY,
  parent_id INT,
  CONSTRAINT child_parent_fk FOREIGN KEY (parent_id) REFERENCES parent(id)
);
CREATE VIEW parent_ids AS SELECT id FROM parent;

SELECT COUNT(*)
FROM information_schema.tables
WHERE table_schema = DATABASE() AND table_type = 'BASE TABLE';

SET SESSION group_concat_max_len = 1048576;
SELECT GROUP_CONCAT(
         CONCAT('`', REPLACE(table_name, '`', '``'), '`')
         ORDER BY table_name SEPARATOR ', '
       )
INTO @table_list
FROM information_schema.tables
WHERE table_schema = DATABASE() AND table_type = 'BASE TABLE';
SET @drop_sql = IF(
  @table_list IS NULL,
  'SELECT ''No base tables found''',
  CONCAT('DROP TABLE IF EXISTS ', @table_list)
);

SET @saved_fk_checks = @@SESSION.foreign_key_checks;
SET SESSION foreign_key_checks = 0;
PREPARE drop_statement FROM @drop_sql;
EXECUTE drop_statement;
DEALLOCATE PREPARE drop_statement;
SET SESSION foreign_key_checks = @saved_fk_checks;

SELECT COUNT(*)
FROM information_schema.tables
WHERE table_schema = DATABASE() AND table_type = 'BASE TABLE';
SELECT COUNT(*)
FROM information_schema.tables
WHERE table_schema = DATABASE() AND table_type = 'VIEW';
SELECT @@SESSION.foreign_key_checks;
SQL
2
0
1
1

La sortie indique deux tables de base au départ, zéro après la suppression, une vue conservée et FOREIGN_KEY_CHECKS rétabli à sa valeur activée initiale. Cette méthode ne supprime ni vues, ni procédures stockées, ni événements, ni utilisateurs, ni la base elle-même.

Vérifier le schéma après la suppression

Exécutez le même comptage INFORMATION_SCHEMA.TABLES que dans le fixture et attendez zéro ligne BASE TABLE. SHOW FULL TABLES FROM your_database aide aussi à voir si les objets restants sont des vues. Si le script modifie FOREIGN_KEY_CHECKS, contrôlez sa valeur de session avant de fermer la connexion ; une autre session ne l’hérite pas.

Comprendre la limite d’échec des clés étrangères

Sans désactiver temporairement les contrôles, MySQL refuse de supprimer une table parente référencée. Ce fixture limite se termine par l’erreur 3730 et montre pourquoi une liste non ordonnée de commandes DROP TABLE peut échouer.

#!/bin/sh
# Demonstrate the foreign-key failure when a referenced table is dropped normally.
set -eu

fixture_tmp=$(mktemp -d)
trap 'kill "$server_pid" 2>/dev/null || true; rm -rf "$fixture_tmp"' EXIT INT TERM
mysqld --no-defaults --initialize-insecure --datadir="$fixture_tmp/data" --user=root >/dev/null 2>&1
mysqld --no-defaults --datadir="$fixture_tmp/data" --socket="$fixture_tmp/mysql.sock" \
  --pid-file="$fixture_tmp/mysql.pid" --skip-networking --user=root >/dev/null 2>&1 &
server_pid=$!
for _ in $(seq 1 30); do
  mysqladmin --no-defaults --socket="$fixture_tmp/mysql.sock" ping >/dev/null 2>&1 && break
  sleep 1
done
mysqladmin --no-defaults --socket="$fixture_tmp/mysql.sock" ping >/dev/null 2>&1

mysql --no-defaults --batch --raw --skip-column-names --socket="$fixture_tmp/mysql.sock" <<'SQL'
CREATE DATABASE fk_boundary_demo;
USE fk_boundary_demo;
CREATE TABLE parent (id INT PRIMARY KEY);
CREATE TABLE child (id INT PRIMARY KEY, parent_id INT, CONSTRAINT child_parent_fk FOREIGN KEY (parent_id) REFERENCES parent(id));
DROP TABLE parent;
SQL

Le diagnostic capturé est ERROR 3730 (HY000) : MySQL indique que parent est référencée par child_parent_fk dans child. N’utilisez pas les contrôles désactivés pour contourner une dépendance inconnue ; utilisez-les seulement après avoir confirmé que toutes les tables de base doivent disparaître.

Alternatives pour les bases jetables et l’automatisation en ligne de commande

Pour un schéma entièrement jetable, supprimer puis recréer la base peut être plus simple, mais cette opération est plus large que la suppression des tables. Elle exige les privilèges appropriés et retire des objets que la méthode des tables de base conserve volontairement. Ne la présentez pas comme un moyen de préserver vues, routines ou événements.

mysqldump --add-drop-table --no-data peut produire un script de suppression pour le shell, utile après révision. Ne mettez pas de mot de passe directement dans la ligne de commande, inspectez les instructions générées et distinguez les questions d’identifiants et de portabilité de la méthode SQL recommandée.

Limites et dépannage

Si aucune table n’est supprimée, vérifiez d’abord le schéma choisi et le filtre BASE TABLE. Un très grand schéma peut dépasser la limite GROUP_CONCAT : augmentez-la consciemment ou générez et révisez les instructions par lots. Une erreur de privilège signifie que le compte n’a pas l’accès DROP. Les vues restent volontairement ; supprimez-les séparément seulement si cela fait partie du nettoyage approuvé. Comme DROP TABLE effectue un commit implicite, restaurez une sauvegarde plutôt que d’attendre un rollback.