Comando sqlite3: O Caminho Mais Curto para Testar SQL no Terminal

Comando sqlite3: O Caminho Mais Curto para Testar SQL no Terminal

O que você vai conseguir fazer

  • Abrir um banco de dados com `sqlite3 gym.db`, criar uma tabela e inserir dados
  • Selecionar só as linhas necessárias com `SELECT` / `WHERE` / `ORDER BY` / `LIMIT` / `COUNT(*)`
  • Ligar o resultado do SQL a `sort` / `uniq` por pipe e transformar o banco em texto com `.dump`

Pré-requisitos (leia estes primeiro)

O Que Você Vai Aprender

  • Como criar um banco de dados em um único arquivo com sqlite3
  • O SQL mínimo para criar uma tabela, inserir dados e buscá-los com SELECT
  • Por que os números diferem entre COUNT(*) e wc -l
  • Como ligar o resultado do SQL a sort / uniq por pipe e como transformar o banco em texto com .dump

Palavras usadas aqui (organizadas antes)

  • Banco de dados: um sistema que guarda dados para você buscar e contar depois. Também se escreve "BD" ou "DB".
  • Tabela: dados organizados em linhas e colunas. É parecida com uma planilha do Excel.
  • Linhas e colunas: a linha atravessa a tabela na horizontal, a coluna desce na vertical. Também se chamam "registros" e "campos".
  • SQL: a linguagem usada para dar ordens a um banco de dados. Lê-se "ésse-quê-éle". Um comando escrito em SQL também se chama "consulta" (query).
  • SQLite e sqlite3: SQLite é o nome do software. sqlite3 é o nome do comando que o opera.
  • CSV: um arquivo de texto com os valores separados por vírgula (,).
  • PromptUm símbolo (como $ ou #) exibido quando o shell está esperando sua entrada.: o sinal no início da linha que diz "você pode digitar aqui". No terminalUm programa interativo que interpreta os comandos digitados e os executa. comum, a linha termina com $, como em user@nomedopc:~$. Não digite o $ que aparece neste artigo.

Ambiente

1. Por Que o sqlite3?

Conclusão: O SQLite não precisa de servidor. O banco de dados inteiro vira um único arquivo, que você trata como qualquer arquivo visto com ls.

Lina: Veterano Linny, quero testar SQL. Mas montar um servidor de banco de dados parece dar muito trabalho.
Veterano Linny: Isso vale para muitos bancos de dados. Mas o SQLite não precisa de servidor. O banco de dados inteiro vira um arquivo.
Lina: Só um arquivo? Dá para ver com ls?
Veterano Linny: Dá. O gym.db que vamos criar aparece assim no ls -l.
$ ls -l gym.db
-rw-r--r-- 1 user user 8192 Oct 24 02:18 gym.db

O gym.db ainda não existe, então você pode testar este ls -l depois da seção 4. O nome do dono e a data mudam conforme o ambiente.

2. Como Instalo o sqlite3?

Conclusão: No Ubuntu e no WSL, instale com apt. O Mac já vem com ele. Nos dois casos, confira com sqlite3 --version.

No Ubuntu / sistemas baseados em Debian

$ sudo apt update
$ sudo apt install sqlite3
$ sqlite3 --version
3.45.1 2024-01-30 16:01:20 e876e51a0ed5c5b3126f52e532044363a014bc594cfefa87ffb5b82257ccalt1 (64-bit)

O sudo executa um comando com permissãoAs regras de acesso de leitura / escrita / execução definidas em um arquivo ou diretório. de administrador. Se ele pedir uma senha, digite a sua senha de login. A tela não mostra nada enquanto você digita, nem *. Digite até o fim e aperte Enter. O primeiro número que o sqlite3 --version mostra é a versão. Neste exemplo, é 3.45.1.

No Windows: abra o Ubuntu no WSL (um jeito de rodar Linux dentro do Windows). Depois, siga os mesmos passos do apt. Se você ainda não tem o WSL, comece pela Introdução ao WSL2.

No Mac: o macOS já vem com o sqlite3. Confira com sqlite3 --version. Dá para testar tudo neste artigo com o sqlite3 que vem com o macOS.

É mais seguro criar antes um diretórioUm local que organiza arquivos. É a mesma ideia da "pasta" do Windows ou macOS. de prática (uma pasta).

$ mkdir ~/sqlite-practice
$ cd ~/sqlite-practice

Todos os arquivos deste artigo ficam dentro dele.

3. O Que Muda Quando Inicio o sqlite3?

Conclusão: Ao iniciar sqlite3 gym.db, o prompt vira sqlite>. Comandos que começam com ponto são ordens para o próprio sqlite3.

Veterano Linny: Vamos iniciar. Escreva o nome do arquivo do banco de dados depois de sqlite3.
Lina: Eu ainda não criei o gym.db. Tem problema?
Veterano Linny: Não tem. A documentação oficial diz que o arquivo é criado automaticamente se não existir. Para ser exato, o arquivo aparece quando você cria uma tabela.
$ sqlite3 gym.db
SQLite version 3.45.1 2024-01-30 16:01:20
Enter ".help" for usage hints.
sqlite>
Lina: A última linha mudou de $ para sqlite>.
Veterano Linny: Isso quer dizer "agora você está dentro do sqlite3". Aqui você digita SQL e "comandos de ponto", que começam com .. Os comandos de ponto são ordens para o próprio sqlite3.

Estes são os cinco que você usa primeiro.

Comando de ponto O que faz
.tables Lista as tabelas
.schema members Mostra como a tabela members foi definida
.headers on Mostra os nomes das colunas na 1ª linha
.mode column Alinha o resultado em colunas
.quit Sai do sqlite3 e volta ao $

Não coloque ponto e vírgula (;) no fim de um comando de ponto. No fim do SQL, sempre coloque ;.

A versão 3.54.0 e as posteriores mostram outro prompt (veja o item 3.54.0 do histórico de versões). O exemplo da documentação oficial é SQLite-3.54 ex1.db->. O que você digita é o mesmo.

Nos exemplos de código, não digite o $ ou o sqlite> do início. Digite só o que vem depois. Se usar o botão de copiar, apague o sqlite> (ou o $ ) do início depois de colar e só então aperte Enter.

As seções 4 e 5 continuam no prompt sqlite>. Se parar no meio, saia com .quit e volte com sqlite3 gym.db. A tabela e os dados continuam no arquivo. Não digite de novo o CREATE TABLE e os INSERT da seção 4 (isso adiciona as mesmas linhas outra vez). O .headers on e o .mode column são apagados, então digite os dois de novo ao voltar pela seção 5.

4. Como Crio uma Tabela e Insiro Dados?

Conclusão: CREATE TABLE define o formato da tabela, e INSERT adiciona os dados uma linha por vez. Sempre termine o SQL com ;.

Veterano Linny: Vamos criar uma tabela de membros da academia. Ela tem quatro colunas: id (número), name (nome), city (cidade onde mora) e age (idade).
Lina: Então é como escrever os títulos na primeira linha do Excel.
sqlite> CREATE TABLE members (id INTEGER PRIMARY KEY, name TEXT, city TEXT, age INTEGER);
sqlite> INSERT INTO members (name, city, age) VALUES ('Pip', 'Tokyo', 24);
sqlite> INSERT INTO members (name, city, age) VALUES ('Momo', 'Osaka', 31);
sqlite> INSERT INTO members (name, city, age) VALUES ('Kai', 'Tokyo', 19);

Se der certo, nada aparece e o próximo sqlite> surge.

Confira o resultado com os comandos de ponto.

sqlite> .tables
members
sqlite> .schema members
CREATE TABLE members (id INTEGER PRIMARY KEY, name TEXT, city TEXT, age INTEGER);
Lina: O .tables parece o ls, e o .schema parece o cat.
Veterano Linny: Boa forma de ver. Use .tables para ver os nomes das tabelas, e .schema para ler como uma tabela foi montada.

Se você esquecer o ; e apertar Enter, o prompt vira ...>. Isso quer dizer "esperando o resto". Digite só ; e aperte Enter para executar.

5. Como Pego Só as Linhas Que Preciso?

Conclusão: Filtre com WHERE, ordene com ORDER BY e corte com LIMIT. Eles fazem o mesmo papel de grep, sort e head.

Primeiro, mostre tudo o que está na tabela. O * quer dizer "todas as colunas".

sqlite> SELECT * FROM members;
1|Pip|Tokyo|24
2|Momo|Osaka|31
3|Kai|Tokyo|19
Lina: Funcionou, mas os separadores | são difíceis de ler. Não sei qual coluna é qual.
Veterano Linny: Para isso servem o .headers on e o .mode column. Os nomes das colunas aparecem e tudo fica alinhado.
sqlite> .headers on
sqlite> .mode column
sqlite> SELECT * FROM members;
id  name  city   age
--  ----  -----  ---
1   Pip   Tokyo  24
2   Momo  Osaka  31
3   Kai   Tokyo  19

Na versão 3.53.0 e posteriores, uma sessão no terminal já mostra uma tabela com bordas desde o início (segundo https://sqlite.org/climode.html e o item 3.53.0 do histórico de versões). Mesmo numa versão mais nova, digite .headers on e .mode column neste artigo.

5-1. Filtrar linhas com WHERE (como o grep)

sqlite> SELECT name, age FROM members WHERE city = 'Tokyo';
name  age
----  ---
Pip   24
Kai   19

Como no grep Tokyo, só aparecem as linhas que atendem à condição.

5-2. Ordenar linhas com ORDER BY (como o sort)

sqlite> SELECT name, age FROM members ORDER BY age DESC;
name  age
----  ---
Momo  31
Pip   24
Kai   19

DESC quer dizer do maior para o menor. É o mesmo sentido do sort -rn. Sem o DESC, a ordem é do menor para o maior.

5-3. Cortar a quantidade com LIMIT (como o head)

sqlite> SELECT name, age FROM members ORDER BY age DESC LIMIT 2;
name  age
----  ---
Momo  31
Pip   24

Como no head -n 2, só aparecem as duas primeiras linhas.

6. O Que Acontece Quando Conto?

Conclusão: COUNT(*) conta as linhas da tabela. Grave em CSV e conte com wc -l, e a linha com os nomes das colunas soma uma a mais.

sqlite> SELECT COUNT(*) FROM members;
COUNT(*)
--------
3
Lina: Três membros. Quero salvar em CSV e conferir o número com wc -l também.
Veterano Linny: Use .mode csv para o formato CSV, e .once para gravar "só o próximo resultado" em um arquivo.
sqlite> .mode csv
sqlite> .once members.csv
sqlite> SELECT * FROM members;
sqlite> .quit
$ wc -l members.csv
4 members.csv

O .quit trouxe o prompt de volta ao $, então o último wc -l roda como um comando normal do Linux.

Lina: O quê? Quatro linhas, mas são três membros. Não deu erro nenhum, e mesmo assim os números não batem.
Veterano Linny: Vamos olhar o conteúdo.
$ cat members.csv
id,name,city,age
1,Pip,Tokyo,24
2,Momo,Osaka,31
3,Kai,Tokyo,19
Lina: Ah, a primeira linha é id,name,city,age. Eu liguei o .headers on antes, então os nomes das colunas também foram gravados.
Veterano Linny: Exatamente. O wc -l conta as linhas de um arquivo, e o COUNT(*) conta as linhas de uma tabela. Eles contam coisas diferentes.
Lina: Então um comando que roda sem erro ainda pode dar o número errado. Entendi por que vale comparar duas formas de contar.

Para contar sem a linha dos nomes das colunas, use tail -n +2 (mostra da linha 2 até o fim).

$ tail -n +2 members.csv | wc -l
3

Agora bate com o 3 do COUNT(*). Configurações como .headers on voltam ao padrão quando você sai do sqlite3.

7. Como Ligo o Resultado do SQL a um Pipe?

Conclusão: Escrever sqlite3 ARQUIVO "SQL" executa uma vez e sai. O resultado é texto simples, então vai direto para sort ou uniq por pipe.

Lina: Entrar no sqlite3 e sair com .quit toda vez dá um pouco de trabalho.
Veterano Linny: Escreva um comando SQL depois do nome do arquivo, e ele roda ali mesmo e sai (segundo a documentação oficial). O resultado é só texto, então você pode usar um pipe.
$ sqlite3 gym.db "SELECT city FROM members" | sort | uniq -c
      1 Osaka
      2 Tokyo
  • sqlite3 gym.db "SELECT city FROM members" mostra o nome das cidades, uma por linha
  • sort junta as cidades iguais lado a lado
  • uniq -c conta as linhas iguais

Esta forma não usa o .headers on, então nenhuma linha com nomes de colunas aparece. Segundo a documentação oficial, o resultado sai no "modo list" (separado por |).

7-1. Experimente o modo interativo no terminal virtual

O estado em que o prompt sqlite> da seção 3 está na tela se chama "modo interativo". Você digita uma linha por vez e vê o resultado na hora.

Você também pode experimentar o modo interativo no terminal virtual deste site. Abra o desafio "Contar os membros" e digite as linhas abaixo, nesta ordem. Não digite o $ ou o sqlite> do início.

$ sqlite3 gym.db
sqlite> SELECT COUNT(*) FROM members;
(uma linha com o número de membros do gym.db do desafio)
sqlite> .quit

O gym.db do terminal virtual foi preparado para o desafio, então o número é diferente dos 3 membros deste artigo. Quando a contagem estiver certa, o desafio aparece como concluído. A forma de execução única da seção 7 (sqlite3 gym.db "SELECT COUNT(*) FROM members;") também conclui o desafio. No terminal virtual, o prompt é sqlite> em qualquer versão.

8. Como Transformo o Banco de Dados em Texto?

Conclusão: .dump transforma o banco inteiro em texto SQL. Passe esse texto ao sqlite3 e você reconstrói o mesmo banco de dados.

O > sobrescreve sem perguntar

Se já existe um arquivo com o mesmo nome, o > apaga o conteúdo e grava de novo. Diferente de uma interface gráfica, ele não pergunta "Deseja substituir?". O .once da seção 6 também sobrescreve do mesmo jeito. Antes de digitar, confira com ls que não existe um arquivo com o mesmo nome, e teste dentro do seu diretório de prática.

$ sqlite3 gym.db .dump > backup.sql
$ cat backup.sql
PRAGMA foreign_keys=OFF;
BEGIN TRANSACTION;
CREATE TABLE members (id INTEGER PRIMARY KEY, name TEXT, city TEXT, age INTEGER);
INSERT INTO members VALUES(1,'Pip','Tokyo',24);
INSERT INTO members VALUES(2,'Momo','Osaka',31);
INSERT INTO members VALUES(3,'Kai','Tokyo',19);
COMMIT;
Lina: O CREATE TABLE e os INSERT que eu digitei estão aqui.
Veterano Linny: Ele gravou o banco como o SQL que o reconstrói. Vamos passar isso para um arquivo novo.

BEGIN TRANSACTION e COMMIT executam o SQL entre eles como um bloco só. A linha PRAGMA é uma configuração que o sqlite3 adicionou sozinho. Por enquanto, pode pular essas linhas.

$ sqlite3 new.db < backup.sql
$ sqlite3 new.db "SELECT * FROM members"
1|Pip|Tokyo|24
2|Momo|Osaka|31
3|Kai|Tokyo|19

O < passa o conteúdo de um arquivo para um comando. O SQL do backup.sql rodou de cima para baixo, e o new.db agora tem a mesma tabela.

9. Erros Comuns e Como Resolver

Conclusão: A maioria dos erros vem de quatro coisas: ponto e vírgula, aspas, maiúsculas e minúsculas, e nome de arquivo. Se aparecer um erro, leia a mensagem. Se não houver erro mas o resultado parecer errado, veja o conteúdo direto com SELECT * ou ls -l.

Sintoma Causa Conferir / resolver
Parse error: near "sqlite": syntax error Você copiou também o sqlite> do início Apague o sqlite> e digite de novo
O prompt fica em ...> Falta o ; no fim do SQL Digite só ; e aperte Enter
Parse error: no such column: Tokyo O texto não está entre aspas ' Use aspas, como em WHERE city = 'Tokyo'
WHERE city = 'tokyo' não mostra nada A comparação de texto diferencia maiúsculas e minúsculas Escreva como está na tabela (Tokyo)
O gym.db não existe depois de iniciar e sair logo em seguida No 3.45.1, o arquivo não é criado se você não fizer nada Crie uma tabela antes do .quit e confira com ls -l
O número de membros aumentou depois de table members already exists Você executou os INSERT duas vezes Apague com DELETE FROM members WHERE id > 3; ou crie o gym.db de novo
new.db < backup.sql mostra table members already exists O new.db já tem a mesma tabela Passe para um arquivo com outro nome (ex.: new2.db)

O caso do 'tokyo' devolve zero linhas sem erro. Quando o resultado vier vazio, rode primeiro SELECT * FROM members; para ver como os valores estão gravados.

10. Mini Exercícios: Tente Você Mesmo

Conclusão: Teste ordenar, contar e usar pipe com as próprias mãos. As respostas estão nas seções recolhidas.

Exercício 1: Ordene do mais novo para o mais velho

Tarefa: Entre com sqlite3 gym.db e digite .headers on e .mode column. Depois, mostre o nome e a idade de todos os membros, do mais novo para o mais velho.

Ver dica 1 (direcionamento)

Adicione depois do SELECT a expressão para "ordenar". Deixe de fora a palavra que você usou para o maior primeiro.

Ver dica 2 (nome do comando)

Use ORDER BY age. Não adicione DESC.

Ver a resposta
sqlite> SELECT name, age FROM members ORDER BY age;
name  age
----  ---
Kai   19
Pip   24
Momo  31

Exercício 2: Conte os membros de Osaka

Tarefa: Conte quantos membros têm city igual a Osaka, usando só SQL.

Ver dica 1 (direcionamento)

Combine duas coisas: "contar" e "filtrar por uma condição".

Ver dica 2 (nome do comando)

Adicione WHERE city = 'Osaka' ao SELECT COUNT(*).

Ver a resposta
sqlite> SELECT COUNT(*) FROM members WHERE city = 'Osaka';
COUNT(*)
--------
1

Exercício 3: Conte os membros de Tokyo com um pipe

Tarefa: Primeiro, volte ao $ com .quit. Depois, sem entrar no sqlite3, mostre os nomes dos membros de Tokyo e conte essas linhas com um comando do Linux.

Ver dica 1 (direcionamento)

Confira se o prompt é $. Use a forma que executa o sqlite3 uma vez e sai. Passe o resultado para o comando que conta linhas.

Ver dica 2 (nome do comando)

Adicione | wc -l depois de sqlite3 gym.db "SELECT ...".

Ver a resposta
$ sqlite3 gym.db "SELECT name FROM members WHERE city = 'Tokyo'" | wc -l
2

Esta forma não mostra a linha com os nomes das colunas, então o número do wc -l já é a quantidade de membros.

11. Revisão

Lina: Vou resumir. O SQLite não precisa de servidor, e o banco de dados era um único arquivo chamado gym.db.
Veterano Linny: Isso. Criamos a tabela com CREATE TABLE e adicionamos as linhas com INSERT.
Lina: O WHERE parece o grep, o ORDER BY parece o sort e o LIMIT parece o head. E o wc -l deu um a mais por causa da linha com os nomes das colunas.
Veterano Linny: Essa é a parte mais importante. Comparar contagens feitas de duas formas mostra a diferença. Lembre também que o .dump transforma tudo de volta em texto.

Resumo de Hoje em 3 Linhas

  1. O SQLite não precisa de servidor, e o banco de dados é um único arquivo que você vê com ls
  2. SELECT / WHERE / ORDER BY / LIMIT correspondem a grep / sort / head
  3. COUNT(*) e wc -l contam coisas diferentes. Atenção à primeira linha de um CSV (os nomes das colunas)

Resumo: O Que Ler a Seguir

Compartilhe este artigo

Próximo passo