Módulo 2: Tipos de verdade
boolean, numeric x divisão inteira, CAST/::, NULL, IS DISTINCT FROM
Antes de começar
O SQLite é frouxo com tipos: aceita ativo = 1, junta texto com número
sem reclamar. O Postgres é rígido, e isso é bom: erro de tipo vira
erro na hora, não dado torto que só aparece semanas depois.
boolean:ativoaqui étrue/false, não 0/1.WHERE ativojá basta (é "onde ativo é verdadeiro"). O contrário éWHERE NOT ativo. Também existeativo IS TRUE/IS FALSE/IS NOT TRUE(esse último pega inclusiveNULL).- Divisão inteira.
5 / 2dá2(dois inteiros → resultado inteiro). Pra ter2.5:5 / 2.0ou5::numeric / 2. Pega muita gente em cálculo de taxa/percentual. CAST(x AS tipo)oux::tipo: converte de propósito:'42'::int,preco::int,data_abertura::text.NULLnão é igual a nada, nem a outro NULL. Teste comIS NULL/IS NOT NULL.COALESCE(a, b)devolve o primeiro não-nulo.a IS DISTINCT FROM bcompara tratando NULL como um valor comum (útil pra "mudou?").
Olhar de QA: "esse campo devia ser numérico e veio texto" ou "somaram 0/1 num campo boolean" são bugs clássicos: no Postgres o próprio banco te avisa.
Dois exemplos
Teoria
WHERE ativo: coluna boolean já é a condição. Negativo:WHERE NOT ativo.coluna IS TRUE / IS FALSE / IS NOT TRUE: oIS NOT TRUEtambém casa comNULL.5 / 2= 2 (inteiro).5::numeric / 2= 2.5.ROUND(x::numeric, 2)arredonda.x::tipo=CAST(x AS tipo). Ex.:valor_total::int,'2025-01-01'::date.COALESCE(a, b, …): primeiro valor não-nulo.NULLIF(a, b): vira NULL sea = b.a IS DISTINCT FROM b: "são diferentes", contando NULL como valor.
Exemplos de aplicação
Um exemplo montado pra cada item da teoria acima. Não precisa rodar, é pra ver a cara do recurso e entender cada pedaço. Os valores são ilustrativos.
Coluna boolean como condição
SELECT nome, ativo
FROM produtos
WHERE ativo; -- só os à venda
-- inativos:
-- WHERE NOT ativo;
ativo já é true/false, então WHERE ativo basta, não precisa de = 1 nem = TRUE. Pra negar, WHERE NOT ativo. No SQLite isso era ativo = 1; no Postgres é boolean de verdade.
IS TRUE / IS FALSE / IS NOT TRUE
SELECT nome, ativo
FROM produtos
WHERE ativo IS NOT TRUE;
IS NOT TRUE pega tanto false quanto NULL, diferente de WHERE NOT ativo, que deixa o NULL de fora. Use quando "não é verdade" precisa incluir os sem valor.
Divisão inteira vs decimal
SELECT
5 / 2 AS inteiro, -- 2
5::numeric / 2 AS decimal, -- 2.5000000000000000
ROUND(5::numeric / 2, 2) AS arredondado -- 2.50
FROM produtos
LIMIT 1;
Dois inteiros divididos dão inteiro (o Postgres corta a parte fracionária). Convertendo um lado pra numeric, a divisão passa a ter casas. ROUND(x, 2) ajusta o número de casas.
x::tipo (cast)
SELECT
valor_total,
valor_total::int AS sem_centavos,
'2025-01-01'::date AS virou_data
FROM pedidos
LIMIT 5;
x::tipo é a forma curta de CAST(x AS tipo): converte o valor. valor_total::int descarta os centavos; '2025-01-01'::date transforma o texto em data de verdade (aí dá pra fazer conta com ela).
COALESCE / NULLIF
SELECT
id,
COALESCE(data_fechamento::text, 'aberto') AS situacao,
NULLIF(severidade, 'baixa') AS severidade_relevante
FROM defeitos;
COALESCE(a, b) devolve o primeiro não-nulo. NULLIF(a, b) faz o contrário: devolve NULL quando a = b (aqui, some com o 'baixa'), senão devolve a.
a IS DISTINCT FROM b
SELECT id, status, reportado_por
FROM defeitos
WHERE reportado_por IS DISTINCT FROM 'ezequiel';
É o "<> que trata NULL como valor". reportado_por <> 'ezequiel' deixa linhas com NULL de fora; IS DISTINCT FROM inclui essas linhas (NULL é "distinto de" qualquer texto).
Pegadinhas deste módulo
Os erros que quase todo mundo comete aqui. Ler agora poupa meia hora de confusão depois, e alguns deles são a causa de relatório errado em projeto real.
NULLnão é igual a nada, nem a outroNULL.WHERE data_fechamento = NULLdevolve zero linhas sempre, mesmo havendo milhares com o campo vazio. O certo éIS NULL. Não dá erro: dá resultado vazio, que é pior.<>descarta as linhas comNULLem silêncio.WHERE status <> 'fechado'não traz as linhas cujo status éNULL, porqueNULL <> 'fechado'não é verdadeiro, é desconhecido. Se você quer essas linhas, precisa deOR status IS NULL. Esta é uma das maiores fontes de relatório com número errado.- Qualquer conta com
NULLviraNULL.valor_total + fretesome se o frete for nulo. UseCOALESCE(frete, 0)quando o vazio deve valer zero. NULL, string vazia e zero são três coisas diferentes.NULL= nunca preenchido;''= preenchido com nada;0= preenchido com zero. Tratar os três como "vazio" no teste é como defeito de importação de dados passa despercebido.CASEsemELSEdevolveNULL. Se nenhuma condição bater e não houverELSE, o resultado é nulo, e a soma daquela coluna some junto.
Prática
Escreva a query e clique Rodar (ou Ctrl+Enter).
carregando banco…