Questão de Banco de Dados — Geral — FGV 2026
- Código
- fg157150
- Banca
- FGV
- Órgão
- PC PI
- Ano
- 2026
- Cargo
- Per OC ( )
- Acrimes sem ocorrência.
- Bnenhum crime.
- Cocorrências sem crime.
- Dtodos os crimes cadastrados.
- Euma ocorrência apenas.
GabaritoD — todos os crimes cadastrados.
Gabarito: letra D. A consulta retorna suspeitos associados a todos os crimes cadastrados — é a implementação clássica da operação de divisão relacional da álgebra relacional, que responde a perguntas com quantificador universal ("para todo"). O NOT EXISTS combinado com EXCEPT verifica se o conjunto de todos os crimes menos os crimes do suspeito é vazio, ou seja, se o suspeito tem ocorrência para cada crime existente.
A consulta usa três conceitos centrais de SQL que precisam ser dominados juntos: a subconsulta correlacionada (referencia s.id de fora), o operador EXCEPT (diferença de conjuntos) e o NOT EXISTS (negação da existência). Vamos destrinchar cada um para entender por que a resposta é a letra D e não as demais.
O que é a divisão relacional? Na álgebra relacional, a divisão (÷) responde a perguntas do tipo "quais X estão associados a TODOS os Y?". Por exemplo: "quais suspeitos cometeram todos os crimes cadastrados?" ou "quais alunos cursaram todas as disciplinas?". Não há um comando SQL direto para divisão — ela é implementada com combinações de NOT EXISTS, EXCEPT ou NOT IN com subconsultas correlacionadas. A consulta da questão é exatamente esse padrão.
Como a consulta funciona passo a passo:
Para cada suspeito s (linha a linha, por ser correlacionada), executa-se a subconsulta interna.
A subconsulta select id from cad_crime except select id_crime from cad_ocorrencia o where o.id_suspeito = s.id calcula: todos os crimes (primeiro bloco) menos os crimes que o suspeito s tem ocorrência (segundo bloco). O resultado é o conjunto de crimes que o suspeito NÃO possui ocorrência.
O NOT EXISTS pergunta: esse conjunto é vazio? Se for vazio, significa que não existe nenhum crime sem ocorrência para o suspeito — ou seja, o suspeito tem ocorrência para todos os crimes.
Se o conjunto for vazio, o suspeito entra no resultado final (cpf e nome).
Exemplo concreto: Suponha 3 crimes cadastrados (C1, C2, C3) e 2 suspeitos:
Suspeito A tem ocorrência para C1 e C2, mas não para C3. Subconsulta: {C1,C2,C3} − {C1,C2} = {C3} → não vazio → NOT EXISTS falso → A não entra.
Suspeito B tem ocorrência para C1, C2 e C3. Subconsulta: {C1,C2,C3} − {C1,C2,C3} = {} → vazio → NOT EXISTS verdadeiro → B entra.
Portanto, apenas suspeitos com ocorrência em todos os crimes são retornados.
A pegadinha da banca: a alternativa B ("nenhum crime") é a mais tentadora para quem lê NOT EXISTS apressadamente e pensa que é o oposto de EXISTS. Mas NOT EXISTS aqui não nega a existência de ocorrências — nega a existência de crimes sem ocorrência. A alternativa A ("crimes sem ocorrência") inverte o sujeito: a consulta retorna suspeitos, não crimes. A alternativa C ("ocorrências sem crime") é impossível pela modelagem, pois id_crime é chave estrangeira para cad_crime. A alternativa E ("uma ocorrência apenas") confunde com uma contagem, que não existe na consulta.
Guarde o padrão: NOT EXISTS (SELECT ... EXCEPT SELECT ...) = divisão = "todos". É exatamente esse critério que separa as alternativas.
"Crimes sem ocorrência" inverte o resultado: a consulta retorna suspeitos (cpf, nome), não crimes. Além disso, o NOT EXISTS exige que o conjunto de crimes sem ocorrência seja vazio — ou seja, o oposto de listar crimes sem ocorrência. Se a consulta quisesse crimes sem ocorrência, seria algo como select id from cad_crime where id not in (select id_crime from cad_ocorrencia) — sem a correlação com o suspeito e sem o NOT EXISTS.
"Nenhum crime" é a pegadinha clássica. O NOT EXISTS não significa "não tem ocorrência"; significa "não existe crime sem ocorrência". Um suspeito sem nenhuma ocorrência teria a subconsulta {todos os crimes} − {} = {todos os crimes}, que não é vazio (a menos que não haja crimes cadastrados), então NOT EXISTS seria falso e o suspeito não entraria. A consulta retorna justamente o oposto: suspeitos com ocorrência em todos os crimes.
"Ocorrências sem crime" é impossível pela modelagem: a tabela cad_ocorrencia tem id_crime como chave estrangeira referenciando cad_crime(id). A restrição de integridade referencial garante que toda ocorrência aponta para um crime existente. Além disso, a consulta retorna suspeitos, não ocorrências.
A consulta implementa a divisão relacional: retorna suspeitos que possuem ocorrência para todos os crimes cadastrados. O EXCEPT calcula os crimes que o suspeito não tem; o NOT EXISTS verifica se esse conjunto é vazio. Se for, o suspeito tem todos os crimes — exatamente o que a alternativa afirma.
"Uma ocorrência apenas" não corresponde à lógica da consulta. Não há nenhuma contagem (COUNT) ou restrição a uma única ocorrência. A consulta exige que o suspeito tenha ocorrência para todos os crimes, não apenas um. Um suspeito com uma única ocorrência teria a subconsulta {todos os crimes} − {1 crime} = não vazio → não entraria no resultado.
A banca explora a leitura apressada do NOT EXISTS. Muitos candidatos leem "não existe" e marcam "nenhum crime" (letra B), mas o NOT EXISTS aqui nega a existência de crimes sem ocorrência — o que equivale a "tem todos". O EXCEPT é o operador de diferença: ele subtrai os crimes do suspeito do total de crimes. Se sobrar algo, falta crime; se não sobrar nada, tem todos. Treine identificar o padrão NOT EXISTS (SELECT ... EXCEPT SELECT ...) como divisão relacional — é o mesmo que "para todo".
Para questões de SQL com NOT EXISTS + EXCEPT (ou NOT IN), traduza mentalmente para a pergunta com quantificador universal: "para todo crime, existe ocorrência?". Monte um mini-exemplo com 2-3 crimes e 1-2 suspeitos no papel e execute a consulta manualmente — isso desfaz qualquer ambiguidade. Na prova, desconfie de alternativas que invertem o sujeito (crimes × suspeitos) ou que usam "nenhum" quando a lógica é "todos".
Gabarito: letra D
Link permanente: /questoes/fg157150