Exportar dados no SQLite é tarefa do shell, não do SQL
O SQLite não tem nada parecido com COPY ... TO do Postgres ou SELECT INTO OUTFILE do MySQL. Quem cuida da exportação de dados é o shell de linha de comando sqlite3, através dos chamados dot-commands: .mode, .headers, .output e .dump. Sabendo esses quatro, dá pra gerar CSV, JSON, texto puro ou um dump SQL completo a partir de qualquer banco.
A ideia é a seguinte: você diz ao shell como formatar os resultados (.mode), se quer incluir os nomes das colunas (.headers) e para onde mandar a saída (.output). Depois é só rodar a query, e o resultado dela cai direto no arquivo.
Vamos montar um banco bem simples pra brincar:
Três linhas, quatro colunas. Vamos exportar isso em vários formatos.
CSV: .mode csv com cabeçalho
O CSV é o formato de exportação mais comum — planilhas, pipelines de dados e praticamente qualquer ferramenta entendem ele. Dentro do shell do sqlite3:
sqlite> .mode csv
sqlite> .headers on
sqlite> .output users.csv
sqlite> SELECT * FROM users;
sqlite> .output stdout
O que aconteceu aí:
.mode csvformata cada linha como valores separados por vírgula, colocando aspas em campos que contenham vírgulas, aspas ou quebras de linha..headers oninclui uma primeira linha com os nomes das colunas. Sem isso, seu CSV sai sem cabeçalho — o que quase nunca é o que a gente quer..output users.csvredireciona os resultados para um arquivo. Daqui pra frente, a saída das consultas vai pra esse arquivo em vez de aparecer na tela.- O
SELECTé executado e grava no arquivo silenciosamente. .output stdoutdevolve a saída para o terminal, pra você conseguir ver o resultado da próxima query.
O arquivo gerado:
id,name,email,signup_date
1,"Ada Lovelace",ada@example.com,2025-01-15
2,"Boris Johnson",boris@example.com,2025-02-03
3,"Carmen Diaz",carmen@example.com,2025-03-22
Você pode exportar o resultado de qualquer query, não só tabelas inteiras — filtre, faça joins, agregue e depois redirecione a saída:
sqlite> .output recent_users.csv
sqlite> SELECT name, email FROM users WHERE signup_date >= '2025-02-01';
sqlite> .output stdout
Tudo em uma linha direto do terminal
Nem precisa entrar no shell interativo. Dá pra mandar os dot-commands e o SQL direto para o sqlite3 pelo terminal do sistema:
sqlite3 mydb.sqlite <<EOF
.headers on
.mode csv
.output users.csv
SELECT * FROM users;
EOF
Esse é o formato ideal para scripts e cron jobs — dá pra repetir sem precisar digitar nada na mão. O .output vale só para a sessão atual, então não fica sujando estado em lugar nenhum.
Exportar SQLite para JSON: .mode json
Quando o destino é uma aplicação web ou alguma ferramenta que consome JSON, o .mode json gera um array de objetos, um por linha:
sqlite> .mode json
sqlite> .output users.json
sqlite> SELECT * FROM users;
sqlite> .output stdout
The file:
[{"id":1,"name":"Ada Lovelace","email":"ada@example.com","signup_date":"2025-01-15"},
{"id":2,"name":"Boris Johnson","email":"boris@example.com","signup_date":"2025-02-03"},
{"id":3,"name":"Carmen Diaz","email":"carmen@example.com","signup_date":"2025-03-22"}]
No JSON, os cabeçalhos ficam implícitos (são as próprias chaves), então o .headers não tem efeito aqui. Se você quiser um formato personalizado — objetos aninhados, campos renomeados —, monte essa estrutura direto na query usando json_object():
Assim você gera strings JSON linha a linha com controle total sobre a estrutura. Combinando com json_group_array(), você consegue empacotar o resultado inteiro em um único documento JSON.
Dump SQL completo: .dump
O .dump joga em outra categoria, bem diferente do CSV ou JSON. Ele gera um arquivo .sql contendo o esquema e todos os dados na forma de comandos CREATE TABLE e INSERT — o suficiente para reconstruir o banco do zero:
sqlite3 mydb.sqlite .dump > backup.sql
Um trecho do que aparece:
PRAGMA foreign_keys=OFF;
BEGIN TRANSACTION;
CREATE TABLE users (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL,
email TEXT NOT NULL,
signup_date TEXT NOT NULL
);
INSERT INTO users VALUES(1,'Ada Lovelace','ada@example.com','2025-01-15');
INSERT INTO users VALUES(2,'Boris Johnson','boris@example.com','2025-02-03');
INSERT INTO users VALUES(3,'Carmen Diaz','carmen@example.com','2025-03-22');
COMMIT;
Restaurar é a operação inversa: basta redirecionar o arquivo de volta para um banco novinho:
sqlite3 restored.sqlite < backup.sql
.dump é a ferramenta certa para fazer backup, versionar snapshots de dados de teste e migrar bancos entre máquinas. Ele preserva índices, triggers, views — tudo o que faz parte do schema.
Fazendo dump de uma única tabela
O .dump aceita o nome de uma tabela (ou um padrão) para restringir a saída:
sqlite3 mydb.sqlite ".dump users" > users_only.sql
Isso exporta apenas o schema e os registros da tabela users. Bem útil quando você quer copiar uma tabela para outro banco sem levar o resto junto. Dá pra usar padrão também: .dump 'log_%' faz o dump de todas as tabelas que começam com log_.
Schema sem os dados
Em alguns casos, você só quer a estrutura, sem as linhas — seja para documentar, montar um ambiente de dev limpo ou comparar schemas entre bancos diferentes. O .schema mostra somente os comandos CREATE:
sqlite3 mydb.sqlite .schema > schema.sql
Combine com o nome de uma tabela para exportar apenas ela:
sqlite3 mydb.sqlite ".schema users" > users_schema.sql
A saída é SQL puro — CREATE TABLE, CREATE INDEX, CREATE TRIGGER — pronta para rodar em um banco vazio.
Outros modos úteis
O .mode tem várias opções além de CSV e JSON. Vale a pena conhecer alguns:
.mode column -- colunas alinhadas, ótimas para leitura no terminal
.mode markdown -- separadas por pipe, tabelas compatíveis com GitHub
.mode html -- saída em <table> HTML
.mode tabs -- valores separados por tabulação (TSV)
.mode insert users -- emite instruções INSERT para a tabela informada
.mode quote -- valores entre aspas SQL, útil para inspeção
.mode markdown cai como uma luva quando você precisa colar o resultado de uma query num README ou numa pull request. Já o .mode insert <tabela> é um atalho prático para gerar dados de seed — basta rodar um SELECT, copiar os comandos INSERT que aparecem e jogar tudo num arquivo de fixture.
sqlite> .mode insert users
sqlite> .output seed.sql
sqlite> SELECT * FROM users WHERE signup_date >= '2025-02-01';
sqlite> .output stdout
Algumas dicas práticas
.output stdout(ou.outputsem argumento) volta a imprimir no terminal. Se esquecer disso, o resultado da próxima query some calado dentro do arquivo.- Exportações em CSV não preservam tipos. Tudo vira texto no arquivo, e na hora de reimportar você precisa de um schema de destino para interpretar os valores. Se o que importa é levar os dados de volta para outro banco SQLite, use
.dump. - Exportações grandes são feitas em streaming. O
.outputgrava as linhas conforme elas são produzidas, então dá para despejar tabelas maiores que a RAM sem dor de cabeça. - Para um backup a quente de um banco em uso, o
.dumpfunciona, mas o comando dedicado.backup(que aparece mais adiante no curso) é mais rápido e seguro, já que usa a API de backup online do SQLite.
A seguir: consultando dados
Agora você já tem o panorama completo de escrita de dados — INSERT, UPDATE, DELETE, UPSERT, RETURNING, importação de CSV e exportação de volta. O próximo passo é a outra metade do trabalho com banco de dados: ler dados de forma eficiente. O SELECT é onde você vai gastar a maior parte do seu tempo, e é exatamente o assunto da próxima página.
Perguntas frequentes
Como exportar uma tabela do SQLite para CSV?
Dentro do shell sqlite3, mude para o modo CSV, ative os cabeçalhos, redirecione a saída para um arquivo e rode a consulta: .mode csv, .headers on, .output users.csv e depois SELECT * FROM users;. Ao terminar, execute .output stdout para voltar a imprimir os resultados no terminal.
Qual a diferença entre o .dump e exportar para CSV?
O .dump gera um arquivo .sql com os comandos CREATE TABLE e INSERT — tudo o que você precisa para reconstruir o banco do zero. Já o CSV contém apenas as linhas de uma consulta ou tabela, sem o esquema. Use .dump para backup e migração; use CSV quando precisar levar os dados para uma planilha ou outra ferramenta.
Dá para exportar o resultado de uma query do SQLite em JSON?
Dá sim. Você pode definir .mode json no shell e rodar qualquer SELECT, ou então usar as funções nativas json_object() e json_group_array() para montar o JSON dentro da própria consulta. O .mode json resolve rápido para exportações pontuais; já a abordagem com funções dá controle total sobre o formato final.