0Pricing
SQL Academy · Aula

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 1 dentro 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

  1. Subconsultas correlacionadas
  2. EXISTS e NOT EXISTS
  3. IN versus ANY versus ALL
  4. Desempenho de EXISTS versus JOIN
← Voltar para SQL Academy