Entenda profundamente o que é NULL, como ele afeta filtros, comparações, agregações, ordenações e concatenação. Aprenda a tratar NULL corretamente no dia a dia.
Dominar a lógica tri-valorada (TRUE, FALSE, UNKNOWN) e aplicar corretamente IS NULL, IS NOT NULL, ISNULL e COALESCE, além de entender como NULL interage com COUNT/SUM/AVG, ORDER BY e CONCAT.
col = NULL nunca é TRUE — o resultado é desconhecido. Sempre use IS NULL / IS NOT NULL.NULL (conceito)O que é / Para que serve: Representa ausência ou desconhecimento de valor.
Sintaxe: —
Como funciona: NULL não é zero, nem string vazia, nem '0'. É um marcador especial. Qualquer comparação direta com NULL resulta em UNKNOWN.
Implicações & boas práticas: • Evite permitir NULL sem necessidade. • Prefira NOT NULL com DEFAULT quando fizer sentido.
-- Demonstração da lógica:
SELECT CASE WHEN NULL = NULL THEN 'igual' ELSE 'não é igual' END AS Comparacao; -- 'não é igual'
SELECT CASE WHEN NULL IS NULL THEN 'é nulo' ELSE 'não é nulo' END; -- 'é nulo'
NULL vs NOT NULL (na definição de coluna)O que é / Para que serve: Controlar se a coluna aceita ausência de valor.
Sintaxe: Coluna TIPO NULL | NOT NULL
Como funciona: Se a coluna for NOT NULL, cada INSERT precisa fornecer valor (ou vir de DEFAULT).
Implicações & boas práticas: • Reduza NULLs desnecessários com DEFAULT. • Em dados obrigatórios, use NOT NULL.
CREATE TABLE dbo.Contatos (
ContatoID INT IDENTITY PRIMARY KEY,
Email NVARCHAR(200) NOT NULL,
Telefone NVARCHAR(20) NULL
);
IS NULL / IS NOT NULLO que é / Para que serve: Testar nulidade explicitamente em filtros.
Sintaxe: col IS NULL | col IS NOT NULL
Como funciona: Retorna TRUE quando a coluna é (não) nula.
Implicações & boas práticas: • Jamais use = NULL ou <> NULL. • Use IS NULL/IS NOT NULL em WHERE e CASE.
SELECT * FROM dbo.Contatos WHERE Telefone IS NULL; -- correto
-- SELECT * FROM dbo.Contatos WHERE Telefone = NULL; -- incorreto
NULL e agregações (SUM, AVG, COUNT)O que é / Para que serve: Entender como as funções tratam NULL.
Sintaxe: SUM(col) | AVG(col) | COUNT(*) | COUNT(col)
Como funciona: SUM/AVG ignoram valores NULL; COUNT(col) ignora NULL; COUNT(*) conta linhas (incluindo as com NULL).
Implicações & boas práticas: • Para tratar NULL como 0 em somas/médias, use COALESCE(col,0).
SELECT
COUNT(*) AS Linhas,
COUNT(Telefone) AS TelefonesInformados, -- ignora NULL
SUM(COALESCE(Limite,0)) AS LimiteSomadoComZero
FROM dbo.Clientes;
ISNULL(expr, substituto)O que é / Para que serve: Substituir NULL por um valor padrão (dois argumentos).
Sintaxe: ISNULL(valor, substituto)
Como funciona: Se valor for NULL, retorna substituto, caso contrário retorna valor. O tipo de retorno segue o primeiro argumento.
Implicações & boas práticas: • Simples, mas tem 2 argumentos. • Tipo é do 1º argumento (atenção à precedência e truncamentos).
SELECT ISNULL(NULL, 0) AS Valor; -- 0
SELECT ISNULL(NULL, 'sem') AS Texto; -- 'sem'
-- Tipagem: ISNULL(CONVERT(VARCHAR(10),NULL),'abc') retorna VARCHAR(10)
COALESCE(a, b, c, ...)O que é / Para que serve: Retornar o primeiro argumento não NULL (padrão ANSI).
Sintaxe: COALESCE(a, b [, c ...])
Como funciona: Avalia da esquerda para a direita e retorna o primeiro valor não NULL; o tipo segue regras de precedência entre argumentos.
Implicações & boas práticas: • Aceita vários argumentos (mais flexível que ISNULL). • Padrão ANSI — portável entre SGBDs.
SELECT COALESCE(NULL, NULL, 'primeiro válido', 'outro') AS Resultado;
-- Diferença de tipo: COALESCE(1, 1.5) -> 1.5 (por precedência numérica)
Funções em filtros vs filtros por faixaO que é / Para que serve: Evitar aplicar função na coluna (quebra de índices) quando possível.
Sintaxe: WHERE YEAR(ColData)=2025 -- EVITE | WHERE ColData >= '2025-01-01' AND ColData < '2026-01-01' -- PREFIRA
Como funciona: Aplicar função na coluna pode impedir uso de índice. Use filtros por faixa (>= e <) para preservar index seek.
Implicações & boas práticas: • Técnica da faixa aberta também evita perda de registros por fração de segundo.
-- Ruim para índice (função na coluna)
SELECT * FROM Vendas WHERE YEAR(CriadoEm)=2025;
-- Bom para índice (faixa)
SELECT * FROM Vendas WHERE CriadoEm >= '2025-01-01' AND CriadoEm < '2026-01-01';
ORDER BY e NULLO que é / Para que serve: Entender a posição de NULL em ordenações.
Sintaxe: ORDER BY Col [ASC|DESC]
Como funciona: Por padrão, em SQL Server, NULLs aparecem primeiro em ASC e por último em DESC.
Implicações & boas práticas: • Para empurrar NULLs para o fim em ASC, use ORDER BY CASE WHEN Col IS NULL THEN 1 ELSE 0 END, Col.
-- NULLs primeiro (ASC):
SELECT Col FROM (VALUES (NULL),(2),(1)) t(Col) ORDER BY Col ASC;
-- Forçar NULLs por último (ASC):
SELECT Col FROM (VALUES (NULL),(2),(1)) t(Col)
ORDER BY CASE WHEN Col IS NULL THEN 1 ELSE 0 END, Col;
CONCAT e NULLO que é / Para que serve: Concatenar strings tratando NULL como vazio.
Sintaxe: CONCAT(a, b, ...)
Como funciona: Em SQL Server, CONCAT converte NULL em string vazia. Já o operador + com strings pode retornar NULL se qualquer lado for NULL.
Implicações & boas práticas: • Prefira CONCAT para evitar NULL propagando na concatenação.
SELECT CONCAT('Nome: ', NULL, ' - OK') AS Resultado; -- 'Nome: - OK'
SELECT 'A' + NULL + 'B'; -- retorna NULL
NOT IN com NULL (armadilha)O que é / Para que serve: Subconsulta com NULL pode tornar o predicado UNKNOWN e retornar zero linhas.
Sintaxe: col NOT IN (subconsulta)
Como funciona: Se a lista tiver NULL, a comparação vira UNKNOWN para todas as linhas. Prefira NOT EXISTS.
Implicações & boas práticas: • Use NOT EXISTS para evitar armadilhas de NULL em subconsultas.
-- Armadilha:
SELECT * FROM Produtos WHERE Categoria NOT IN (SELECT Cat FROM CategoriasPossiveis); -- se houver NULL em Cat, pode retornar nada
-- Correto:
SELECT p.* FROM Produtos p WHERE NOT EXISTS (
SELECT 1 FROM CategoriasPossiveis c WHERE c.Cat = p.Categoria
);
Telefone NVARCHAR(20) NULL. Insira linhas com e sem telefone.IS NULL) e depois os que têm telefone (IS NOT NULL).COUNT(*), COUNT(Telefone) e AVG(COALESCE(Limite,0)).NOT IN falha por causa de NULL e reescreva com NOT EXISTS.CONCAT vs + com uma coluna possivelmente nula.