HOWTO · MySQL
Come eliminare tutte le tabelle in MySQL
Elimina in sicurezza tutte le tabelle di base di uno schema MySQL, gestisci le chiavi esterne e verifica il risultato.
In questa pagina
Per eliminare tutte le tabelle mantenendo il database MySQL, genera un’istruzione DROP TABLE controllata per gli oggetti BASE TABLE dello schema, eseguila nella stessa sessione con FOREIGN_KEY_CHECKS temporaneamente disabilitato e verifica poi il risultato. Le definizioni delle tabelle e i dati vengono rimossi definitivamente: esegui un backup e conferma che lo schema selezionato sia eliminabile prima di procedere.
Scegliere DROP TABLE per questa operazione
DROP TABLE rimuove le tabelle; non equivale a DELETE, che rimuove le righe ma lascia la definizione della tabella, né a TRUNCATE, che svuota una tabella. DROP DATABASE è un’operazione diversa e più ampia: usala solo se intendi rimuovere anche il contenitore del database e i relativi oggetti di schema. L’eliminazione di una tabella rimuove anche i relativi trigger e provoca un commit implicito, quindi non è un’operazione da provare in una transazione contando su un rollback successivo.
Ti serve il privilegio DROP per le tabelle da rimuovere. Lavora su uno schema esplicitamente nominato, usa un backup o un database di test noto come eliminabile e mantieni nella stessa connessione MySQL le istruzioni di preparazione, eliminazione e ripristino.
Generare un elenco quotato delle tabelle di base
INFORMATION_SCHEMA.TABLES distingue una BASE TABLE da una vista. Il filtro table_type = 'BASE TABLE' evita quindi che l’eliminazione tratti le viste da conservare come tabelle. La query seguente racchiude inoltre gli identificatori tra backtick e raddoppia un backtick presente nel nome di una tabella prima di costruire l’istruzione.
Imposta group_concat_max_len a un valore sufficiente per il numero e la lunghezza dei nomi presenti nello schema. L’espressione IF produce un messaggio innocuo per uno schema vuoto invece di tentare un DROP TABLE senza nomi. Controlla il valore generato in @drop_sql prima di eseguirlo in un ambiente simile alla produzione.
Eliminare le tabelle di base collegate da chiavi esterne in una sessione
L’ordine delle chiavi esterne può far fallire l’eliminazione di singole tabelle. Salva il valore corrente della sessione, disabilita i controlli soltanto in questa sessione controllata, esegui l’istruzione generata e ripristina il valore salvato. Il seguente fixture esatto di MySQL 8.4.11 crea due tabelle collegate da una chiave esterna e una vista, elimina soltanto le tabelle e mostra i conteggi prima e dopo.
#!/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
L’output indica che inizialmente erano presenti due tabelle di base, nessuna dopo l’eliminazione, una vista ancora presente e FOREIGN_KEY_CHECKS ripristinato al valore originale abilitato. Questa strategia non elimina viste, procedure memorizzate, eventi, utenti o il database stesso.
Verificare lo schema dopo l’eliminazione
Esegui lo stesso conteggio di INFORMATION_SCHEMA.TABLES usato dal fixture e aspettati zero righe BASE TABLE. SHOW FULL TABLES FROM your_database è utile anche per verificare se gli oggetti rimanenti sono viste anziché tabelle. Se lo script modifica FOREIGN_KEY_CHECKS, controllane il valore di sessione prima di chiudere la connessione; non presumere che un’altra sessione abbia ereditato la modifica.
Comprendere il limite imposto dalle chiavi esterne
Senza disabilitare temporaneamente i controlli, MySQL rifiuta il tentativo di eliminare una tabella padre referenziata. Questo fixture di limite termina con l’errore 3730 e dimostra perché un elenco non ordinato di comandi DROP TABLE può fallire.
#!/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
La diagnostica acquisita è ERROR 3730 (HY000): MySQL segnala che parent è referenziata da child_parent_fk in child. Non usare la tecnica dei controlli disabilitati per aggirare una dipendenza sconosciuta; usala soltanto dopo aver confermato che l’eliminazione di ogni tabella di base è intenzionale.
Alternative per database eliminabili e automazione da riga di comando
Per uno schema interamente eliminabile, eliminare e ricreare il database può essere più semplice, ma è un’operazione più ampia della rimozione delle tabelle. Richiede gli appropriati privilegi a livello di database e rimuove oggetti che il metodo delle tabelle di base conserva deliberatamente. Non descriverla come un modo per preservare viste, routine o eventi.
mysqldump --add-drop-table --no-data può produrre uno script di eliminazione orientato alla shell, utile per l’automazione dopo una revisione. Evita di inserire una password direttamente nella riga di comando, controlla le istruzioni generate e mantieni le questioni di credenziali e portabilità distinte dal metodo SQL raccomandato.
Limiti e risoluzione dei problemi
Se non viene eliminata alcuna tabella, verifica prima lo schema selezionato e il filtro BASE TABLE. Uno schema molto grande può superare il limite di GROUP_CONCAT, quindi aumentalo consapevolmente oppure genera e controlla le istruzioni a gruppi. Un errore di privilegi indica che l’account non dispone dell’accesso DROP. Le viste rimangono per scelta progettuale; rimuovile separatamente solo quando fanno parte della pulizia approvata. Infine, poiché DROP TABLE esegue un commit implicito, ripristina un backup invece di aspettarti che un rollback recuperi i dati eliminati.