Wiki SQL
NULL e a lógica de três valores
NULL não é zero nem texto vazio: é "desconhecido". Comparar com ele dá desconhecido, e o WHERE só deixa passar o verdadeiro.
Em SQL, uma condição pode dar verdadeiro, falso ou desconhecido (NULL). Qualquer comparação com NULL, inclusive NULL = NULL, dá desconhecido. O WHERE e o ON só deixam passar o que é verdadeiro.
SELECT NULL = NULL AS igual,
NULL <> 1 AS diferente,
NULL IS NULL AS e_nulo,
1 + NULL AS soma,
'a' || NULL AS concatena;Saída
igual | diferente | e_nulo | soma | concatena ----- | --------- | ------ | ---- | --------- NULL | NULL | 1 | NULL | NULL
IS NULL, nunca = NULL
SELECT
(SELECT COUNT(*) FROM clientes WHERE cidade = NULL) AS com_igual,
(SELECT COUNT(*) FROM clientes WHERE cidade IS NULL) AS com_is_null;Saída
com_igual | com_is_null --------- | ----------- 0 | 1
A armadilha do NOT IN
x NOT IN (a, b, NULL) é x <> a AND x <> b AND x <> NULL. O último termo é desconhecido, então o todo nunca é verdadeiro: a consulta volta vazia. Com NOT EXISTS isso não acontece.
SELECT
(SELECT COUNT(*) FROM clientes WHERE cidade NOT IN ('Recife', NULL)) AS not_in,
(SELECT COUNT(*) FROM clientes c
WHERE NOT EXISTS (SELECT 1 FROM (SELECT 'Recife' AS x UNION ALL SELECT NULL) l WHERE l.x = c.cidade)) AS not_exists;Saída
not_in | not_exists ------ | ---------- 0 | 5
O NOT EXISTS devolveu 5: os quatro clientes com cidade e a Elisa, cuja cidade é desconhecida. Decida se ela entra; o que não dá é a resposta mudar porque a lista ganhou um NULL.
AND e OR com desconhecido
FALSE AND NULLé falso (já se sabe a resposta);TRUE AND NULLé desconhecido.TRUE OR NULLé verdadeiro;FALSE OR NULLé desconhecido.NOT NULLcontinua desconhecido.
SELECT (1 = 0) AND NULL AS falso_e_nulo,
(1 = 1) OR NULL AS verdadeiro_ou_nulo,
(1 = 1) AND NULL AS verdadeiro_e_nulo;Saída
falso_e_nulo | verdadeiro_ou_nulo | verdadeiro_e_nulo ------------ | ------------------ | ----------------- 0 | 1 | NULL
(O SQLite mostra verdadeiro como 1 e falso como 0.)
COALESCE e a comparação que trata NULL como valor
COALESCE(a, b, …) devolve o primeiro que não é NULL. Para comparar tratando dois NULL como iguais, o padrão é IS NOT DISTINCT FROM; no SQLite, IS; no Spark, o operador <=>.
SELECT nome, COALESCE(cidade, '(sem cidade)') AS cidade,
cidade IS NULL AS desconhecida
FROM clientes
WHERE id IN (4, 5);Saída
nome | cidade | desconhecida ----- | ------------ | ------------ Diego | Curitiba | 0 Elisa | (sem cidade) | 1
- No
ORDER BY ... ASC, o SQLite e o Spark põemNULLprimeiro; o PostgreSQL, por último. EscrevaNULLS FIRSTouNULLS LASTquando a ordem importar. NULLem chave de JOIN nunca casa com nada, nem com outroNULL.
Fontes
Conhecimento compartilhado pela Genesis Innovation.