SQL Datas e Horas
Quase todo banco de dados guarda datas: o dia do pedido, o dia da entrega, o aniversário do cliente, a hora do pagamento. A Loja Aurora tem 90 pedidos, de janeiro de 2024 a outubro de 2026, e a Ana precisa responder perguntas como "quantos pedidos tivemos em 2025?" e "o que foi pago no dia 14?". Nesta aula você vai entender como o SQLite guarda datas e horas (ele não tem um tipo de data próprio!), por que o formato AAAA-MM-DD é o único que funciona bem, como filtrar por período sem cair na armadilha do BETWEEN, e como pegar a data de hoje.
- Que o SQLite não tem tipo
DATE: as datas são texto (ou número), e o formato ISO 8601 (2025-03-14) é o combinado. - Por que
AAAA-MM-DDordena e compara certo, eDD/MM/AAAAnão. - Filtrar por ano, por mês e por período com
>=,<,BETWEENeLIKE. - Data com hora (
2026-10-14 16:45:10) e a armadilha doBETWEENcom elas. - Os três jeitos de guardar o mesmo instante: texto, dia juliano e tempo Unix.
- A data e a hora de agora:
date('now'),CURRENT_DATE,CURRENT_TIMESTAMP, e por que elas vêm em UTC. - Como impedir que uma data impossível (
2024-02-30,30/01/2024) entre na tabela.
Os exemplos rodam de verdade no seu navegador, num SQLite com o banco da Loja Aurora, e cada exemplo parte do banco limpo. As sessões de terminal saíram do sqlite3 3.50.4 no computador fictício da Ana. As funções de data (date, strftime, somar dias, descobrir o dia da semana…) têm aula própria, logo depois desta: Funções de Data.
A ideia: escrever a data de um jeito que ordena
Pense numa pasta de fotos no computador. Se cada arquivo se chama 05-01-2024.jpg, 14-01-2024.jpg, 27-12-2023.jpg, o computador põe em ordem pelo dia (05, 14, 27), misturando meses e anos. Quem já sofreu com isso passou a nomear as fotos assim: 2023-12-27.jpg, 2024-01-05.jpg, 2024-01-14.jpg. Com o ano primeiro, depois o mês, depois o dia, sempre com dois dígitos, a ordem alfabética dos nomes é a mesma ordem do calendário.
O SQLite usa exatamente esse truque. Ele não tem um tipo especial para datas (veja Os Tipos no SQLite): uma data é um texto comum, como '2025-03-14'. Esse formato, ano-mês-dia com hífens, é um padrão internacional, o ISO 8601. Todas as funções de data do SQLite entendem esse formato, e, como o ano vem primeiro, ordenar e comparar o texto dá o mesmo que ordenar e comparar as datas.
| Parte | Formato | Exemplo |
|---|---|---|
| Data | AAAA-MM-DD (ano com 4 dígitos, mês e dia com 2) | 2025-03-14 |
| Hora | HH:MM:SS (0 a 23 horas) | 16:45:10 |
| Data e hora | AAAA-MM-DD HH:MM:SS (um espaço no meio; um T também vale) | 2026-10-14 16:45:10 |
1. As datas da Loja Aurora
A tabela pedidos tem duas colunas de data: data (o dia do pedido) e entregue_em (o dia da entrega, ou NULL se ainda não chegou). A função typeof ("tipo de") mostra como cada valor está guardado:
SELECT id, data, entregue_em,
typeof(data) AS tipo_data,
typeof(entregue_em) AS tipo_entrega
FROM pedidos
WHERE id IN (1, 2, 86);
- data
- O dia do pedido, como texto ISO:
2024-01-05é 5 de janeiro de 2024. - entregue_em
- O dia da entrega. O pedido 86 ainda não foi entregue: NULL (veja O Valor NULL).
- typeof(data)
text: a data é um texto. Não existe "tipo data" no SQLite.- typeof(entregue_em)
nullno pedido 86: é a ausência de valor, não uma data.
Na tabela clientes, a coluna nascimento usa o mesmo formato. Dois clientes (9 e 21) estão sem data de nascimento.
2. Ordenar e comparar: por que ano-mês-dia
Com as datas em ISO, o ORDER BY (aula ORDER BY) põe os clientes do mais velho para o mais novo sem nenhum esforço:
SELECT nome, nascimento FROM clientes WHERE nascimento IS NOT NULL ORDER BY nascimento LIMIT 5;
Agora veja o que acontece quando alguém guarda as datas do jeito brasileiro, DD/MM/AAAA. A Ana fez uma tabelinha de aniversários da equipe:
CREATE TABLE aniversarios (nome TEXT, dia TEXT);
INSERT INTO aniversarios VALUES
('Ana', '05/01/2024'),
('Caio', '14/01/2024'),
('Renata', '27/12/2023'),
('Pedro', '03/02/2024');
SELECT * FROM aniversarios ORDER BY dia;
A ordem saiu errada: Pedro (fevereiro de 2024) veio primeiro e Renata (dezembro de 2023) ficou por último. O SQLite não sabe que aquilo é uma data; ele ordenou o texto, letra por letra, e comparou primeiro os dias: 03, 05, 14, 27. Com comparações, o estrago é o mesmo: WHERE dia > '01/01/2024' traria a Renata, de 2023.
Grave sempre AAAA-MM-DD no banco. Na hora de mostrar para o cliente, aí sim converta para 14/03/2025, com strftime('%d/%m/%Y', data) (aula Funções de Data). Banco é para guardar certo; a tela é para mostrar bonito.
3. Filtrar por período
Como data ISO compara certo, filtrar por período é usar os operadores que você já conhece (aula Comparações) com texto entre aspas simples.
Um ano inteiro
SELECT COUNT(*) AS pedidos_2025 FROM pedidos WHERE data >= '2025-01-01' AND data < '2026-01-01';
- data >= '2025-01-01'
- Do primeiro dia de 2025 em diante (incluindo ele).
- AND
- As duas condições ao mesmo tempo (aula AND).
- data < '2026-01-01'
- Antes do primeiro dia de 2026 (sem incluí-lo).
Foram 32 pedidos em 2025. Esse jeito, "maior ou igual ao início e menor que o início do período seguinte", é o mais seguro de todos: funciona igual para datas com e sem hora, e você nunca precisa saber se o mês acaba no dia 28, 30 ou 31.
Com BETWEEN
O BETWEEN ("entre", aula BETWEEN) inclui as duas pontas. Para datas sem hora, como as da loja, ele funciona bem:
SELECT COUNT(*) AS pedidos_2025 FROM pedidos WHERE data BETWEEN '2025-01-01' AND '2025-12-31';
Os mesmos 32. Mas guarde a palavra "sem hora": na seção 4 você vai ver o BETWEEN errar.
Um mês com LIKE
Como a data é texto, dá para usar o LIKE (aula LIKE): todo dia de março de 2025 começa com 2025-03-.
SELECT id, data FROM pedidos WHERE data LIKE '2025-03-%';
Funciona, e é fácil de ler. A desvantagem é que o LIKE trata a data só como texto; com >= e < o banco consegue usar um índice na coluna de data (aula Índices), e o LIKE, em geral, não.
Experimente: a Ana quer os pedidos de dezembro de 2025. A consulta tem só o começo do período, e trouxe dezembro de 2025 e tudo o que veio depois. Acrescente o fim do período.
SELECT id, data FROM pedidos WHERE data >= '2025-12-01';
SELECT id, data FROM pedidos WHERE data >= '2025-12-01' AND data < '2026-01-01';
4. Data com hora e a armadilha do BETWEEN
Quando a hora importa, ela vem depois da data, separada por um espaço: '2026-10-14 16:45:10'. A Ana anotou os pagamentos dos últimos pedidos numa tabela nova, com a hora exata de cada um:
CREATE TABLE pagamentos (pedido_id INTEGER, pago_em TEXT); INSERT INTO pagamentos VALUES (88, '2026-10-05 09:12:40'), (89, '2026-10-09 18:03:05'), (90, '2026-10-14 08:30:00'), (87, '2026-10-14 16:45:10'), (86, '2026-10-15 00:00:00'); SELECT * FROM pagamentos ORDER BY pago_em;
Ordenou certo, de novo: o formato ISO com hora também ordena como texto. Agora a pergunta: "o que foi pago no dia 14?". A primeira ideia de muita gente:
CREATE TABLE pagamentos (pedido_id INTEGER, pago_em TEXT); INSERT INTO pagamentos VALUES (88, '2026-10-05 09:12:40'), (89, '2026-10-09 18:03:05'), (90, '2026-10-14 08:30:00'), (87, '2026-10-14 16:45:10'), (86, '2026-10-15 00:00:00'); SELECT * FROM pagamentos WHERE pago_em BETWEEN '2026-10-14' AND '2026-10-14';
Zero linhas, e houve dois pagamentos no dia 14! Por quê? Para o SQLite, '2026-10-14' é só um texto, e quer dizer "dia 14 à meia-noite em ponto". O texto '2026-10-14 08:30:00' é maior que '2026-10-14' (é mais comprido e começa igual), então está fora do intervalo. A tentativa seguinte também erra:
| Filtro | O que vem | Certo? |
|---|---|---|
BETWEEN '2026-10-14' AND '2026-10-14' | Nada | Não |
BETWEEN '2026-10-14' AND '2026-10-15' | Os dois do dia 14 | Por sorte. O pagamento '2026-10-15 00:00:00' ficou de fora porque é maior que '2026-10-15'; mas um pagamento gravado só como '2026-10-15' entraria, e ele é do dia 15 |
pago_em >= '2026-10-14' AND pago_em < '2026-10-15' | Só os dois do dia 14 | Sim |
date(pago_em) = '2026-10-14' | Só os dois do dia 14 | Sim (mas não usa índice) |
pago_em LIKE '2026-10-14%' | Só os dois do dia 14 | Sim |
A date(pago_em) corta a hora e deixa só a data; ela é da próxima aula (Funções de Data). A regra que resolve tudo é a mesma da seção 3: maior ou igual ao começo, menor que o começo do dia seguinte.
Missão: conserte o filtro para trazer os dois pagamentos do dia 14 de outubro de 2026, e só eles.
CREATE TABLE pagamentos (pedido_id INTEGER, pago_em TEXT); INSERT INTO pagamentos VALUES (88, '2026-10-05 09:12:40'), (89, '2026-10-09 18:03:05'), (90, '2026-10-14 08:30:00'), (87, '2026-10-14 16:45:10'), (86, '2026-10-15 00:00:00'); SELECT * FROM pagamentos WHERE pago_em BETWEEN '2026-10-14' AND '2026-10-14';
CREATE TABLE pagamentos (pedido_id INTEGER, pago_em TEXT); INSERT INTO pagamentos VALUES (88, '2026-10-05 09:12:40'), (89, '2026-10-09 18:03:05'), (90, '2026-10-14 08:30:00'), (87, '2026-10-14 16:45:10'), (86, '2026-10-15 00:00:00'); SELECT * FROM pagamentos WHERE pago_em >= '2026-10-14' AND pago_em < '2026-10-15';
5. Três jeitos de guardar o mesmo instante
O texto ISO é o jeito mais comum, mas o SQLite aceita mais dois. Os três representam o mesmo dia, o do primeiro pedido da loja:
SELECT '2024-01-05' AS texto_iso,
julianday('2024-01-05') AS dia_juliano,
unixepoch('2024-01-05') AS tempo_unix;
| Formato | Tipo | O que é | Bom para |
|---|---|---|---|
| Texto ISO 8601 | TEXT | '2024-01-05' ou '2024-01-05 08:30:00' | Quase tudo: dá para ler a olho, ordena certo. É o recomendado e o que a Loja Aurora usa. |
| Dia juliano | REAL | Quantos dias se passaram desde o meio-dia de 24 de novembro de 4714 a.C. (um marco dos astrônomos). A parte depois do ponto é a fração do dia: o .5 quer dizer meia-noite. | Fazer contas: a diferença entre dois dias julianos é o número de dias entre as datas. |
| Tempo Unix | INTEGER | Quantos segundos se passaram desde 1º de janeiro de 1970, à meia-noite em UTC. | Trocar dados com programas: quase toda linguagem (PHP, Python, JavaScript) fala esse número. |
As funções de data convertem de um para o outro. A date() volta para o texto ISO; com tempo Unix, é preciso avisar com 'unixepoch', senão ela acharia que o número é um dia juliano:
SELECT date(2460314.5) AS do_juliano,
date(1704412800, 'unixepoch') AS do_unix,
datetime(1704412800, 'unixepoch') AS do_unix_com_hora;
Uma conta com dias julianos
Quantos dias cada pedido levou para ser entregue? Subtraindo os dias julianos das duas datas:
SELECT id, data, entregue_em,
julianday(entregue_em) - julianday(data) AS dias
FROM pedidos
WHERE id <= 3;
O pedido 1 levou 5 dias, de 5 a 10 de janeiro. Subtrair os textos direto (entregue_em - data) não funciona: o SQLite transforma cada texto em número aproveitando só o 2024 do começo, e a conta dá 0. Essa e as outras contas de data estão em Funções de Data.
6. A data e a hora de agora
Para saber o dia de hoje, o SQLite tem a função date('now') ("agora") e três palavras do SQL padrão: CURRENT_DATE ("data atual"), CURRENT_TIME ("hora atual") e CURRENT_TIMESTAMP ("data e hora atuais"). Elas dão uma resposta diferente a cada dia (e a cada segundo), então a sessão abaixo mostra o que a Ana viu numa manhã de outubro de 2026:
$ sqlite3 loja.db
SQLite version 3.50.4 2025-07-30 19:33:53
Enter ".help" for usage hints.
sqlite> SELECT date('now');
2026-10-18
sqlite> SELECT CURRENT_DATE, CURRENT_TIME;
2026-10-18|13:40:15
sqlite> SELECT CURRENT_TIMESTAMP;
2026-10-18 13:40:15 « 13h40 em UTC
sqlite> SELECT datetime('now', 'localtime');
2026-10-18 10:40:15 « 10h40 no relógio da Ana (horário de Brasília)
sqlite> .quit
Repare na diferença de 3 horas. O SQLite dá a hora de agora em UTC (o "tempo universal coordenado", a hora de Greenwich, a referência do mundo inteiro), e não na hora local. No horário de Brasília, o relógio está 3 horas atrás do UTC. Para a hora do relógio da parede, acrescente 'localtime' ("hora local"). Guardar em UTC é, na verdade, uma boa prática: um sistema com clientes em Fortaleza, Lisboa e Buenos Aires tem uma hora só como referência.
now nos exemplos
Uma consulta com date('now') dá uma resposta hoje e outra amanhã. Se esta aula dissesse "a consulta abaixo devolve 3 pedidos", a frase ficaria errada na semana que vem. Por isso os exemplos usam datas fixas dos pedidos da loja (como '2026-10-14', a data do último pedido). No editor do guia você pode rodar SELECT date('now'); à vontade: vai ver a data do seu computador, em UTC.
Gravar a hora automaticamente
O uso mais comum do CURRENT_TIMESTAMP é como valor padrão (DEFAULT, aula DEFAULT) de uma coluna "criado em": cada linha nova anota sozinha quando foi gravada.
$ sqlite3 loja.db
SQLite version 3.50.4 2025-07-30 19:33:53
Enter ".help" for usage hints.
sqlite> CREATE TABLE avisos (id INTEGER PRIMARY KEY, texto TEXT, criado_em TEXT DEFAULT CURRENT_TIMESTAMP);
sqlite> INSERT INTO avisos (texto) VALUES ('Chegou o estoque de cadernos');
sqlite> SELECT * FROM avisos;
1|Chegou o estoque de cadernos|2026-10-18 13:40:15
sqlite> DROP TABLE avisos;
sqlite> .quit
O INSERT não disse nada sobre criado_em, e a coluna recebeu a data e a hora do momento, em UTC. No editor, onde o resultado mudaria a cada segundo, dá para conferir só o formato:
CREATE TABLE avisos (
id INTEGER PRIMARY KEY,
texto TEXT,
criado_em TEXT DEFAULT CURRENT_TIMESTAMP
);
INSERT INTO avisos (texto) VALUES ('Chegou o estoque de cadernos');
SELECT texto, typeof(criado_em) AS tipo, length(criado_em) AS tamanho
FROM avisos;
Um texto de 19 caracteres: AAAA-MM-DD HH:MM:SS.
7. O SQLite aceita qualquer coisa: proteja a coluna
Como a data é só texto, o SQLite grava o que você mandar, sem reclamar. Até numa coluna declarada como DATE:
CREATE TABLE eventos (dia DATE);
INSERT INTO eventos VALUES ('2024-02-30'), ('ontem'), (20240105);
SELECT dia, typeof(dia) AS tipo FROM eventos;
Um 30 de fevereiro, a palavra "ontem" e um número: tudo entrou. O nome DATE no CREATE TABLE não faz o SQLite conferir nada (ele só influencia a "afinidade" da coluna, assunto de Os Tipos no SQLite). Quem confere é a função date(): ela devolve a data no formato ISO, ou NULL quando não entende o texto.
SELECT date('2024-02-29') AS bissexto,
date('2024-02-30') AS dia_30,
date('30/01/2024') AS formato_br,
date('2024-1-5') AS sem_zeros;
Três surpresas: '30/01/2024' e '2024-1-5' (sem os zeros) não são entendidos e viram NULL; e o '2024-02-30' não vira NULL, vira 2024-03-01: o SQLite "empurra" o dia que sobrou para o mês seguinte. O truque para validar é comparar o valor com a date() dele: só uma data correta e bem escrita continua igual. Use isso num CHECK (aula CHECK):
CREATE TABLE eventos (
dia TEXT CHECK (dia IS date(dia))
);
INSERT INTO eventos VALUES ('2024-02-29'); -- passa
INSERT INTO eventos VALUES ('2024-02-30'); -- é recusado
- CHECK (…)
- Uma regra que toda linha precisa cumprir.
- dia IS date(dia)
- O texto guardado tem de ser igual à data que a
date()entende.'2024-02-30'vira'2024-03-01': diferente, recusado.'30/01/2024'vira NULL: diferente, recusado. - IS
- Por que
ISe não=? Com=,'30/01/2024' = NULLdá NULL, e umCHECKque dá NULL deixa passar. OIScompara de verdade, até com NULL (aula IS NULL). Bônus: uma linha sem data (NULL) passa, porqueNULL IS NULLé verdadeiro; para proibir, junteNOT NULL.
O primeiro INSERT passou; o segundo parou com CHECK constraint failed: dia IS date(dia), "a restrição CHECK falhou".
8. Formas diferentes de filtrar um período
Todas estas trazem os pedidos de março de 2025 (os pedidos 38, 39 e 40):
| Forma | Exemplo | Prós e contras |
|---|---|---|
>= início AND < início do seguinte | data >= '2025-03-01' AND data < '2025-04-01' | A recomendada. Certa com ou sem hora, usa índice, não precisa saber o último dia do mês. |
BETWEEN | data BETWEEN '2025-03-01' AND '2025-03-31' | Fácil de ler. Certa só se a coluna não tiver hora. |
LIKE | data LIKE '2025-03-%' | Curta. Trata a data como texto; em geral, sem índice. |
| Função de data | strftime('%Y-%m', data) = '2025-03' | Muito flexível (dia da semana, trimestre…), mas calcula linha por linha, sem índice. Veja Funções de Data. |
Quando dá errado
Erros de data quase nunca dão mensagem de erro: a consulta roda e traz o resultado errado, ou nenhum. Por isso é preciso conhecer os casos.
SELECT COUNT(*) AS pedidos FROM pedidos WHERE data = '2024-1-5';
O que aconteceu: zero pedidos, e existe um pedido em 5 de janeiro de 2024 (o pedido 1). A coluna guarda '2024-01-05', e o texto '2024-1-5' é outro texto. Nenhum aviso.
Como consertar: sempre com zeros: '2024-01-05'.
SELECT COUNT(*) AS pedidos FROM pedidos WHERE data = '05/01/2024';
O que aconteceu: zero, de novo. E com > ou < é pior: o resultado vem, mas errado, porque o texto '05/01/2024' é comparado letra por letra com '2024-…'.
Como consertar: no SQL, escreva sempre a data como 'AAAA-MM-DD'.
SELECT COUNT(*) AS pedidos FROM pedidos WHERE data = 2024-01-05;
O que aconteceu: sem aspas, 2024-01-05 é uma conta: 2024 menos 1 menos 5, que dá 2018. A consulta procurou pedidos com data igual ao número 2018 e não achou nenhum. Sem erro, sem aviso.
Como consertar: data é texto, e texto vai entre aspas simples: '2024-01-05'.
SELECT COUNT(*) AS pedidos FROM pedidos WHERE data = "2024-01-05";
O que aconteceu: no such column: "2024-01-05" - should this be a string literal in single-quotes?: "não existe a coluna "2024-01-05"; isto deveria ser um texto entre aspas simples?". No SQL, aspas duplas são para nomes de colunas e tabelas; texto, inclusive datas, vai entre aspas simples.
Como consertar: WHERE data = '2024-01-05'.
BETWEEN numa coluna com hora
Você já viu na seção 4: pago_em BETWEEN '2026-10-14' AND '2026-10-14' não traz nada, porque '2026-10-14 08:30:00' é maior que '2026-10-14'. Como consertar: pago_em >= '2026-10-14' AND pago_em < '2026-10-15'.
CURRENT_TIMESTAMP e datetime('now') vêm em UTC, 3 horas à frente do horário de Brasília. Um relatório "pedidos de hoje" rodado às 22h em Teresina já estaria no dia seguinte em UTC. Como consertar: guarde em UTC e, para mostrar ou comparar com a hora local, use datetime('now', 'localtime') (seção 6).
MySQL, PostgreSQL e SQL Server têm tipos de data de verdade, e conferem o valor na hora de gravar. A data é escrita do mesmo jeito, como texto ISO entre aspas simples ('2025-03-14'), mas o banco a transforma num valor de data.
| Banco | Tipos | Agora |
|---|---|---|
| SQLite | Nenhum: TEXT (ISO), REAL ou INTEGER | CURRENT_TIMESTAMP, datetime('now') (UTC) |
| PostgreSQL | DATE, TIME, TIMESTAMP, TIMESTAMP WITH TIME ZONE, INTERVAL | CURRENT_DATE, CURRENT_TIMESTAMP, now() |
| MySQL | DATE, TIME, DATETIME, TIMESTAMP, YEAR | CURRENT_DATE, CURRENT_TIMESTAMP, NOW() |
| SQL Server | date, time, datetime, datetime2, datetimeoffset | CURRENT_TIMESTAMP, GETDATE(), SYSDATETIME() |
Numa coluna DATE do PostgreSQL ou do SQL Server, um '2024-02-30' é recusado com erro. O MySQL também recusa no modo estrito (o modo que vem ligado de fábrica); se o modo estrito estiver desligado, ele grava a "data zero" 0000-00-00 com um aviso. No SQLite, a proteção é o CHECK da seção 7. Trecho ilustrativo, que não roda no SQLite:
-- PostgreSQL: a coluna é do tipo DATE de verdade CREATE TABLE pedidos (id INTEGER PRIMARY KEY, data DATE NOT NULL); SELECT data + 7 FROM pedidos; -- soma 7 dias direto na data
Referência rápida
| Escrita | O que é / o que faz |
|---|---|
'2025-03-14' | Uma data (texto ISO 8601: ano-mês-dia, com zeros) |
'2025-03-14 16:45:10' | Data e hora (24 horas) |
col >= '2025-03-01' AND col < '2025-04-01' | Um período (março de 2025), certo com ou sem hora |
col BETWEEN '2025-03-01' AND '2025-03-31' | Um período, só para colunas sem hora |
col LIKE '2025-03-%' | Um mês, comparando o texto |
julianday(data) | A data como dia juliano (REAL); diferença = dias |
unixepoch(data) | A data como tempo Unix (segundos desde 1970) |
date(numero) / date(numero, 'unixepoch') | Volta de juliano / de Unix para texto ISO |
date('now'), CURRENT_DATE | A data de hoje (UTC) |
CURRENT_TIME | A hora de agora (UTC) |
CURRENT_TIMESTAMP, datetime('now') | Data e hora de agora (UTC) |
datetime('now', 'localtime') | Data e hora de agora no fuso do computador |
DEFAULT CURRENT_TIMESTAMP | Coluna que anota sozinha quando a linha foi gravada |
CHECK (col IS date(col)) | Só aceita datas válidas no formato AAAA-MM-DD |
Exercícios
1. Escreva a data
Escreva o dia 7 de março de 2025 no formato que o SQLite entende (com as aspas):
2. Complete o período
Pedidos do ano de 2024 inteiro, do jeito recomendado:
3. Por que o SQLite consegue ordenar as datas da Loja Aurora com um simples ORDER BY data?
4. A coluna pago_em guarda data e hora. Quantas linhas WHERE pago_em BETWEEN '2026-10-14' AND '2026-10-14' traz para os pagamentos feitos às 08:30 e às 16:45 do dia 14?
5. A Ana rodou SELECT CURRENT_TIMESTAMP; às 10h da manhã em Teresina. Que hora apareceu?
6. O que date('2024-02-30') devolve no SQLite?
Missão final: os clientes dos anos 90
Missão: a loja vai fazer uma campanha para os clientes nascidos nos anos 90 (de 1º de janeiro de 1990 a 31 de dezembro de 1999). Mostre o nome e o nascimento deles, do mais velho para o mais novo.
SELECT nome, nascimento FROM clientes;
SELECT nome, nascimento FROM clientes WHERE nascimento >= '1990-01-01' AND nascimento < '2000-01-01' ORDER BY nascimento;
São 12 clientes, do Rafael Monteiro (maio de 1990) à Larissa Macêdo (janeiro de 1999). Os dois clientes sem data de nascimento ficaram de fora sozinhos: NULL >= '1990-01-01' não é verdadeiro.
Resumo
- O SQLite não tem tipo de data. O combinado é guardar texto no formato ISO 8601:
'AAAA-MM-DD'ou'AAAA-MM-DD HH:MM:SS', sempre com zeros. - Com o ano primeiro, a ordem do texto é a ordem do calendário:
ORDER BY,<e>funcionam.DD/MM/AAAAordena e compara errado. - Para um período, use
col >= início AND col < início do próximo. OBETWEENsó é seguro em colunas sem hora. - O mesmo instante pode ser texto ISO, dia juliano (
julianday, bom para contas) ou tempo Unix (unixepoch, segundos desde 1970). date('now'),CURRENT_DATEeCURRENT_TIMESTAMPdão o momento atual em UTC;'localtime'dá a hora do relógio. Mudam a cada dia: nunca dependa delas para um resultado fixo.- O SQLite grava qualquer texto como data. Proteja a coluna com
CHECK (col IS date(col)).