HOWTO · MySQL

Como eliminar todas as tabelas no MySQL

Remova com segurança todas as tabelas base de um esquema MySQL, trate chaves estrangeiras e verifique o resultado.

Nesta página

Para eliminar todas as tabelas e manter o próprio banco de dados MySQL, gere uma instrução DROP TABLE revisada para os objetos BASE TABLE do esquema, execute-a na mesma sessão com FOREIGN_KEY_CHECKS temporariamente desativado e confirme o resultado. As definições e os dados das tabelas são removidos permanentemente; faça um backup e confirme que o esquema selecionado pode ser descartado antes de continuar.

Escolha DROP TABLE para esta tarefa

DROP TABLE remove tabelas; não é o mesmo que DELETE, que remove linhas mas mantém a definição da tabela, nem que TRUNCATE, que esvazia uma tabela. DROP DATABASE é uma operação diferente e mais ampla: use-a somente se também pretende remover o contêiner do banco de dados e os objetos do esquema. Remover uma tabela também remove seus gatilhos e causa um commit implícito, portanto não é uma operação para testar em uma transação esperando revertê-la depois.

Você precisa do privilégio DROP nas tabelas que removerá. Trabalhe em um esquema identificado, use um backup ou um banco de testes comprovadamente descartável e mantenha os comandos de preparação, remoção e restauração na mesma conexão MySQL.

Gere uma lista entre aspas das tabelas de base

INFORMATION_SCHEMA.TABLES distingue uma BASE TABLE de uma visão. Filtrar por table_type = 'BASE TABLE' evita que a remoção trate visões que devem ser mantidas como tabelas. A consulta também envolve identificadores com crases e duplica uma crase que apareça no nome da tabela antes de montar a instrução.

Defina group_concat_max_len para acomodar a quantidade e o comprimento dos nomes no esquema. A expressão IF produz uma mensagem inofensiva para um esquema vazio em vez de tentar executar DROP TABLE sem nomes. Revise o valor gerado em @drop_sql antes de executá-lo em um ambiente semelhante à produção.

Remova tabelas de base ligadas por chave estrangeira em uma sessão

A ordem das chaves estrangeiras pode fazer remoções individuais falharem. Salve o valor atual da sessão, desative as verificações somente nessa sessão controlada, execute a instrução gerada e restaure o valor salvo. O fixture exato do MySQL 8.4.11 a seguir cria duas tabelas ligadas por chave estrangeira e uma visão, remove somente as tabelas e mostra as contagens antes e depois.

#!/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

A saída mostra duas tabelas de base inicialmente, nenhuma após a remoção, uma visão ainda presente e FOREIGN_KEY_CHECKS restaurado ao valor original habilitado. Essa estratégia não exclui visões, procedimentos armazenados, eventos, usuários nem o próprio banco de dados.

Verifique o esquema após a remoção

Execute a mesma contagem em INFORMATION_SCHEMA.TABLES usada pelo fixture e espere zero linhas BASE TABLE. SHOW FULL TABLES FROM your_database também ajuda a inspecionar se os objetos restantes são visões em vez de tabelas. Se o script alterar FOREIGN_KEY_CHECKS, confira o valor da sessão antes de fechar a conexão; não suponha que outra sessão herdou a alteração.

Entenda o limite de falha da chave estrangeira

Sem desativar temporariamente as verificações, o MySQL rejeita a tentativa de remover uma tabela pai referenciada. Esse fixture de limite termina com o erro 3730 e demonstra por que uma lista sem ordem de comandos DROP TABLE pode falhar.

#!/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

O diagnóstico capturado é ERROR 3730 (HY000): o MySQL informa que parent é referenciada por child_parent_fk em child. Não use a técnica de verificações desativadas para contornar uma dependência desconhecida; use-a apenas depois de confirmar que a exclusão de todas as tabelas de base é intencional.

Alternativas para bancos descartáveis e automação de linha de comando

Para um esquema inteiramente descartável, excluir e recriar o banco de dados pode ser mais simples, mas é uma operação mais ampla que remover tabelas. Ela exige os privilégios adequados no banco de dados e remove objetos que o método das tabelas de base deliberadamente preserva. Não a apresente como uma maneira de preservar visões, rotinas ou eventos.

mysqldump --add-drop-table --no-data pode produzir um script de remoção voltado ao shell, útil para automação após revisão. Evite colocar uma senha diretamente na linha de comando, inspecione as instruções geradas e mantenha as questões de credenciais e portabilidade separadas do método SQL recomendado.

Limites e solução de problemas

Se nenhuma tabela for removida, primeiro confirme o esquema escolhido e o filtro BASE TABLE. Um esquema muito grande pode ultrapassar o limite de GROUP_CONCAT; aumente-o deliberadamente ou gere e revise instruções em lotes. Um erro de privilégio significa que a conta não tem acesso DROP. As visões permanecem por projeto; remova-as separadamente apenas quando isso fizer parte da limpeza aprovada. Por fim, como DROP TABLE faz commit implícito, restaure um backup em vez de esperar que um rollback recupere os dados excluídos.