【Tutorial de SQL NULL】Domine a Extração de Dados Conquistando IS NULL e IS NOT NULL
Quando você começa a aprender SQL, inevitavelmente encontra uma entidade misteriosa: `NULL`. Ele é usado para representar um estado onde os dados não existem, como "um usuário com um número de telefone não registrado" ou "um produto sem nada escrito no campo de notas". No entanto, o tratamento de `NULL` é muito especial, e muitos iniciantes se deparam com um muro, perguntando-se: "Por que não consigo obter os dados que esperava?".
A principal razão para isso é tentar comparar `NULL` com = (igual), como se fosse o mesmo que "0" ou uma "string vazia ('')". No mundo do SQL, existe uma regra filosófica: `NULL` не é igual a nenhum outro valor, nem mesmo a si próprio.
Este artigo explicará detalhadamente a natureza do `NULL` e os operadores dedicados para tratá-lo corretamente, `IS NULL` e `IS NOT NULL`, usando código que você pode copiar e colar. Não é exagero dizer que quem domina o `NULL`, domina o SQL. Vamos aproveitar esta oportunidade para dominar definitivamente a habilidade de verificar a existência de dados!
Preparação: Vamos Preparar Dados de Membros que Incluam NULL
Para ver como o `NULL` realmente se comporta, primeiro vamos preparar alguns dados de amostra. Desta vez, vamos criar uma tabela simples de members para gerenciar informações de membros. A chave é registrar intencionalmente registros que contenham `NULL` (um estado onde os dados estão vazios), como para números de telefone e datas do último login.
-- Se a tabela members existir, exclua-a (para testes repetíveis)
DROP TABLE IF EXISTS members;
-- Crie uma nova tabela members
CREATE TABLE members (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL,
email TEXT NOT NULL UNIQUE,
phone_number TEXT, -- Permite NULL
last_login DATE, -- Permite NULL
points INTEGER DEFAULT 0
);
-- Insira dados iniciais
INSERT INTO members (id, name, email, phone_number, last_login, points) VALUES
(1, 'Yamada Taro', 'yamada@example.com', '090-1111-2222', '2025-06-25', 150),
(2, 'Suzuki Hanako', 'suzuki@example.com', NULL, '2025-07-01', 50),
(3, 'Sato Jiro', 'sato@example.com', '080-3333-4444', NULL, 200),
(4, 'Ito Sakura', 'ito@example.com', NULL, NULL, 0),
(5, 'Watanabe Kenta', 'watanabe@example.com', '', '2025-06-28', 300); -- O número de telefone é uma string vazia
Esses dados incluem usuários com um número de telefone `NULL` (IDs 2, 4) e usuários com um último login `NULL` (IDs 3, 4). Além disso, observe que o número de telefone de Watanabe (ID 5) não é `NULL`, mas sim uma **string vazia** (''). Essa distinção será importante mais tarde.
A Maior Armadilha: Por Que Não se Pode Buscar com `= NULL`?
Não é exagero dizer que 100% dos iniciantes em SQL caem nesta armadilha: escrever WHERE phone_number = NULL. À primeira vista, parece que deveria funcionar corretamente, mas se você executar esta consulta, nenhum registro será retornado.
-- 【ERRADO!】Esta consulta não funcionará como esperado
SELECT * FROM members WHERE phone_number = NULL;
Por que isso acontece? É porque `NULL` representa um estado especial de "sem valor" ou "desconhecido". Como `NULL` não é um valor, qualquer comparação com ele (mesmo uma comparação com o próprio `NULL`) não resulta em `TRUE` ou `FALSE`, mas em um terceiro estado: `UNKNOWN` (desconhecido). A cláusula WHERE extrai apenas registros para os quais a condição é `TRUE`, então registros que avaliam para `UNKNOWN` nunca são selecionados.
Pense nisso como uma pergunta de pesquisa sobre "comida favorita". Se você quer encontrar pessoas que deixaram a resposta "em branco", não pode encontrá-las procurando por pessoas que escreveram a palavra "em branco". Você precisa procurar pelo estado de "estar em branco" em si.
【O Básico】A Maneira Correta de Usar `IS NULL` e `IS NOT NULL`
O SQL fornece operadores dedicados para verificar este estado especial de `NULL`. Eles são `IS NULL` e `IS NOT NULL`.
`IS NULL`: Extraindo Registros Onde um Valor é NULL
Se você quer encontrar registros onde o valor de uma coluna é `NULL` (os dados estão vazios), você deve usar `IS NULL`, e não `= NULL`.
Cenário: "Encontrar todos os membros que não registraram um número de telefone (onde `phone_number` é `NULL`)."
SELECT * FROM members WHERE phone_number IS NULL;
Resultado:
id | name | email | phone_number | last_login | points
---|--------------|-------------------|--------------|------------|-------
2 | Suzuki Hanako| suzuki@example.com| NULL | 2025-07-01 | 50
4 | Ito Sakura | ito@example.com | NULL | NULL | 0
Desta vez, os usuários com IDs 2 e 4 foram extraídos corretamente como pretendido. Note que Watanabe (ID 5) não está incluído no resultado porque seu número de telefone é uma "string vazia", e não `NULL`.
`IS NOT NULL`: Extraindo Registros Onde um Valor não é NULL
Por outro lado, se você quer encontrar registros onde há algum dado (ou seja, o valor não está vazio), você usa `IS NOT NULL`.
Cenário: "Encontrar todos os membros que têm um registro do último login (onde `last_login` не é `NULL`)."
SELECT * FROM members WHERE last_login IS NOT NULL;
Resultado:
id | name | email | phone_number | last_login | points
---|----------------|----------------------|----------------|------------|-------
1 | Yamada Taro | yamada@example.com | 090-1111-2222 | 2025-06-25 | 150
2 | Suzuki Hanako | suzuki@example.com | NULL | 2025-07-01 | 50
5 | Watanabe Kenta | watanabe@example.com | | 2025-06-28 | 300
Como você pode ver, usar `IS NOT NULL` permite selecionar eficientemente apenas os registros que não têm dados ausentes.
Aplicação: Entendendo a Diferença Entre `NULL`, Strings Vazias e `0`
Iniciantes frequentemente tratam "strings vazias ('')" e o "número 0" como se fossem o mesmo que `NULL`. No SQL, estes são tratados como coisas distintas.
- `NULL`: Um estado de ser "desconhecido" ou "inexistente".
- String Vazia (
''): Um "valor" que é uma string de comprimento zero. 0: Um "valor" numérico de zero.
O número de telefone de Watanabe (ID 5) é uma string vazia, não `NULL`. Portanto, a seguinte consulta encontrará apenas o usuário com ID 5.
SELECT * FROM members WHERE phone_number = '';
Da mesma forma, os pontos de Ito (ID 4) são `0`, mas isso é diferente de `NULL`. Essa diferença fica ainda mais clara ao usar funções de agregação como `COUNT`.
-- Membros totais, membros com um número de telefone registrado, e soma dos pontos
SELECT COUNT(*), COUNT(phone_number), SUM(points) FROM members;
Resultado:
COUNT(*) | COUNT(phone_number) | SUM(points)
--------|---------------------|------------
5 | 3 | 650
COUNT(*) conta todos os registros, então é 5, mas COUNT(phone_number) ignora valores `NULL`, então é 3 (IDs 1, 3 e 5). Da mesma forma, SUM(points) também exclui registros com `NULL` de seu cálculo. Este comportamento é muito importante na análise de dados, então certifique-se de lembrá-lo.
【Playground Interativo】Verifique o Comportamento do NULL Executando SQL no seu Navegador!
Agora é hora de transformar conhecimento em habilidade! Copie todo o código HTML abaixo, salve-o como um arquivo tipo sql_null_test.html, e abra-o no seu navegador. Seu próprio ambiente SQL pessoal será iniciado, pré-carregado com a tabela members que usamos neste artigo.
Veja por si mesmo como os resultados diferem entre = NULL e IS NULL, e por que COUNT(*) e COUNT(column_name) dão resultados diferentes. Vamos descobrir sujando as mãos!
<!DOCTYPE html>
<html lang="pt">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Playground Online de SQL NULL</title>
<style>
body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; line-height: 1.7; color: #333; max-width: 800px; margin: 2rem auto; padding: 0 1rem; }
h1 { color: #34495e; }
textarea { width: 100%; height: 180px; font-family: "SF Mono", "Consolas", monospace; font-size: 16px; padding: 12px; border: 1px solid #ccc; border-radius: 6px; box-sizing: border-box; margin-bottom: 1rem; }
button { background-color: #34495e; color: white; border: none; padding: 12px 22px; font-size: 16px; border-radius: 6px; cursor: pointer; transition: background-color 0.2s; }
button:hover { background-color: #2c3e50; }
button:disabled { background-color: #bdc3c7; cursor: not-allowed; }
#result-container { margin-top: 2rem; border: 1px solid #ddd; padding: 1rem; border-radius: 6px; background: #fdfdfd; min-height: 50px; }
#error-message { color: #e74c3c; font-weight: bold; }
table { border-collapse: collapse; width: 100%; margin-top: 1rem; }
th, td { border: 1px solid #ddd; padding: 10px; text-align: left; }
th { background-color: #f2f2f2; }
tr:nth-child(even) { background-color: #f9f9f9; }
</style>
<script src="https://cdnjs.cloudflare.com/ajax/libs/sql.js/1.10.3/sql-wasm.js"></script>
</head>
<body>
<h1>Vamos Experimentar o SQL!</h1>
<p>Digite uma instrução SQL na área de texto abaixo e clique no botão "Executar". Experimente com diferentes condições!</p>
<textarea id="sql-input">-- Encontrar membros que nunca fizeram login (last_login é NULL)
SELECT * FROM members WHERE last_login IS NULL;
</textarea>
<button id="execute-btn">Executar</button>
<div id="result-container">
<p id="error-message"></p>
<div id="result-output"></div>
</div>
<script>
const sqlInput = document.getElementById('sql-input');
const executeBtn = document.getElementById('execute-btn');
const errorMsg = document.getElementById('error-message');
const resultOutput = document.getElementById('result-output');
let db;
async function initDb() {
executeBtn.disabled = true;
executeBtn.textContent = 'Inicializando BD...';
try {
const SQL = await initSqlJs({
locateFile: file => `https://cdnjs.cloudflare.com/ajax/libs/sql.js/1.10.3/${file}`
});
db = new SQL.Database();
const setupSql = `
DROP TABLE IF EXISTS members;
CREATE TABLE members (id INTEGER PRIMARY KEY, name TEXT NOT NULL, email TEXT NOT NULL UNIQUE, phone_number TEXT, last_login DATE, points INTEGER DEFAULT 0);
INSERT INTO members (id, name, email, phone_number, last_login, points) VALUES
(1, 'Yamada Taro', 'yamada@example.com', '090-1111-2222', '2025-06-25', 150),
(2, 'Suzuki Hanako', 'suzuki@example.com', NULL, '2025-07-01', 50),
(3, 'Sato Jiro', 'sato@example.com', '080-3333-4444', NULL, 200),
(4, 'Ito Sakura', 'ito@example.com', NULL, NULL, 0),
(5, 'Watanabe Kenta', 'watanabe@example.com', '', '2025-06-28', 300);
`;
db.run(setupSql);
executeBtn.disabled = false;
executeBtn.textContent = 'Executar';
resultOutput.innerHTML = '<p>Pronto! Sinta-se à vontade para experimentar suas próprias consultas SQL.</p>';
} catch (err) {
errorMsg.textContent = 'Falha ao inicializar o banco de dados: ' + err.message;
console.error(err);
}
}
function executeSql() {
if (!db) return;
const sql = sqlInput.value;
errorMsg.textContent = '';
resultOutput.innerHTML = '';
try {
const results = db.exec(sql);
if (results.length === 0) {
resultOutput.innerHTML = '<p>Consulta executada com sucesso, mas nenhum conjunto de resultados foi retornado.</p>';
return;
}
results.forEach(result => {
const table = document.createElement('table');
const thead = document.createElement('thead');
const tbody = document.createElement('tbody');
const headerRow = document.createElement('tr');
result.columns.forEach(colName => {
const th = document.createElement('th');
th.textContent = colName;
headerRow.appendChild(th);
});
thead.appendChild(headerRow);
result.values.forEach(row => {
const bodyRow = document.createElement('tr');
row.forEach(cellValue => {
const td = document.createElement('td');
td.textContent = cellValue === null ? 'NULL' : cellValue;
bodyRow.appendChild(td);
});
tbody.appendChild(bodyRow);
});
table.appendChild(thead);
table.appendChild(tbody);
resultOutput.appendChild(table);
});
} catch (err) {
errorMsg.textContent = 'Erro de SQL: ' + err.message;
console.error(err);
}
}
executeBtn.addEventListener('click', executeSql);
initDb();
</script>
</body>
</html>
Conclusão
Neste artigo, aprendemos sobre a maneira correta de lidar com `NULL` no SQL, cobrindo seu conceito e métodos específicos de verificação.
- A Natureza do `NULL`: `NULL` é um estado especial que representa "sem valor" ou "desconhecido" e é completamente diferente de "0" ou uma "string vazia".
- A Regra de Comparação: A comparação com `NULL` (
=,<>) sempre resulta em `UNKNOWN`, então não produzirá os resultados esperados em uma cláusulaWHERE. - O Método de Verificação Correto: A única maneira correta de verificar se algo é `NULL` é usar
IS NULL, e para verificar se não é `NULL`, usarIS NOT NULL. - Relação com Funções de Agregação: Funções de agregação como
COUNT(nome_da_coluna),SUM(), eAVG()excluem automaticamente registros com `NULL` de seus cálculos.
Compreender corretamente o conceito de `NULL` é um passo inevitável para dominar o SQL. Pode ser um pouco confuso no início, mas se você tiver em mente que "`NULL` não é um valor, mas um estado", você se acostumará gradualmente. Esta habilidade é essencial para lidar corretamente com dados ausentes e desenvolver aplicações robustas e sem bugs. Seu nível de SQL acabou de subir mais um degrau!