Uma subconsulta é uma maneira poderosa de localizar os dados que você deseja usar para outra consulta. Eles são frequentemente usados em instruções SELECT e UPDATE para tornar essas consultas mais eficientes e fáceis de manter.
Existem várias maneiras diferentes de usar subconsultas em instruções UPDATE. Vamos dar uma olhada em cada um deles.
SET e subconsulta
O primeiro método que veremos é usar uma subconsulta na cláusula SET de uma instrução UPDATE.
Digamos que tivéssemos uma tabela de produtos assim:
[ID da tabela=29 /]
Ele armazena algumas informações sobre diferentes produtos que uma empresa vende.
Suponha que a empresa decidiu aumentar o preço do produto “Couch” (ID do produto 1). No entanto, em vez de definir um preço específico, eles querem torná-lo 20% maior do que o produto mais caro que possuem.
Para fazer isso, podemos usar uma subconsulta na cláusula SET. Poderíamos usar instruções separadas, mas é mais fácil manter usando uma única instrução.
Nossa declaração ficaria assim:
UPDATE product SET price = ( SELECT MAX(price) * 1.2 FROM product ) WHERE product_id = 1;
Você pode ver que a cláusula SET inclui uma subconsulta, que encontra o valor MAX da coluna de preço na tabela de produtos e o multiplica por 1,2 para adicionar 20%. Por fim, a cláusula WHERE está fora da subconsulta para atualizar apenas o product_id de 1, pois se aplica a UPDATE e não à subconsulta.
Isso resultará na seguinte alteração:
[ID da tabela=30 /]
SET e subconsulta correlacionada
Outra maneira de usar uma subconsulta em uma instrução UPDATE é usar uma subconsulta correlacionada.
Funciona de forma semelhante ao exemplo anterior. No entanto, uma subconsulta correlacionada é uma subconsulta que se refere à instrução externa e pode ser parte de uma instrução UPDATE.
Usando os dados do exemplo anterior (tabela de produtos), a empresa deseja desativar todos os produtos que não tiveram um pedido feito para eles. Os dados para isso são armazenados na tabela order_line.
Se a escrevermos como uma subconsulta correlacionada, a consulta ficará assim:
UPDATE product p SET active = ( SELECT CASE WHEN COUNT(*) > 0 THEN 'Y' ELSE 'N' END FROM order_line o WHERE o.product_id = p.product_id );
A subconsulta executará uma função COUNT usando uma instrução CASE para determinar se o valor retornado é Y ou N dependendo do valor de COUNT. Ele é calculado para cada product_id e corresponde à consulta externa.
Isso resultará na coluna ativa para alguns produtos definidos como Y e outros definidos como N:
[ID da tabela=31 /]
ONDE maior que a subconsulta
Também é possível usar uma subconsulta na cláusula WHERE. Assim como nos exemplos anteriores, isso pode ser feito para remover a etapa separada de encontrar um valor a ser atualizado e, em seguida, executar a consulta para atualizá-lo.
Podemos continuar trabalhando com nosso exemplo das etapas anteriores. Suponha que a empresa queira ativar produtos que tenham preço acima da média. Para fazer isso, podemos adicionar uma subconsulta à cláusula WHERE.
Primeiro, desative todos os produtos.
UPDATE product SET active = ’N’;
Em seguida, atualize a tabela usando nossa subconsulta.
UPDATE product SET active = 'Y' WHERE price > ( SELECT AVG(price) FROM product );
Isso definirá o valor ativo como Y para todos os registros com preço acima da média.
A tabela agora está assim:
[ID da tabela=32 /]
Mostra 2 registros com valor ativo de Y porque estão acima da média.
Esse tipo de consulta também pode ser executado com outros operadores que permitem um único valor, como
ONDE EM Subconsulta
Além disso, podemos usar uma subconsulta com um operador IN na cláusula WHERE.
Isso é semelhante ao exemplo anterior que usou o operador maior que para um único valor. O operador IN pode ser aplicado a vários valores.
Digamos que a empresa quisesse atualizar o preço de alguns produtos que eram o único item da categoria. Os preços teriam que ser reduzidos pela metade.
Nossa consulta pode ficar assim:
UPDATE product SET price = price / 2 WHERE category_id IN ( SELECT category_id FROM product GROUP BY category_id HAVING COUNT(*) = 1 );
A subconsulta encontra todos os valores category_id onde COUNT é 1. Não precisamos ter COUNT na parte SELECT da subconsulta, no entanto, se o fizermos, a consulta exibirá um erro.
A instrução UPDATE atualizará o preço onde a categoria atende aos critérios da subconsulta.
Nossos resultados então ficarão assim:
[ID da tabela=33 /]
Os dados são muito semelhantes. No entanto, o produto com ID de categoria 1 teve seu preço atualizado para metade do custo original, pois é o único produto em sua categoria.
UPDATE Subconsulta
Por fim, você pode usar uma subconsulta em uma instrução UPDATE para que a tabela seja atualizada.
Nos exemplos anteriores, usamos apenas a tabela de produtos. No entanto, você pode usar uma subconsulta em vez da tabela de produtos, que retornará um conjunto de resultados que pode ser atualizado.
O conjunto de resultados precisa ser atualizável, semelhante ao caso quando você cria um objeto VIEW e tenta atualizá-lo. Ele precisa ser simples e ter a chave primária.
Assim, usando nossos exemplos anteriores, suponha que a empresa queira alterar a categoria de todos os produtos que estão na categoria 4 para a categoria 5.
Nossa consulta pode ficar assim:
UPDATE ( SELECT product_id, category_id FROM product) SET category_id = 5 WHERE category_id = 4;
É um exemplo simples que demonstra o conceito. A tabela foi substituída pela instrução SELECT que mostra apenas duas colunas da tabela.
Os resultados dessa consulta seriam:
[ID da tabela=34 /]
O mesmo resultado pode ser recebido movendo a cláusula WHERE para a instrução UPDATE:
UPDATE ( SELECT product_id, category_id FROM product WHERE category_id = 4) SET category_id = 5;
Conclusão
Usar uma subconsulta em uma instrução UPDATE pode ser uma boa maneira de melhorar a capacidade de manutenção de suas consultas. Ele também pode reduzir o número de etapas necessárias para atualizar seus dados compactando duas ou mais consultas em uma única consulta.