COALESCE e NULLIF: lidando com nulos

1. Introdução aos valores NULL no SQL

NULL em SQL não é zero, nem string vazia, nem qualquer outro valor. NULL representa a ausência de valor — um dado desconhecido, não informado ou inexistente. Essa distinção é crucial: enquanto zero é um valor numérico e '' é uma string vazia, NULL indica que simplesmente não há dado.

Os problemas causados por NULL são notórios:
- Em cálculos aritméticos, qualquer operação envolvendo NULL resulta em NULL
- Em agregações como AVG() ou SUM(), NULLs são ignorados, mas podem distorcer resultados
- Em junções (JOIN), colunas com NULL não correspondem a nada, nem mesmo a outro NULL
- Em cláusulas WHERE, coluna = NULL nunca é verdadeiro — deve-se usar IS NULL

Para lidar com esses desafios, o SQL oferece funções especializadas: COALESCE, NULLIF, NVL (Oracle) e ISNULL (SQL Server). Este artigo foca nas duas primeiras, que são padrão ANSI e funcionam na maioria dos bancos.

2. COALESCE: Sintaxe e Funcionamento Básico

A sintaxe do COALESCE é:

COALESCE(valor1, valor2, ..., valorN)

A função avalia os argumentos na ordem em que são fornecidos e retorna o primeiro valor não nulo. Se todos os argumentos forem NULL, o resultado é NULL.

Exemplo simples:

SELECT COALESCE(NULL, NULL, 'terceiro', 'quarto') AS resultado;
-- Resultado: 'terceiro'

Em uma tabela de clientes:

SELECT 
    nome,
    COALESCE(telefone, 'Não informado') AS telefone_contato
FROM clientes;

Aqui, clientes sem telefone cadastrado exibem "Não informado" em vez de NULL.

3. Casos de Uso Práticos com COALESCE

Preenchimento em relatórios:

SELECT 
    produto,
    COALESCE(descricao, 'Sem descrição') AS descricao,
    COALESCE(preco, 0.00) AS preco
FROM produtos;

Combinação de colunas alternativas:

SELECT 
    nome,
    COALESCE(telefone_celular, telefone_fixo, email, 'Sem contato') AS contato_principal
FROM funcionarios;

Isso cria uma hierarquia: usa celular se existir; senão, tenta fixo; depois email; por fim, um fallback.

Expressões aritméticas seguras:

SELECT 
    id_pedido,
    COALESCE(quantidade, 0) * COALESCE(preco_unitario, 0) AS valor_total
FROM itens_pedido;

Sem COALESCE, se qualquer coluna for NULL, o resultado de quantidade * preco_unitario seria NULL.

4. NULLIF: Sintaxe e Funcionamento Básico

A sintaxe do NULLIF é:

NULLIF(expressão1, expressão2)

A lógica é direta: se expressão1 for igual a expressão2, retorna NULL; caso contrário, retorna expressão1.

Exemplo simples:

SELECT NULLIF(10, 10) AS resultado1;   -- NULL
SELECT NULLIF(10, 20) AS resultado2;   -- 10

Prevenção de divisão por zero:

SELECT 
    produto,
    receita / NULLIF(quantidade, 0) AS preco_medio
FROM vendas;

Se quantidade for zero, NULLIF retorna NULL, e a divisão receita / NULL resulta em NULL — evitando o erro de divisão por zero.

5. Casos de Uso Práticos com NULLIF

Cálculos financeiros seguros:

SELECT 
    mes,
    SUM(receita) / NULLIF(COUNT(vendas), 0) AS receita_media_por_venda
FROM relatorio_mensal
GROUP BY mes;

Marcação de valores redundantes:

SELECT 
    nome,
    NULLIF(email_principal, email_secundario) AS email_diferente
FROM usuarios;

Se os dois emails forem idênticos, retorna NULL — indicando redundância.

Limpeza de dados sentinela:

UPDATE clientes
SET idade = NULLIF(idade, -1)
WHERE idade = -1;

Valores como -1 ou 9999 são frequentemente usados como "não informado" em sistemas legados. NULLIF os converte para NULL padronizado.

6. COALESCE e NULLIF Trabalhando Juntos

A combinação dessas funções permite lógica condicional robusta em uma única expressão.

Substituir zero por um padrão:

SELECT 
    produto,
    COALESCE(NULLIF(estoque, 0), 1) AS estoque_ajustado
FROM produtos;

Aqui, NULLIF(estoque, 0) transforma zero em NULL, e COALESCE substitui esse NULL por 1. O resultado: todos os estoques zero são tratados como 1.

Evitar valores indesejados em relatórios:

SELECT 
    funcionario,
    COALESCE(NULLIF(comissao, 0), NULLIF(bonus, 0), 0) AS remuneracao_variavel
FROM pagamentos;

Isso prioriza comissão, depois bônus, mas ignora valores zero (tratando-os como ausentes).

Padrão para substituir string vazia:

SELECT 
    cliente,
    COALESCE(NULLIF(observacao, ''), 'Sem observação') AS obs_formatada
FROM cadastro;

7. Comparação com Alternativas (NVL, ISNULL, CASE)

NVL (Oracle) vs COALESCE:

-- Oracle
NVL(coluna, 'padrão')   -- apenas 2 argumentos
COALESCE(coluna1, coluna2, coluna3, 'padrão')  -- N argumentos

NVL é limitado a dois argumentos. COALESCE é mais flexível e padrão ANSI.

ISNULL (SQL Server) vs COALESCE:

-- SQL Server
ISNULL(coluna, 0)   -- tipos devem ser compatíveis
COALESCE(coluna, 0) -- pode ter problemas de tipo com strings vs números

No SQL Server, ISNULL preserva o tipo do primeiro argumento, enquanto COALESCE tenta determinar o tipo de maior precedência entre todos os argumentos.

CASE WHEN para lógica complexa:

SELECT 
    CASE 
        WHEN coluna1 IS NOT NULL THEN coluna1
        WHEN coluna2 > 0 THEN coluna2
        ELSE 'padrão'
    END AS resultado;

Use CASE quando a lógica envolver condições que não são simplesmente "primeiro não nulo" ou "igualdade".

8. Boas Práticas e Armadilhas Comuns

Tipos de dados incompatíveis:

-- Problema: misturar string e número
SELECT COALESCE(idade, 'não informado') FROM pessoas;
-- Erro em muitos bancos: tipos incompatíveis

Solução: converter explicitamente ou usar valores padrão do mesmo tipo.

Performance em grandes volumes:

  • COALESCE é geralmente eficiente, mas avaliar muitos argumentos tem custo
  • ISNULL (SQL Server) pode ser ligeiramente mais rápido que COALESCE em cenários simples
  • CASE com múltiplas condições pode ser mais lento que COALESCE para a mesma lógica

Filtragem correta em WHERE:

-- Errado: não funciona com NULL
SELECT * FROM clientes WHERE email = NULL;

-- Correto
SELECT * FROM clientes WHERE email IS NULL;
SELECT * FROM clientes WHERE COALESCE(email, '') = '';

Uso em JOINs:

-- Cuidado: NULL nunca é igual a NULL
SELECT * FROM a JOIN b ON a.coluna = b.coluna;
-- Se ambas forem NULL, a linha não será incluída

-- Solução: tratar NULLs explicitamente
SELECT * FROM a JOIN b ON COALESCE(a.coluna, '') = COALESCE(b.coluna, '');

Dominar COALESCE e NULLIF é essencial para escrever SQL robusto e previsível. Essas funções transformam o tratamento de nulos de uma dor de cabeça em uma ferramenta elegante de expressividade e segurança.

Referências