IS NULL e IS NOT NULL
1. Entendendo o valor NULL no SQL
NULL em SQL representa a ausência de valor, não um valor em si. É fundamental compreender que NULL é diferente de zero (0), string vazia ('') ou qualquer outro valor. NULL significa que o dado é desconhecido, inexistente ou ainda não foi informado.
-- NULL não é igual a zero ou string vazia
SELECT NULL = 0; -- Resultado: NULL (desconhecido)
SELECT NULL = ''; -- Resultado: NULL (desconhecido)
SELECT NULL = NULL; -- Resultado: NULL (desconhecido)
Por definição, NULL não é igual a nada, nem mesmo a outro NULL. Isso ocorre porque o SQL utiliza lógica trivalente (verdadeiro, falso, desconhecido). Comparações com NULL sempre resultam em "desconhecido", nunca em verdadeiro ou falso.
Essa característica exige operadores especiais para verificar a presença ou ausência de NULL: IS NULL e IS NOT NULL. Os operadores comuns como = e <> simplesmente não funcionam com NULL.
2. Operador IS NULL: encontrando valores ausentes
O operador IS NULL retorna verdadeiro quando o valor da coluna é NULL. Sua sintaxe é direta:
SELECT coluna1, coluna2
FROM tabela
WHERE coluna IS NULL;
Exemplo prático 1: Encontrar clientes que não informaram telefone
SELECT id_cliente, nome, telefone
FROM clientes
WHERE telefone IS NULL;
Exemplo prático 2: Pedidos sem data de entrega registrada
SELECT id_pedido, data_pedido, data_entrega
FROM pedidos
WHERE data_entrega IS NULL;
Cuidado importante: Colunas que permitem NULL podem conter valores ausentes em qualquer registro. Sempre verifique se a coluna foi definida com a restrição NOT NULL antes de assumir que todos os registros possuem valor.
3. Operador IS NOT NULL: filtrando dados preenchidos
O operador IS NOT NULL retorna verdadeiro quando a coluna possui um valor definido (qualquer valor que não seja NULL).
SELECT coluna1, coluna2
FROM tabela
WHERE coluna IS NOT NULL;
Exemplo prático 1: Produtos com preço definido
SELECT id_produto, nome, preco
FROM produtos
WHERE preco IS NOT NULL;
Exemplo prático 2: Funcionários com e-mail cadastrado
SELECT id_funcionario, nome, email
FROM funcionarios
WHERE email IS NOT NULL;
Uso combinado com outras condições:
SELECT nome, salario, data_admissao
FROM funcionarios
WHERE salario IS NOT NULL
AND data_admissao >= '2023-01-01';
4. NULL em expressões e funções agregadas
NULL em operações aritméticas propaga-se: qualquer operação envolvendo NULL resulta em NULL.
SELECT 10 + NULL; -- Resultado: NULL
SELECT NULL * 5; -- Resultado: NULL
SELECT 'Texto' || NULL; -- Resultado: NULL (em alguns SGBDs)
Funções agregadas e NULL:
-- Tabela exemplo: vendas
-- (100, 200, NULL, 150, NULL)
SELECT COUNT(*) FROM vendas; -- 5 (conta todas as linhas)
SELECT COUNT(valor) FROM vendas; -- 3 (ignora NULL)
SELECT SUM(valor) FROM vendas; -- 450 (ignora NULL)
SELECT AVG(valor) FROM vendas; -- 150 (soma 450 / 3 registros não nulos)
Tratando NULL com COALESCE:
SELECT COALESCE(valor, 0) + 10 AS valor_ajustado
FROM vendas;
-- Se valor for NULL, usa 0; caso contrário, usa o valor original
5. Diferença entre IS NULL e outras comparações
A principal confusão entre iniciantes é usar = NULL ou <> NULL em vez de IS NULL ou IS NOT NULL.
-- ERRADO: sempre retorna vazio (ou nenhuma linha)
SELECT * FROM clientes WHERE telefone = NULL;
-- CORRETO: retorna clientes sem telefone
SELECT * FROM clientes WHERE telefone IS NULL;
-- ERRADO: sempre retorna vazio
SELECT * FROM clientes WHERE telefone <> NULL;
-- CORRETO: retorna clientes com telefone
SELECT * FROM clientes WHERE telefone IS NOT NULL;
Comparação com string vazia e zero:
-- NULL vs string vazia
SELECT * FROM clientes WHERE nome = ''; -- Encontra string vazia, não NULL
SELECT * FROM clientes WHERE nome IS NULL; -- Encontra NULL, não string vazia
-- NULL vs zero
SELECT * FROM produtos WHERE preco = 0; -- Encontra preço zero, não NULL
SELECT * FROM produtos WHERE preco IS NULL; -- Encontra preço ausente, não zero
6. NULL em junções (JOINs) e subconsultas
Comportamento em JOINs:
-- INNER JOIN: linhas com NULL na chave de junção são excluídas
SELECT c.nome, p.id_pedido
FROM clientes c
INNER JOIN pedidos p ON c.id_cliente = p.id_cliente;
-- Clientes sem pedidos (id_cliente NULL em pedidos) não aparecem
-- LEFT JOIN: linhas com NULL na tabela da direita são preservadas
SELECT c.nome, p.id_pedido
FROM clientes c
LEFT JOIN pedidos p ON c.id_cliente = p.id_cliente;
-- Clientes sem pedidos aparecem com id_pedido = NULL
Armadilha do NOT IN com NULL:
-- Suponha: clientes (1, 2, 3) e pedidos (1, NULL)
-- Subconsulta retorna: (1, NULL)
-- ERRADO: NOT IN com NULL na subconsulta retorna vazio
SELECT * FROM clientes
WHERE id_cliente NOT IN (SELECT id_cliente FROM pedidos);
-- Resultado: nenhuma linha (devido ao NULL)
-- CORRETO: usar NOT EXISTS
SELECT * FROM clientes c
WHERE NOT EXISTS (
SELECT 1 FROM pedidos p
WHERE p.id_cliente = c.id_cliente
);
7. Funções e expressões para lidar com NULL
COALESCE: Retorna o primeiro valor não nulo da lista.
SELECT COALESCE(telefone, celular, 'Sem contato') AS contato
FROM clientes;
NULLIF: Retorna NULL se dois valores forem iguais.
SELECT NULLIF(quantidade, 0) AS quantidade_ajustada
FROM itens_venda;
-- Se quantidade for 0, retorna NULL; caso contrário, retorna o valor
Funções específicas de SGBD:
-- SQL Server: ISNULL
SELECT ISNULL(telefone, 'Não informado') FROM clientes;
-- MySQL: IFNULL
SELECT IFNULL(telefone, 'Não informado') FROM clientes;
-- PostgreSQL: COALESCE (padrão ANSI)
SELECT COALESCE(telefone, 'Não informado') FROM clientes;
8. Boas práticas e desempenho com NULL
Indexação de colunas com NULL:
-- PostgreSQL: índice parcial para filtrar NULLs
CREATE INDEX idx_clientes_telefone_notnull
ON clientes (telefone)
WHERE telefone IS NOT NULL;
-- SQL Server: índice filtrado
CREATE INDEX idx_clientes_telefone_notnull
ON clientes (telefone)
WHERE telefone IS NOT NULL;
Modelagem de dados:
- Permitir NULL quando: o valor é opcional ou ainda não conhecido (ex: data de entrega futura)
- Evitar NULL quando: o valor é obrigatório para a lógica de negócio (ex: CPF do cliente)
- Valores sentinela: usar valores especiais (ex:
'1900-01-01'para data desconhecida) geralmente é pior que NULL, pois pode gerar confusão em relatórios
Chaves estrangeiras e NULL:
-- Evitar NULL em chaves estrangeiras quando possível
CREATE TABLE pedidos (
id_pedido INT PRIMARY KEY,
id_cliente INT NOT NULL, -- Evitar NULL aqui
FOREIGN KEY (id_cliente) REFERENCES clientes(id_cliente)
);
NULL em chaves estrangeiras pode indicar que o relacionamento é opcional, mas compromete a integridade referencial.
Referências
- Documentação PostgreSQL: NULL — Explicação oficial sobre NULL e operadores de comparação no PostgreSQL
- MySQL 8.0 Reference: Working with NULL — Guia completo sobre NULL no MySQL, incluindo funções IFNULL e COALESCE
- SQL Server: IS NULL / IS NOT NULL — Documentação oficial da Microsoft sobre os operadores IS NULL e IS NOT NULL
- SQLite: NULL Handling — Artigo técnico sobre como o SQLite trata valores NULL em comparações e junções
- Use The Index, Luke: NULL and Indexing — Guia prático sobre indexação de colunas que permitem NULL e otimização de consultas