EXISTS e NOT EXISTS
Verifique linhas relacionadas com eficiência.
EXISTS e NOT EXISTS é uma aula grátis de SQL Academy no CoddyKit. Esta é a aula 2 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de SQL Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de SQL Academy inclui 4 aulas no total.
O que é EXISTS?
O operador EXISTS verifica se uma subconsulta retorna pelo menos uma linha. Ele resulta em TRUE se a subconsulta produzir qualquer resultado e em FALSE se estiver vazia.
Diferentemente de outros operadores de subconsulta que comparam valores, EXISTS se preocupa apenas com a presença — não analisa os dados efetivamente retornados pela subconsulta.
Configurando as tabelas de exemplo
Antes de escrever consultas com EXISTS, vamos criar duas tabelas: customers e orders. Usaremos essas tabelas ao longo da lição para explorar, na prática, como EXISTS e NOT EXISTS funcionam.
CREATE TABLE customers (
customer_id INT PRIMARY KEY,
name VARCHAR(100),
country VARCHAR(50)
);
CREATE TABLE orders (
order_id INT PRIMARY KEY,
customer_id INT,
amount DECIMAL(10,2),
order_date DATE
);
INSERT INTO customers VALUES
(1, 'Alice', 'US'),
(2, 'Bob', 'UK'),
(3, 'Charlie', 'US'),
(4, 'Diana', 'DE');
INSERT INTO orders VALUES
(101, 1, 250.00, '2024-01-10'),
(102, 1, 180.00, '2024-02-15'),
(103, 2, 95.00, '2024-03-01'),
(104, 3, 430.00, '2024-03-22');Sintaxe básica de EXISTS
A sintaxe básica de EXISTS o coloca dentro de uma cláusula WHERE. A subconsulta dentro de EXISTS geralmente faz referência a uma coluna da consulta externa — isso é chamado de subconsulta correlacionada.
A consulta abaixo encontra todos os clientes que fizeram pelo menos um pedido.
SELECT customer_id, name
FROM customers c
WHERE EXISTS (
SELECT 1
FROM orders o
WHERE o.customer_id = c.customer_id
);SELECT 1 dentro de EXISTS
Talvez tenha notado que a subconsulta usa SELECT 1 em vez de selecionar uma coluna real. Isso é intencional — EXISTS verifica apenas se há linhas, não o que elas contêm.
Usar SELECT 1 (ou até mesmo SELECT *) não faz diferença no resultado, mas SELECT 1 sinaliza claramente tanto ao mecanismo do banco de dados quanto ao leitor que os valores em si não importam.
-- Both of these return the same result
SELECT name FROM customers c
WHERE EXISTS (SELECT 1 FROM orders o WHERE o.customer_id = c.customer_id);
SELECT name FROM customers c
WHERE EXISTS (SELECT o.* FROM orders o WHERE o.customer_id = c.customer_id);Como o banco de dados avalia EXISTS
Para cada linha da consulta externa, o banco de dados executa a subconsulta correlacionada. Assim que uma linha correspondente é encontrada, o mecanismo interrompe a varredura e marca EXISTS como TRUE — essa avaliação por curto-circuito torna EXISTS muito eficiente, mesmo em tabelas grandes.
Em contraste, um JOIN construiria o conjunto completo de linhas correspondentes antes da filtragem, o que pode ser mais lento quando você só precisa saber se existe uma correspondência.
-- EXISTS short-circuits after first match
-- Efficient even when orders table has millions of rows
SELECT name, country
FROM customers c
WHERE EXISTS (
SELECT 1
FROM orders o
WHERE o.customer_id = c.customer_id
AND o.amount > 200
);NOT EXISTS: encontrando linhas ausentes
NOT EXISTS é o inverso: retorna TRUE quando a subconsulta não encontra nenhuma linha correspondente. Essa é a forma padrão em SQL de responder a perguntas como "quais clientes nunca fizeram um pedido?"
Tentar resolver isso com um JOIN comum ou NOT IN pode produzir resultados incorretos quando há valores NULL envolvidos — NOT EXISTS evita completamente essa armadilha.
-- Customers who have NOT placed any order
SELECT customer_id, name
FROM customers c
WHERE NOT EXISTS (
SELECT 1
FROM orders o
WHERE o.customer_id = c.customer_id
);NOT EXISTS em comparação com NOT IN e valores NULL
Uma vantagem crítica de NOT EXISTS em relação a NOT IN é a segurança com valores NULL. Se a subconsulta usada por NOT IN retornar até mesmo um valor NULL, toda a expressão NOT IN se tornará NULL — o que significa que nenhuma linha será retornada pela consulta externa.
NOT EXISTS não é afetado por esse problema porque avalia a existência de linhas, não a igualdade de valores.
-- Dangerous: if any customer_id in orders is NULL,
-- NOT IN returns zero rows!
SELECT name FROM customers
WHERE customer_id NOT IN (SELECT customer_id FROM orders);
-- Safe: NOT EXISTS handles NULLs correctly
SELECT name FROM customers c
WHERE NOT EXISTS (
SELECT 1 FROM orders o
WHERE o.customer_id = c.customer_id
);EXISTS com várias condições
A subconsulta dentro de EXISTS pode conter qualquer SQL válido, incluindo várias condições WHERE. Isso permite verificar linhas relacionadas muito específicas — por exemplo, clientes que fizeram um pedido acima de um limite em um determinado mês.
-- Customers who placed an order over 200 in March 2024
SELECT c.name, c.country
FROM customers c
WHERE EXISTS (
SELECT 1
FROM orders o
WHERE o.customer_id = c.customer_id
AND o.amount > 200
AND o.order_date >= '2024-03-01'
AND o.order_date < '2024-04-01'
);EXISTS em DELETE e UPDATE
EXISTS não se limita a instruções SELECT. Você pode usá-lo em UPDATE e DELETE para modificar ou remover linhas com base na existência de dados relacionados em outra tabela.
O exemplo abaixo exclui pedidos pertencentes a clientes de um país específico.
-- Delete orders placed by US customers
DELETE FROM orders o
WHERE EXISTS (
SELECT 1
FROM customers c
WHERE c.customer_id = o.customer_id
AND c.country = 'US'
);Comparando EXISTS com um JOIN
EXISTS e JOIN muitas vezes podem expressar a mesma pergunta, mas se comportam de maneiras diferentes. Um JOIN multiplica as linhas quando há várias correspondências; EXISTS sempre retorna cada linha externa no máximo uma vez.
Quando você só precisa saber se existe uma relação, e não recuperar dados da tabela relacionada, EXISTS é mais claro e geralmente mais rápido.
-- JOIN may return duplicate customer rows if a customer has multiple orders
SELECT DISTINCT c.name
FROM customers c
JOIN orders o ON o.customer_id = c.customer_id;
-- EXISTS always returns each customer once
SELECT c.name
FROM customers c
WHERE EXISTS (
SELECT 1 FROM orders o
WHERE o.customer_id = c.customer_id
);NOT EXISTS para verificações de qualidade dos dados
NOT EXISTS é uma ferramenta poderosa para auditorias de qualidade dos dados. Você pode usá-lo para encontrar registros órfãos, referências ausentes ou linhas que deveriam ter dados relacionados, mas não têm.
A consulta abaixo detecta quaisquer linhas de pedidos cuja customer_id não corresponde a nenhuma linha na tabela de clientes — um sinal de integridade referencial comprometida.
-- Find orders with no matching customer (orphaned records)
SELECT o.order_id, o.customer_id, o.amount
FROM orders o
WHERE NOT EXISTS (
SELECT 1
FROM customers c
WHERE c.customer_id = o.customer_id
);Verificação rápida
Teste sua compreensão de EXISTS e NOT EXISTS.
Recapitulação da lição
Nesta lição, você aprendeu como EXISTS e NOT EXISTS permitem verificar a presença ou a ausência de linhas relacionadas sem comparar valores diretamente.
Principais conclusões:
- EXISTS retorna TRUE assim que a subconsulta encontra uma linha correspondente (avaliação por curto-circuito).
- NOT EXISTS retorna TRUE quando a subconsulta não encontra nenhuma linha correspondente.
- Use
SELECT 1dentro de EXISTS — os valores retornados são irrelevantes. - NOT EXISTS é seguro com valores NULL; NOT IN não é — prefira NOT EXISTS quando puderem aparecer valores NULL.
- EXISTS funciona em instruções SELECT, UPDATE e DELETE.
- Quando você só precisa verificar a existência, EXISTS costuma ser mais claro e rápido do que um JOIN.
Perguntas Frequentes
A aula “EXISTS e NOT EXISTS” é grátis?
Sim — o texto completo de “EXISTS e NOT EXISTS” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de SQL Academy, atualize para CoddyKit PRO. O curso de SQL Academy inclui 4 aulas no total.
O que vou aprender em “EXISTS e NOT EXISTS”?
Verifique linhas relacionadas com eficiência. Você pratica SQL Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.
Preciso ter experiência prévia para começar SQL Academy?
Nenhuma experiência prévia é necessária. SQL Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 2 de 4.
Quanto tempo leva a aula “EXISTS e NOT EXISTS”?
A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.
Posso escrever e executar código nesta aula de SQL Academy?
Sim. Cada aula de SQL Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.
Todas as aulas deste curso
- Subconsultas correlacionadas
- EXISTS e NOT EXISTS
- IN versus ANY versus ALL
- Desempenho de EXISTS versus JOIN