Lógica de três valores e UNKNOWN
Entenda por que NULL = NULL não é verdadeiro e como UNKNOWN se propaga pelas condições.
Lógica de três valores e UNKNOWN é uma aula grátis de SQL Interview Prep no CoddyKit. Esta é a aula 1 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de SQL Interview Prep, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de SQL Interview Prep inclui 4 aulas no total.
Por que NULL leva candidatos a respostas erradas
NULL é a principal fonte de respostas erradas em entrevistas de SQL. A armadilha é tratá-lo como um valor normal, quando, na realidade, NULL significa “desconhecido” ou “ausente”, não zero nem uma cadeia de caracteres vazia.
Os entrevistadores gostam disso porque a sintaxe parece correta, mas o resultado está silenciosamente errado. Eles podem mostrar um filtro que “deveria” retornar uma linha e perguntar por que ele não retorna nada.
Nesta lição, você construirá o modelo mental que esclarece qualquer pergunta sobre NULL: a lógica de três valores. Depois que você entender que as comparações podem retornar TRUE, FALSE ou UNKNOWN, o restante se encaixa.
NULL não é um valor
A frase mais importante para dizer em uma entrevista: NULL é a ausência de um valor, não um valor em si.
Isso significa que você não pode compará-lo usando = da mesma forma que compara números. O banco de dados não sabe se dois valores desconhecidos são iguais, portanto não pode afirmar que o resultado é TRUE ou FALSE.
NULL = 5não é FALSE, mas UNKNOWNNULL = NULLnão é TRUE, mas UNKNOWNNULL <> NULLtambém é UNKNOWN
É por isso que um filtro ingênuo de igualdade em uma coluna que aceita NULL elimina linhas silenciosamente.
Lógica de dois valores versus lógica de três valores
A maioria das linguagens de programação usa a lógica de dois valores: uma expressão é TRUE ou FALSE. SQL acrescenta um terceiro resultado, UNKNOWN, sempre que NULL participa de uma comparação.
Assim, qualquer predicado em SQL pode ser avaliado como um de três resultados: TRUE, FALSE ou UNKNOWN. A cláusula WHERE mantém uma linha somente quando seu predicado é exatamente TRUE. UNKNOWN se comporta como FALSE na filtragem, mas, do ponto de vista lógico, não é a mesma coisa.
Os entrevistadores verificam se você conhece essa distinção, porque UNKNOWN se comporta de modo diferente sob NOT do que FALSE.
Um filtro que elimina linhas silenciosamente
Este é o exemplo clássico resolvido. Suponha que bonus às vezes seja NULL. Um recrutador pergunta: “Esta consulta deveria retornar todos os funcionários cuja bonificação não é 1000. Por que ela ignora os funcionários sem bonificação?”
Para uma linha em que bonus é NULL, bonus <> 1000 é avaliado como UNKNOWN, não como TRUE. WHERE mantém apenas as linhas cujo resultado é TRUE, então esses funcionários desaparecem.
A correção é lidar explicitamente com NULL, algo que abordaremos na próxima lição. Por enquanto, reconheça que as linhas ausentes são uma consequência lógica, não um erro.
SELECT name, bonus
FROM employees
WHERE bonus <> 1000;
-- Rows where bonus IS NULL are excluded:
-- NULL <> 1000 evaluates to UNKNOWN, not TRUENULL em expressões AND
A lógica de três valores muda o comportamento de AND. Memorize a regra e você poderá responder imediatamente a qualquer pergunta sobre tabelas-verdade.
- TRUE AND UNKNOWN = UNKNOWN
- FALSE AND UNKNOWN = FALSE
- UNKNOWN AND UNKNOWN = UNKNOWN
A intuição é a seguinte: AND precisa de apenas um FALSE para ser definitivamente FALSE. Portanto, FALSE AND qualquer coisa continua sendo FALSE. Mas TRUE AND algo desconhecido continua desconhecido, porque o lado desconhecido pode acabar assumindo qualquer um dos resultados.
-- If status = 'active' is TRUE but bonus = 100 is UNKNOWN:
SELECT *
FROM employees
WHERE status = 'active' AND bonus = 100;
-- Combined result is UNKNOWN, so the row is NOT returnedNULL em expressões OR
OR é o equivalente de AND. Basta um TRUE para que o resultado seja definitivamente TRUE, então TRUE elimina o efeito do desconhecido.
- TRUE OR UNKNOWN = TRUE
- FALSE OR UNKNOWN = UNKNOWN
- UNKNOWN OR UNKNOWN = UNKNOWN
Assim, uma linha ainda pode atender a uma condição OR quando um dos ramos é desconhecido, desde que outro ramo seja genuinamente TRUE. Esta é uma pergunta complementar frequente depois da questão sobre AND.
SELECT *
FROM employees
WHERE department = 'Sales' OR bonus = 100;
-- A Sales employee with NULL bonus:
-- TRUE OR UNKNOWN = TRUE, so the row IS returnedNOT inverte TRUE/FALSE, mas não UNKNOWN
Aqui está o ponto sutil que os entrevistadores deixam para o final. NOT transforma TRUE em FALSE e FALSE em TRUE, mas NOT UNKNOWN continua sendo UNKNOWN.
É por isso que você não pode simplesmente envolver uma condição que falhou em NOT para inverter o resultado. Se bonus = 1000 for UNKNOWN para uma linha com NULL, então NOT (bonus = 1000) também será UNKNOWN, e a linha continuará excluída.
A negação não recupera linhas NULL. Somente um teste explícito de IS NULL faz isso.
-- For a row where bonus IS NULL:
-- bonus = 1000 -> UNKNOWN
-- NOT (bonus = 1000) -> UNKNOWN (still excluded)
SELECT * FROM employees WHERE NOT (bonus = 1000);Exemplo resolvido: a armadilha de NOT IN
Este é um dos enigmas sobre NULL mais frequentes. NOT IN com uma lista que contém NULL não retorna linha alguma, surpreendendo os candidatos que esperam que o NULL seja simplesmente ignorado.
Nos bastidores, x NOT IN (1, 2, NULL) se expande para x <> 1 AND x <> 2 AND x <> NULL. Essa última comparação é UNKNOWN, e TRUE AND TRUE AND UNKNOWN se reduz a UNKNOWN, portanto nada atende ao critério.
A alternativa segura é NOT EXISTS, que não está sujeita a esse problema.
-- Returns ZERO rows if the subquery yields any NULL
SELECT name
FROM employees
WHERE manager_id NOT IN (SELECT manager_id FROM managers);
-- Each comparison against NULL becomes UNKNOWN,
-- and the AND-chain collapses to UNKNOWN for every row.Por que UNKNOWN se comporta como FALSE em WHERE
Uma pergunta complementar comum é: “Se UNKNOWN não é FALSE, por que a linha é eliminada da mesma forma que uma linha FALSE?”
A resposta é precisa: WHERE, ON e HAVING seguem uma regra de manter somente TRUE. Tanto FALSE quanto UNKNOWN falham nesse teste, portanto, para fins de filtragem, parecem idênticos.
A diferença só aparece com a negação e as restrições CHECK. Uma restrição CHECK aceita uma linha quando a condição é TRUE ou UNKNOWN, portanto um NULL pode passar por uma restrição CHECK que você imaginava que o bloquearia.
-- CHECK passes on TRUE or UNKNOWN, so NULL salary is allowed:
-- CONSTRAINT salary_positive CHECK (salary > 0)
-- INSERT ... salary = NULL -> NULL > 0 is UNKNOWN -> allowedExemplo mais aprofundado: COUNT e a lacuna da lógica de verdade
Relacione tudo a um enunciado realista de entrevista. “Temos 100 funcionários. SELECT COUNT(*) WHERE bonus = 100 retorna 30, e WHERE bonus <> 100 retorna 50. Onde estão os outros 20?”
Os 20 ausentes têm um bônus NULL. Nem = 100 nem <> 100 é TRUE para eles; ambos são UNKNOWN, então eles passam direto por ambos os filtros.
Dizer “os grupos não somam o total porque NULL não satisfaz nenhum dos predicados” é exatamente a resposta que os entrevistadores querem.
SELECT
COUNT(*) FILTER (WHERE bonus = 100) AS eq_100,
COUNT(*) FILTER (WHERE bonus <> 100) AS ne_100,
COUNT(*) FILTER (WHERE bonus IS NULL) AS null_bonus,
COUNT(*) AS total
FROM employees;Pontos para mencionar na entrevista
Quando a lógica de NULL surgir, mencione estes pontos para demonstrar domínio:
- NULL significa desconhecido; comparações com ele produzem UNKNOWN.
- SQL usa a lógica de três valores: TRUE, FALSE, UNKNOWN.
- WHERE, ON e HAVING mantêm somente TRUE linhas.
NOT UNKNOWNcontinua sendo UNKNOWN, portanto a negação não recupera linhas NULL.NOT INcom qualquer NULL não retorna linhas; prefiraNOT EXISTS.
Apresente primeiro o modelo e depois percorra a tabela-verdade. Essa ordem mostra que você entende o motivo, não apenas o truque.
Verificação rápida
Teste seu domínio da lógica de três valores.
Recapitulação
Agora você tem o modelo mental básico de NULL:
- NULL é desconhecido, não um valor; nunca o compare usando
=ou<>. - SQL usa três valores: os predicados retornam TRUE, FALSE ou UNKNOWN.
- As cláusulas de filtragem mantêm somente TRUE; as linhas UNKNOWN desaparecem como as linhas FALSE.
NOTinverte TRUE e FALSE, mas deixa UNKNOWN inalterado.- A armadilha de
NOT IN+ NULL retorna zero linhas; useNOT EXISTS.
A seguir: a maneira correta de testar NULL com IS NULL, IS NOT NULL e operadores de igualdade que tratam NULL com segurança.
Perguntas Frequentes
A aula “Lógica de três valores e UNKNOWN” é grátis?
Sim — o texto completo de “Lógica de três valores e UNKNOWN” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de SQL Interview Prep, atualize para CoddyKit PRO. O curso de SQL Interview Prep inclui 4 aulas no total.
O que vou aprender em “Lógica de três valores e UNKNOWN”?
Entenda por que NULL = NULL não é verdadeiro e como UNKNOWN se propaga pelas condições. Você pratica SQL Interview Prep com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.
Preciso ter experiência prévia para começar SQL Interview Prep?
Nenhuma experiência prévia é necessária. SQL Interview Prep no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 1 de 4.
Quanto tempo leva a aula “Lógica de três valores e UNKNOWN”?
A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.
Posso escrever e executar código nesta aula de SQL Interview Prep?
Sim. Cada aula de SQL Interview Prep inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.
Todas as aulas deste curso
- Lógica de três valores e UNKNOWN
- IS NULL, IS NOT NULL e igualdade segura para NULL
- COALESCE, NULLIF e ISNULL
- NULLs em agregações, junções e DISTINCT