Uma conexão, vários arquivos
Uma conexão SQLite não fica presa a um único arquivo. Com ATTACH DATABASE, dá pra abrir outros arquivos .db junto com o que você já tinha aberto e consultar todos como se fossem schemas dentro de um mesmo banco. É o mais perto que o SQLite chega de ter "vários bancos no mesmo servidor".
A forma básica é esta:
O arquivo archive.db é criado caso ainda não exista, exatamente como acontece com o banco principal. Daqui pra frente, dentro dessa sessão, tudo que vier com o prefixo archive. mora nesse segundo arquivo. Já o que estiver com prefixo main. (ou sem prefixo nenhum) continua no banco original.
Toda conexão já vem com dois schemas implícitos: o main (o arquivo que você abriu primeiro) e o temp (uma área de rascunho pra tabelas temporárias). O ATTACH simplesmente adiciona mais schemas a essa lista.
A sintaxe do ATTACH DATABASE e o papel do alias
ATTACH DATABASE 'caminho/para/arquivo.db' AS nome_alias;
O alias é o nome do schema que você vai usar para qualificar as tabelas. Ele é local à conexão atual — outra conexão que anexar o mesmo arquivo pode escolher um alias diferente. Use algo curto e descritivo (archive, analytics, cache), porque você vai digitar bastante.
Alguns pontos que vale a pena saber:
- O caminho é relativo ao diretório de trabalho do processo, a menos que seja absoluto.
- A string
':memory:'anexa um banco em memória novinho sob aquele alias. - O alias não pode colidir com
mainnemtemp, e não pode se repetir entre anexações.
Fazendo join entre bancos SQLite
Esse é o motivo principal pelo qual a maioria das pessoas usa attach. Com dois arquivos na mesma conexão, dá para fazer join entre as tabelas deles em uma única consulta:
O planejador de consultas trata os dois schemas exatamente como trata as tabelas do main. Índices em tabelas anexadas são utilizados normalmente. EXPLAIN QUERY PLAN funciona entre eles. E não tem ida e volta pela rede — os dois arquivos ficam abertos no mesmo processo.
Isso é realmente útil para separar dados quentes de arquivos frios, isolar arquivos por tenant ou extrair dados de referência de um banco de consulta somente leitura.
Anexar banco SQLite em modo somente leitura ou em memória
Se o segundo banco é algo que você quer apenas ler, sem nunca alterar — um conjunto de dados de referência distribuído junto com a aplicação, por exemplo —, dá para anexar em modo somente leitura usando uma URI:
A forma com URI exige que a biblioteca do SQLite esteja com SQLITE_OPEN_URI habilitado (o que já é o caso na CLI e na maioria dos bindings de linguagens). A partir daí, qualquer INSERT, UPDATE ou DELETE em ref.* vai disparar um erro antes mesmo de encostar no arquivo.
Anexar bancos em memória também é bem prático para preparar dados temporários:
scratch desaparece quando a conexão é fechada. É parecido com temp, mas o tempo de vida fica nas suas mãos.
Transações abrangem todos os bancos anexados
Um único BEGIN/COMMIT cobre as escritas no main e em qualquer schema anexado. Ou tudo é commitado, ou tudo sofre rollback — a atomicidade é preservada entre os arquivos:
Mover linhas de uma tabela ativa para um arquivo de arquivamento é exatamente o tipo de operação em que você quer essa garantia. Sem atomicidade entre arquivos, uma queda no meio do caminho deixaria você com linhas duplicadas ou, pior, com linhas perdidas.
Um detalhe importante: quando mais de um banco anexado está sendo gravado dentro de uma mesma transação, o SQLite adota um protocolo de commit mais cauteloso, que exige um journal temporário. É mais lento do que um commit em arquivo único, mas continua sendo seguro.
Desanexando bancos com DETACH
Quando terminar de usar um banco anexado, basta desanexá-lo com sqlite detach database:
DETACH DATABASE archive;
O arquivo continua intacto no disco — o DETACH apenas fecha o handle na conexão atual. Duas restrições importantes:
- Não dá pra desanexar o
mainnem otemp. - Não dá pra desanexar um banco que está dentro de uma transação ou que tem statements abertos.
Se você esquecer de fazer o detach, não é o fim do mundo: ao fechar a conexão, tudo é liberado.
Limites e erros comuns
Alguns limites práticos que vale conhecer:
- O limite padrão é de 10 bancos anexados por conexão (além do
maine dotemp). O máximo em tempo de compilação é 125. Se estourar, aparecetoo many attached databases - max 10. - Cada arquivo anexado consome cache de páginas. Anexar uma dúzia de bancos grandes não sai de graça — o uso de RAM sobe.
- O próprio
ATTACHnão pode rodar dentro de uma transação. Execute antes doBEGINou depois doCOMMIT.
Alguns erros que você provavelmente vai encontrar:
-- O arquivo não existe e o diretório não tem permissão de escrita:
Error: unable to open database: 'missing/path.db'
-- Você tentou escrever em um anexo somente leitura:
Error: attempt to write a readonly database
-- Você usou o mesmo alias duas vezes:
Error: database archive is already in use
A maioria desses erros fica óbvia quando você lê com calma. O que mais pega gente desprevenida é o "already in use" — o ATTACH não substitui um alias existente; você precisa dar DETACH antes.
Um padrão na prática: separação hot/cold
Juntando tudo — um pequeno fluxo de arquivamento que tira do banco principal os pedidos com mais de um ano:
As linhas antigas vão para archive.orders, e as recentes ficam em main. Relatórios que precisam do histórico podem fazer join entre os dois bancos; já as consultas do dia a dia em main.orders continuam rápidas, porque a tabela fica menor. Mesma conexão, dois arquivos, uma única transação.
Próximo passo: Prepared Statements
O ATTACH serve para dar a uma única conexão acesso a mais dados. Os próximos tópicos vão focar em como as aplicações conversam com o SQLite de forma segura e eficiente — começando pelos prepared statements, que são a base do binding de parâmetros e de consultas à prova de SQL injection.
Perguntas frequentes
O que o ATTACH DATABASE faz no SQLite?
O comando ATTACH DATABASE 'arquivo.db' AS apelido abre um segundo arquivo SQLite dentro da conexão atual e atribui um nome de schema a ele. A partir daí, dá para referenciar as tabelas como apelido.nome_da_tabela e fazer JOIN com tabelas do banco principal numa única consulta.
Quantos bancos o SQLite consegue anexar ao mesmo tempo?
Por padrão, o SQLite permite até 10 bancos anexados por conexão, além dos schemas main e temp. O teto absoluto é 125 e pode ser ajustado em tempo de compilação pela opção SQLITE_MAX_ATTACHED. Se você estourar o limite, recebe o erro too many attached databases.
Dá para consultar vários bancos SQLite anexados em uma só instrução?
Sim. Depois de anexados, basta qualificar cada tabela com o nome do schema — algo como SELECT * FROM main.users JOIN archive.orders ON .... JOINs, subconsultas e INSERT ... SELECT funcionam normalmente entre schemas. As transações também abrangem todos os bancos anexados, então um COMMIT é atômico em todos os arquivos de uma vez.
Como faço para desanexar um banco SQLite?
É só executar DETACH DATABASE apelido. O arquivo continua intacto no disco — o DETACH apenas fecha o handle dentro da conexão atual. Não é possível desanexar main nem temp, e também não dá para desanexar um banco que esteja no meio de uma transação.