Menu

DROP TABLE e ALTER TABLE no SQLite: guia prático

Como apagar, renomear e alterar tabelas no SQLite — o que o ALTER TABLE consegue fazer, o que ele não faz e o truque do rebuild para os casos que não dá.

Esta página tem editores executáveis — edite, execute e veja a saída na hora.

Schemas mudam. O SQLite te deixa mudar — quase tudo.

Depois que uma tabela existe, em algum momento você vai querer renomeá-la, adicionar uma coluna, remover uma coluna ou reestruturar tudo. O SQLite cobre os casos mais comuns direto com DROP TABLE e ALTER TABLE, e ainda oferece um workaround documentado pra todo o resto.

O detalhe: o ALTER TABLE do SQLite é bem mais limitado que o do Postgres ou do MySQL. Saber o que ele faz e o que não faz — e dominar o padrão de rebuild para o que não faz — é praticamente toda a habilidade necessária aqui.

Como apagar tabela no SQLite com DROP TABLE

O DROP TABLE apaga a tabela, suas linhas, seus índices e qualquer trigger definida sobre ela. E não tem como desfazer:

A tabela já era. Se você tentar consultá-la agora, vai tomar um no such table: scratch.

Quando não dá pra ter certeza se a tabela existe — situação clássica em scripts de setup — use IF EXISTS para que o comando simplesmente não faça nada caso ela não esteja lá:

Sem o IF EXISTS, o segundo DROP quebraria com erro. Com ele, os dois rodam sem dor de cabeça.

Foreign keys podem barrar o DROP

Se a checagem de chaves estrangeiras estiver ativa (PRAGMA foreign_keys = ON;) e existir outra tabela referenciando aquela que você quer apagar, o DROP falha:

sqlite> PRAGMA foreign_keys = ON;
sqlite> DROP TABLE users;
Runtime error: FOREIGN KEY constraint failed

Você tem algumas saídas: apagar primeiro a tabela que faz referência, deletar as linhas que referenciam, ou definir a foreign key com ON DELETE CASCADE na hora da criação. O SQLite não vai quebrar a integridade referencial silenciosamente pra você.

ALTER TABLE no SQLite: as quatro operações suportadas

O ALTER TABLE do SQLite aceita exatamente quatro operações:

Cada um desses comandos roda como uma única instrução. Os dois primeiros são praticamente de graça — apenas atualizam o schema. O ADD COLUMN também é rápido: o SQLite não reescreve a tabela, só registra a definição da nova coluna. Já o DROP COLUMN é mais pesado — o SQLite precisa reescrever cada linha para remover fisicamente os dados da coluna.

ADD COLUMN com valor padrão

Uma coluna nova em uma tabela já existente começa como NULL em todas as linhas, a menos que você defina um valor padrão:

Os dois registros existentes recebem 'active'. O valor padrão precisa ser uma constante — o SQLite não aceita CURRENT_TIMESTAMP nem qualquer outra expressão não-constante como default no ADD COLUMN, porque ele precisa de um valor que possa ser aplicado a todas as linhas existentes sem avaliar linha por linha.

Se você precisa de NOT NULL sem default, o jeito é adicionar a coluna como nullable, preencher os valores com um UPDATE e depois reconstruir a tabela para aplicar a restrição. O que nos leva direto às limitações.

Limitações do ALTER TABLE no SQLite

Coisas que funcionam no Postgres ou MySQL, mas não no SQLite:

  • Mudar o tipo de uma coluna (ALTER COLUMN ... TYPE ...).
  • Alterar o default de uma coluna no lugar.
  • Adicionar ou remover NOT NULL, CHECK, UNIQUE ou PRIMARY KEY em uma coluna existente.
  • Adicionar uma chave estrangeira em uma coluna que já existe.
  • Reordenar colunas.

Qualquer tentativa dessas resulta em erro de sintaxe. O SQLite simplesmente não tem a cláusula ALTER COLUMN. A resposta oficial é sempre a mesma: refazer a tabela.

O padrão de rebuild de tabela

Quando o ALTER TABLE não dá conta, o caminho é criar uma nova tabela com o schema desejado, copiar os dados, apagar a antiga e renomear a nova no lugar dela. Faça tudo dentro de uma transação para garantir o "tudo ou nada":

Agora users.age é um inteiro com uma check constraint, e email é NOT NULL. Os dados vieram junto na viagem.

Alguns pontos para ter em mente quando você for fazer isso pra valer:

  • Desligue as foreign keys durante o processo. Se outras tabelas referenciam a sua, rode PRAGMA foreign_keys = OFF; antes da transação e PRAGMA foreign_keys = ON; depois. Caso contrário, o DROP TABLE vai falhar. Esse pragma não pode ser alterado dentro de uma transação, então defina ele do lado de fora.
  • Recrie índices e triggers. Ao apagar a tabela antiga, os índices e triggers dela vão junto. Adicione novamente na tabela nova depois de renomear.
  • Verifique as views. Views que referenciam a tabela continuam apontando para o nome antigo no SQL armazenado. Reconstrua qualquer uma que dependa de colunas alteradas.

O padrão de rebuild de tabela no SQLite é verboso, mas confiável. É exatamente o que ferramentas de migração como Alembic e Rails fazem por baixo dos panos quando o alvo é SQLite.

Apagando várias tabelas no SQLite

Não existe um único comando para apagar várias tabelas de uma vez — você roda um DROP TABLE para cada uma. Dentro de uma transação, se quiser agrupar tudo:

Quando você envolve tudo em uma transação, ou os três DROP funcionam ou nenhum acontece — algo bem útil ao derrubar tabelas relacionadas que podem falhar por causa de chaves estrangeiras no meio do caminho.

O que fica de aprendizado

  • DROP TABLE apaga a tabela junto com seus índices e triggers. Use IF EXISTS para deixar seus scripts idempotentes.
  • ALTER TABLE no SQLite só faz quatro coisas: renomear tabela, renomear coluna, adicionar coluna e remover coluna.
  • Para qualquer coisa além disso — mudar tipo, adicionar constraints novas, criar chave estrangeira em coluna já existente — faça o rebuild da tabela dentro de uma transação.
  • Fique de olho em chaves estrangeiras, índices, triggers e views ao reconstruir uma tabela. Eles não acompanham os dados automaticamente.

A seguir: colocando dados nas tabelas

Você passou um capítulo inteiro falando de tabelas e das constraints que dão forma a elas. Agora é hora de povoá-las — o próximo capítulo começa com o INSERT, incluindo a versão que insere várias linhas de uma vez, valores padrão e como o SQLite reage quando uma inserção bate de frente com suas constraints.

Perguntas frequentes

Como apagar uma tabela no SQLite?

Use DROP TABLE nome_da_tabela;. Se quiser que o comando não dê erro caso a tabela não exista, acrescente IF EXISTS: DROP TABLE IF EXISTS users;. Ao apagar a tabela, os índices e triggers ligados a ela também são removidos. E atenção: se as foreign keys estiverem habilitadas, o DROP falha quando outras tabelas ainda fazem referência a ela.

O que dá pra fazer com ALTER TABLE no SQLite?

Basicamente quatro coisas: RENAME TO (renomear a tabela), RENAME COLUMN ... TO ... (renomear uma coluna), ADD COLUMN (adicionar uma nova coluna) e DROP COLUMN (remover uma coluna, a partir do SQLite 3.35). E é só isso — não dá pra mudar o tipo de uma coluna, alterar o default no lugar, nem adicionar uma constraint a uma coluna já existente.

Como faço para mudar o tipo ou as constraints de uma coluna no SQLite?

O SQLite não suporta isso direto. A saída clássica é o padrão de rebuild: cria uma nova tabela com o schema desejado, faz INSERT INTO nova SELECT ... FROM antiga, depois DROP TABLE antiga e por fim ALTER TABLE nova RENAME TO antiga. Coloca tudo dentro de uma transação para o processo ser atômico.

Coddy programming languages illustration

Aprenda a programar com o Coddy

COMEÇAR