O código DDL abaixo cria três tabelas em um banco de dados relacional: CREATE TABLE Velejadores ( vid INTEGER PRIMARY KEY, nome VARCHAR(100), idade INTEGER ); CREATE TABLE Barcos ( bid INTEGER PRIMARY KEY, nome VARCHAR(50), modelo VARCHAR(50) ); CREATE TABLE Reservas ( vid INTEGER, bid INTEGER, data DATE, PRIMARY KEY (vid, bid), FOREIGN KEY (vid) REFERENCES Velejadores(vid), FOREIGN KEY (bid) REFERENCES Barcos(bid) ); Considerando as tabelas acima, a seguinte consulta foi realizada: SELECT V.nome FROM Velejadores V WHERE NOT EXISTS ( (SELECT B.bid FROM Barcos B) EXCEPT (SELECT R.bid FROM Reservas R WHERE R.vid = V.vid) ); O retorno da consulta foram os nomes
- A)dos velejadores que possuem reservas para todos os barcos.
Correta: a condição testa se não existe barco que esteja em Barcos e não esteja entre os barcos reservados por cada velejador, ou seja, se ele reservou todos os barcos.
- B)dos barcos que não possuem reservas.
Errada: a consulta não lista barcos sem reserva, e sim nomes de velejadores filtrados por uma condição sobre todas as embarcações.
- C)dos velejadores que não possuem reservas.
Errada: não basta o velejador não ter reservas; a lógica aqui exige justamente o oposto, a cobertura total dos barcos.
- D)dos velejadores que possuem reserva para mais de um barco.
Errada: a consulta não verifica quantidade de reservas, mas sim se o conjunto de barcos reservados cobre todos os barcos existentes.
- E)dos barcos que possuem reservas feitas por todos os velejadores.
Errada: o resultado não são barcos, e sim velejadores, além de a comparação ser feita do lado das reservas de cada velejador, não de reservas feitas por todos.
Gabarito: A
Essa consulta usa uma ideia clássica de banco relacional: verificar se existe, para cada velejador, algum barco que ainda não foi reservado por ele. O trecho com EXCEPT faz a diferença entre “todos os barcos” e “os barcos reservados por aquele velejador”. Se essa diferença vier vazia, significa que não sobrou barco nenhum de fora da lista de reservas daquele velejador. Traduzindo para linguagem de prova: o subselect interno monta o conjunto de barcos que o velejador V ainda não reservou. O NOT EXISTS diz que esse conjunto precisa ser vazio. Em outras palavras, para aquele V, não pode existir barco sem reserva feita por ele. Isso é exatamente o mesmo que dizer que ele reservou todos os barcos existentes. Por isso o gabarito é a alternativa A. A consulta retorna os nomes dos velejadores que possuem reservas para todos os barcos, isto é, os que satisfazem a condição de cobertura completa do conjunto de Barcos. É a lógica de divisão relacional disfarçada de SQL, uma velha conhecida das bancas: quem conhece a “divisão” sorri, quem não conhece vai no susto. Não há fundamento legal aqui, porque a questão é puramente de álgebra relacional e SQL. O ponto central é entender o sentido de NOT EXISTS com EXCEPT: vazio = não falta nenhum barco para aquele velejador.