FolioPierEstudos de TI

NULL: a ausência de valor

Nota 9 de 41 · 5 min de leitura
Nesta página
  1. O que é o NULL
  2. Comparações com NULL
  3. NULL e texto vazio
  4. Contagens, somas e contas
  5. Uma armadilha com NOT IN
  6. O NULL na ordenação

Uma consulta pode contar zero clientes sem e-mail quando existem vários, um filtro pode deixar vendas de fora sem motivo aparente, e uma conta pode resultar em vazio. Esses comportamentos costumam ter a mesma origem: o NULL, a marca que o banco usa para indicar que uma coluna não tem valor. O NULL segue regras próprias, diferentes das regras dos valores comuns.

O que é o NULL

O NULL indica que a coluna não tem valor naquela linha. O NULL não é o número zero, nem um texto vazio, nem um espaço. No cenário, a tabela vendas tem dois exemplos:

  • a coluna cliente_id fica em NULL quando o consumidor não se identifica na compra;
  • a coluna desconto fica em NULL quando a venda não tem desconto.

A definição da tabela informa se cada coluna aceita o NULL. Uma coluna definida como NOT NULL exige um valor em todas as linhas. O comando SHOW COLUMNS FROM vendas; mostra essa informação na coluna Null.

Comparações com NULL

Uma comparação com NULL não resulta em verdadeiro nem em falso, e sim em desconhecido, porque não é possível saber se um valor ausente é igual ou diferente de outro. O filtro de uma consulta só mantém as linhas em que a condição é verdadeira, e por isso as linhas com resultado desconhecido ficam de fora. Para testar a ausência de valor, o SQL tem operadores próprios:

  • SELECT * FROM clientes WHERE email IS NULL;: encontra os clientes sem e-mail;
  • SELECT * FROM clientes WHERE email IS NOT NULL;: encontra os clientes com algum e-mail;
  • SELECT * FROM clientes WHERE email = NULL;: não encontra nenhuma linha, porque a comparação com o sinal de igual nunca é verdadeira quando envolve NULL.

O mesmo vale para a comparação de diferença. Na tabela vendas, a coluna situacao guarda a letra F para as vendas finalizadas e a letra C para as canceladas. Se algumas linhas antigas têm essa coluna em NULL, a condição a seguir as deixa de fora:

  • SELECT * FROM vendas WHERE situacao <> 'C';: traz as vendas com situação diferente de C, mas não traz as vendas com a situação em NULL.

Para incluir essas linhas, a condição precisa citá-las:

  • SELECT * FROM vendas WHERE situacao <> 'C' OR situacao IS NULL;

NULL e texto vazio

Um texto vazio, escrito como duas aspas simples sem nada entre elas, é um valor. Um NULL é a ausência de valor. Uma mesma coluna pode ter os dois casos, dependendo de como cada tela grava os dados. Para encontrar todos os clientes sem e-mail, a consulta precisa considerar as duas formas:

  • SELECT * FROM clientes WHERE email IS NULL OR email = '';

Contagens, somas e contas

As funções que resumem dados tratam o NULL de formas diferentes:

  • COUNT(*) conta as linhas, com ou sem NULL;
  • COUNT(desconto) conta apenas as linhas em que a coluna tem valor;
  • SUM(desconto) e AVG(desconto) ignoram as linhas em NULL, e a média é calculada apenas sobre as linhas com valor.

Por isso, em uma tabela com 100 vendas, das quais 30 têm desconto, COUNT(*) resulta em 100, e COUNT(desconto) resulta em 30.

Em uma conta, qualquer operação com NULL resulta em NULL. A expressão total - desconto resulta em NULL nas vendas sem desconto. A função COALESCE troca o NULL por um valor escolhido:

  • SELECT total - COALESCE(desconto, 0) FROM vendas;: usa zero no lugar do desconto ausente.

A função CONCAT, que une textos, segue a mesma regra. O resultado dessa função é NULL quando uma das partes é NULL, e a ferramenta mostra NULL no lugar do texto esperado.

Uma armadilha com NOT IN

A condição NOT IN compara um valor com uma lista. Quando a lista contém um NULL, a condição nunca resulta em verdadeiro, e a consulta não devolve nenhuma linha. Um exemplo é a busca pelos clientes que nunca compraram:

  • SELECT * FROM clientes WHERE id NOT IN (SELECT cliente_id FROM vendas);: não devolve nenhuma linha se alguma venda tiver cliente_id em NULL;
  • SELECT * FROM clientes WHERE id NOT IN (SELECT cliente_id FROM vendas WHERE cliente_id IS NOT NULL);: retira o NULL da lista e devolve os clientes sem compras.

O NULL na ordenação

Na ordem crescente, o MySQL coloca as linhas com NULL antes de todas as outras. Na ordem decrescente, essas linhas vão para o fim. Uma lista de clientes ordenada por e-mail começa, portanto, pelos clientes sem e-mail.

No suporte

Quando uma contagem ou um filtro deixa linhas de fora sem explicação, convém verificar se a coluna tem valores NULL. A consulta SELECT COUNT(*) FROM vendas WHERE situacao IS NULL mostra quantas linhas estão nessa situação, e o resultado indica se a condição precisa tratar o NULL.

Para guardar

  • O NULL indica a ausência de valor e não é zero nem texto vazio.
  • Comparações com NULL resultam em desconhecido, e o filtro descarta essas linhas.
  • IS NULL e IS NOT NULL são as formas de testar a ausência de valor.
  • COUNT(*) conta as linhas, e COUNT(coluna) conta apenas os valores presentes.
  • Contas com NULL resultam em NULL, e COALESCE troca o NULL por um valor.
  • Um NULL na lista do NOT IN faz a consulta não devolver nenhuma linha.
A consulta SELECT COUNT(*) FROM clientes WHERE email = NULL resulta em zero, mas existem clientes sem e-mail. Por quê?

Porque a comparação com o sinal de igual nunca é verdadeira quando envolve NULL, e as linhas ficam de fora do filtro. A condição correta é email IS NULL. Se o sistema também grava e-mails vazios, a condição precisa incluir email = ''.

A consulta com a condição situacao <> 'C' deveria trazer todas as vendas não canceladas, mas deixa algumas de fora. Qual é a explicação provável?

As vendas que estão com a coluna situacao em NULL. A comparação de NULL com qualquer valor resulta em desconhecido, e a linha não entra no resultado. Se essas vendas devem aparecer, a condição precisa acrescentar OR situacao IS NULL.

Publicado a partir do Obsidian · FolioPier