Nesse tutorial vamos mergulhar fundo no mundo dos Cursores Aninhados em Oracle PL/SQL. Este conceito avançado nos permite trabalhar com múltiplos níveis de dados de forma eficiente e elegante. Vamos explorar todos os aspectos deste recurso, com exemplos práticos e insights valiosos!
Para executar os exemplos, certifique-se de criar os objetos conforme mostrado nesse artigo sobre cursores implícitos. Basta clicar aqui.
Introdução aos Cursores Aninhados
Assim como aprendemos a aninhar loops dentro de outros loops no Capítulo 7, “Controle Iterativo: Parte II”, podemos aninhar cursores dentro de outros cursores. Esta técnica é particularmente útil quando precisamos processar dados hierárquicos ou relacionados.
Exemplo Básico de Cursores Aninhados
Vamos começar com um exemplo detalhado que demonstra o conceito de cursores aninhados:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
DECLARE CURSOR c_zip IS SELECT z.zip, z.city FROM zipcode z, student s WHERE z.zip = s.zip AND z.state = 'CT'; BEGIN -- Loop do cursor externo FOR r_zip IN c_zip LOOP DBMS_OUTPUT.PUT_LINE('Estudantes morando em ' || r_zip.city || ', ' || r_zip.zip); -- Loop do cursor interno FOR r_student IN (SELECT first_name || ' ' || last_name AS name FROM student WHERE zip = r_zip.zip) LOOP DBMS_OUTPUT.PUT_LINE(r_student.name); END LOOP; END LOOP; END; |
Análise Detalhada do Exemplo
- Cursor Externo (c_zip):
- Seleciona códigos postais e cidades de Connecticut onde existem estudantes.
- Usa uma junção entre as tabelas
zipcode
estudent
.
- Loop Externo:
- É um cursor FOR loop explícito.
- Itera sobre cada código postal/cidade retornado pelo cursor externo.
- Cursor Interno:
- É um cursor FOR loop implícito aninhado dentro do loop externo.
- Usa o valor
r_zip.zip
do cursor externo para filtrar estudantes.
- Loop Interno:
- Processa cada estudante do código postal atual.
- A variável
r_student.name
contém o nome completo do estudante.
Resultado da Execução
Quando executado, este script produzirá uma saída semelhante a:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
Estudantes morando em Oxford, 06483 John Ancean Estudantes morando em Bridgeport, 06605 Mike Madej Estudantes morando em Woodbury, 06798 David Thares Estudantes morando em Greenwich, 06830 Dawn Dennis Victor Meshaj J. Dalvi Estudantes morando em Norwalk, 06850 Edwin Allende Estudantes morando em Norwalk, 06851 David Essner ... Estudantes morando em Stamford, 06905 Rita Archor Estudantes morando em Stamford, 06907 Charles Caro |
Versão Alternativa com Cursor Explícito
Agora, vamos ver uma versão modificada do exemplo anterior, onde substituímos o cursor FOR loop externo por um loop de cursor explícito:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
DECLARE CURSOR c_zip IS SELECT z.zip, z.city FROM zipcode z, student s WHERE z.zip = s.zip AND z.state = 'CT'; -- Declaração de registro baseado em cursor r_zip c_zip%ROWTYPE; BEGIN OPEN c_zip; -- Loop do cursor externo LOOP FETCH c_zip INTO r_zip; EXIT WHEN c_zip%NOTFOUND; DBMS_OUTPUT.PUT_LINE('Estudantes morando em ' || r_zip.city || ', ' || r_zip.zip); -- Loop do cursor interno (permanece como cursor FOR loop implícito) FOR r_student IN (SELECT first_name || ' ' || last_name AS name FROM student WHERE zip = r_zip.zip) LOOP DBMS_OUTPUT.PUT_LINE(r_student.name); END LOOP; END LOOP; CLOSE c_zip; END; |
Diferenças Chave na Versão Alternativa
- Declaração de Registro Baseado em Cursor:
- Adicionamos
r_zip c_zip%ROWTYPE;
para declarar um registro que corresponde à estrutura do cursorc_zip
.
- Adicionamos
- Gerenciamento Explícito do Cursor:
- Usamos
OPEN c_zip;
para abrir o cursor explicitamente. - Implementamos um loop LOOP…END LOOP para processar o cursor.
- Utilizamos
FETCH c_zip INTO r_zip;
para buscar cada linha do cursor. - Adicionamos
EXIT WHEN c_zip%NOTFOUND;
para sair do loop quando não houver mais linhas. - Fechamos o cursor com
CLOSE c_zip;
ao final do processamento.
- Usamos
- Acesso aos Dados:
- No loop externo, acessamos os dados através do registro
r_zip
(por exemplo,r_zip.city
,r_zip.zip
).
- No loop externo, acessamos os dados através do registro
- Cursor Interno:
- O cursor interno permanece como um cursor FOR loop implícito, demonstrando como podemos combinar diferentes estilos de cursores.
Comparação entre as Duas Abordagens
- Cursor FOR Loop (primeira versão):
- Mais conciso e fácil de ler.
- O Oracle gerencia automaticamente a abertura, busca e fechamento do cursor.
- Loop Explícito (segunda versão):
- Oferece mais controle sobre o processo de busca.
- Permite acesso aos atributos do cursor (%FOUND, %NOTFOUND, %ROWCOUNT).
- Requer mais código e gerenciamento manual do cursor.
Considerações Importantes
- Ambas as versões produzem o mesmo resultado, demonstrando a flexibilidade do PL/SQL em lidar com cursores aninhados.
- A escolha entre usar um cursor FOR loop ou um loop explícito depende das necessidades específicas do seu programa:
- Use cursor FOR loops para código mais conciso e simples.
- Use loops explícitos quando precisar de mais controle ou acesso aos atributos do cursor.
- O cursor interno em ambos os exemplos usa a sintaxe de cursor inline, que é conveniente para consultas que não serão reutilizadas.
- A estrutura de cursores aninhados é particularmente útil para processar dados hierárquicos, como no caso de códigos postais e estudantes.
Dicas e Melhores Práticas
- Escolha o estilo de cursor (FOR loop ou explícito) com base nas necessidades de controle e legibilidade do seu código.
- Use cursores aninhados com cautela em grandes conjuntos de dados, pois podem impactar o desempenho.
- Considere o uso de índices nas colunas frequentemente usadas nos critérios de seleção dos cursores para melhorar o desempenho.
- Para conjuntos de dados muito grandes, explore alternativas como junções de tabelas em uma única consulta ou uso de coleções PL/SQL com BULK COLLECT.
- Mantenha a consistência no estilo de codificação ao longo do seu projeto para melhorar a manutenibilidade.
Conclusão
Os Cursores Aninhados são uma ferramenta poderosa no arsenal do desenvolvedor PL/SQL, permitindo o processamento eficiente de dados hierárquicos ou relacionados. Eles oferecem flexibilidade na manipulação de dados complexos, combinando diferentes estilos de cursores para atender às necessidades específicas do seu programa.
Pontos-chave para lembrar:
- Cursores Aninhados podem combinar cursores explícitos e implícitos.
- A escolha entre cursor FOR loops e loops explícitos depende das necessidades de controle e legibilidade.
- O gerenciamento adequado de cursores é crucial para a eficiência e correção do código.
- Considere o impacto no desempenho ao trabalhar com grandes conjuntos de dados.
- A prática e a experimentação são essenciais para dominar o uso eficaz de cursores aninhados.