Tipos de Cursores Básicos em Oracle PL/SQL

Nesse artigo você vai  mergulhar no mundo dos cursores em Oracle PL/SQL. Você já parou para pensar como o banco de dados lida com conjuntos de dados? É aí que entram os cursores! Vamos explorar os dois tipos principais: cursores implícitos e explícitos.

Se você quer executar os exemplos, certifique-se de executar os scripts de criação de objetos que você pode encontrar aqui: Download DDLs.

O que são Cursores?

Antes de mais nada, vamos entender o que são cursores. Imagine que você tem uma lista de compras. Quando você está no supermercado, você vai passando o dedo por cada item da lista, certo? Bem, um cursor é como esse seu dedo, apontando para cada “item” (ou linha) em um conjunto de resultados de uma consulta SQL. No Oracle PL/SQL, os cursores são mecanismos fundamentais para processar conjuntos de resultados retornados por consultas SQL. Eles permitem que você percorra as linhas de dados, uma por uma, realizando operações específicas em cada linha.

Cursores Implícitos

Vamos começar com os cursores implícitos. Esses são como aqueles ajudantes silenciosos que trabalham nos bastidores.

Definição:

Um cursor implícito é gerenciado automaticamente pelo PL/SQL. Toda vez que você executa um comando SQL (como SELECT INTO, INSERT, UPDATE ou DELETE), o PL/SQL cria um cursor implícito para você, sem que você precise fazer nada. Isso simplifica muito o código para operações que afetam apenas uma linha ou um pequeno conjunto de dados.

Exemplo de Cursor Implícito

Neste código, o PL/SQL cria automaticamente um cursor implícito para o comando SELECT INTO. O cursor é aberto, os dados são buscados e o cursor é fechado, tudo isso sem que você precise escrever código específico para gerenciar o cursor.

Atributos de Cursores Implícitos

Embora você não possa controlar diretamente um cursor implícito, pode obter informações sobre ele usando alguns atributos especiais. Esses atributos são prefixados com “SQL%” porque se referem ao cursor implícito mais recentemente executado.

  1. SQL%ISOPEN: Sempre retorna FALSE para cursores implícitos, pois o PL/SQL fecha o cursor imediatamente após a execução da instrução.
  2. SQL%FOUND: Retorna TRUE se a operação afetou pelo menos uma linha, FALSE se nenhuma linha foi afetada, ou NULL se nenhuma instrução SQL ou DML foi executada.
  3. SQL%NOTFOUND: É o oposto lógico de SQL%FOUND. Retorna TRUE se nenhuma linha foi afetada, FALSE se pelo menos uma linha foi afetada, ou NULL se nenhuma instrução SQL ou DML foi executada.
  4. SQL%ROWCOUNT: Retorna o número de linhas afetadas pela instrução SQL mais recente. Retorna NULL se nenhuma instrução SQL ou DML foi executada.

Vamos ver como usar esses atributos em um exemplo mais detalhado:

Este exemplo demonstra o uso de cursores implícitos em diferentes operações SQL (UPDATE, SELECT) e mostra como os atributos do cursor implícito podem ser usados para obter informações sobre a execução dessas operações.

Cursores Explícitos

Agora, vamos falar dos cursores explícitos. Estes são como assistentes pessoais que você contrata e diz exatamente o que fazer. Eles oferecem mais controle e flexibilidade, especialmente quando você precisa processar múltiplas linhas de dados.

Definição

Um cursor explícito é definido e gerenciado por você. Você declara, abre, busca dados e fecha o cursor manualmente no seu programa. Isso permite um controle mais granular sobre o processamento dos dados.

Trabalhando com Cursores Explícitos

Trabalhar com cursores explícitos envolve quatro etapas principais:

  1. Declarar o cursor
  2. Abrir o cursor
  3. Buscar dados do cursor
  4. Fechar o cursor

Vamos ver cada uma dessas etapas em detalhes:

1. Declarando um Cursor

A declaração de um cursor associa um nome a uma instrução SELECT específica. Isso é feito na seção DECLARE do bloco PL/SQL. Aqui está a sintaxe básica:

Exemplo:

Neste exemplo, declaramos um cursor chamado c_professores que seleciona informações de professores do departamento de Computação.

2. Abrindo e Fechando um Cursor

Após declarar o cursor, você precisa abri-lo antes de usá-lo e fechá-lo quando terminar. Isso é feito com as instruções OPEN e CLOSE:

A instrução OPEN executa a consulta SQL associada ao cursor e identifica o conjunto de resultados. A instrução CLOSE libera os recursos alocados para o cursor.

3. Buscando Dados de um Cursor

Para recuperar dados de um cursor aberto, usamos a instrução FETCH. Cada FETCH recupera a próxima linha do conjunto de resultados do cursor. Aqui está um exemplo:

Neste exemplo, usamos um loop para buscar cada linha do cursor e imprimir as informações do professor.

4. Exemplo Completo com Cursor Parametrizado

Vamos ver um exemplo mais complexo que usa um cursor parametrizado para buscar alunos de um determinado curso:

Este exemplo demonstra um cursor parametrizado que aceita um ID de curso como parâmetro. Ele busca todos os alunos matriculados nesse curso específico, demonstrando como os cursores podem ser usados para processar conjuntos de dados mais complexos.

Atributos de Cursores Explícitos

Assim como os cursores implícitos, os explícitos também têm atributos úteis. A diferença é que para cursores explícitos, você usa o nome do cursor ao invés de “SQL” para acessar esses atributos:

  1. %ISOPEN: Retorna TRUE se o cursor estiver aberto, FALSE caso contrário.
  2. %FOUND: Retorna TRUE se a última busca retornou uma linha, FALSE se não retornou, ou NULL se nenhuma busca foi realizada ainda.
  3. %NOTFOUND: O oposto de %FOUND.
  4. %ROWCOUNT: Retorna o número de linhas buscadas até o momento.

Veja como usar esses atributos em um exemplo mais detalhado (esse exemplo usa o schema demo HR fornecido pela própria Oracle. Se você ainda não criou o schema HR baixe os scripts aqui):

Este exemplo demonstra o uso de todos os atributos do cursor explícito, fornecendo informações detalhadas sobre o processamento dos dados. Vamos examinar com mais detalhes.

Declaração do Cursor:

Este cursor seleciona informações dos departamentos que têm um gerente atribuído (manager_id não é nulo).

Declaração de Variáveis:

Estas variáveis armazenarão os dados de cada departamento e contarão o total de departamentos processados.

Abertura do Cursor:

Verifica se o cursor já está aberto. Se não estiver, abre-o e imprime uma mensagem.

Loop Principal:

Este loop busca cada registro do cursor e processa-o. O loop termina quando não há mais registros para buscar.

Processamento de Cada Departamento:

Incrementa o contador de departamentos, imprime as informações do departamento atual e o número de linhas processadas até o momento.

Impressão dos Totais:

Após o loop, imprime o total de departamentos processados e o número total de linhas processadas pelo cursor.

Fechamento do Cursor:

Verifica se o cursor ainda está aberto. Se estiver, fecha-o e imprime uma mensagem.

Tratamento de Exceções:

Se ocorrer qualquer erro durante a execução, este bloco garante que o cursor seja fechado antes de repassar a exceção.

Este script demonstra várias características importantes dos cursores explícitos:

  • Uso dos atributos do cursor (%ISOPEN, %FOUND, %ROWCOUNT)
  • Abertura e fechamento explícitos do cursor
  • Processamento de registros em um loop
  • Contagem manual de registros processados
  • Tratamento de exceções e garantia de que o cursor seja fechado em caso de erro

Cursores FOR Loops

Cursor FOR Loop Implícito

Um cursor FOR loop implícito não requer a declaração prévia do cursor. Em vez disso, a instrução SELECT é embutida diretamente no loop. Veja um exemplo para listar nomes de funcionários de um banco de dados:

Explicação do Cursor FOR Loop Implícito

  • FOR emp_rec IN (SELECT …): Aqui, o cursor é declarado implicitamente dentro do loop. Não há necessidade de abrir, buscar ou fechar o cursor manualmente; isso é tratado automaticamente.
  • emp_rec: É uma variável de linha do tipo %ROWTYPE, que representa cada registro retornado pela consulta.

Cursor FOR Loop Explícito

Um cursor FOR loop explícito envolve a declaração do cursor antes do uso no loop. Isso é útil quando você precisa reutilizar o cursor ou processá-lo múltiplas vezes. Veja um exemplo:

Explicação do Cursor FOR Loop Explícito

  • DECLARE CURSOR c_emp_dept IS …: O cursor é declarado explicitamente fora do loop.
  • FOR emp_rec IN c_emp_dept LOOP: O loop percorre cada registro retornado pelo cursor c_emp_dept.
  • A abertura, a busca e o fechamento do cursor são gerenciados automaticamente pelo loop.

Considerações Finais

  • Cursor Implícito: Ideal para situações simples onde o cursor é usado uma única vez.
  • Cursor Explícito: Útil quando você precisa de mais controle sobre o cursor, como reutilizá-lo ou aplicar lógica adicional entre aberturas e fechamentos.

Esses exemplos demonstram como utilizar CURSOR FOR LOOPS de maneira eficiente em PL/SQL, simplificando a manipulação de conjuntos de resultados sem a necessidade de gerenciar manualmente o ciclo de vida do cursor.

Cursores com Parâmetros

Cursores com parâmetros permitem que você crie cursores mais flexíveis e reutilizáveis. Veja um exemplo:

Este exemplo usa um cursor parametrizado para listar funcionários de um departamento específico, calculando também o salário médio do departamento.

Cursores Aninhados (Nested Cursors)

Cursores aninhados são úteis quando você precisa processar dados hierárquicos ou relacionados. Veja um exemplo:

Neste script, um cursor FOR loop implícito (loop interno) está aninhado dentro de um cursor FOR loop explícito (loop externo), c_dept. Para cada iteração do cursor c_dept, o loop interno percorre todo o conjunto de resultados da tabela EMPLOYEES para um determinado departamento.

Explicação de Cursores Aninhados:

  • Loop Externo: O loop externo (FOR r_dept IN c_dept LOOP) itera sobre cada departamento_id e nome do departamento onde há funcionários e o location_id é 1700. Este é um cursor explícito, pois c_dept é declarado antes do loop.
  • Loop Interno: O loop interno (FOR r_employee IN (...) LOOP) é um cursor implícito que não precisa ser declarado previamente. Ele seleciona os nomes completos dos funcionários cujo department_id corresponde ao department_id atual do loop externo.
  • Uso de r_dept.department_id: A variável r_dept.department_id é utilizada no critério de seleção do loop interno para determinar corretamente o conjunto de funcionários para um departamento específico.

Produção de Saída: Este script produz uma saída listando funcionários por departamento, como mostrado abaixo:

Versão Alternativa com Cursor Declarado: Em uma versão alternativa do exemplo, o loop do cursor externo pode ser substituído por um loop que abre, busca e fecha o cursor explicitamente:

Nesta versão, a manipulação do cursor é feita explicitamente, e um registro baseado em cursor é declarado para viabilizar a busca do cursor externo. A saída produzida é idêntica à versão anterior.

Melhores Práticas ao Trabalhar com Cursores

  1. Use cursores implícitos para operações simples que afetam uma única linha.
  2. Prefira cursores explícitos para operações que processam múltiplas linhas.
  3. Utilize cursores FOR loops sempre que possível, pois eles são mais eficientes e requerem menos código.
  4. Feche sempre os cursores explícitos após o uso para liberar recursos.
  5. Considere o uso de cursores com parâmetros para criar código mais flexível e reutilizável.
  6. Esteja ciente do impacto de desempenho ao usar cursores, especialmente ao processar grandes conjuntos de dados.

Conclusão

Ufa! Chegamos ao fim da nossa jornada pelos tipos de cursores em Oracle PL/SQL. Vamos recapitular os pontos principais:

  1. Cursores implícitos são gerenciados automaticamente pelo PL/SQL e são ótimos para operações simples.
  2. Cursores explícitos dão a você controle total sobre o processamento dos dados e são ideais para operações mais complexas.
  3. Ambos os tipos têm atributos úteis que fornecem informações sobre o estado do cursor.
  4. Cursores FOR loops oferecem uma maneira concisa e eficiente de processar conjuntos de resultados.
  5. Cursores com parâmetros permitem criar código mais flexível e reutilizável.
  6. Cursores aninhados são úteis para processar dados hierárquicos.

Lembre-se: a escolha entre usar um cursor implícito ou explícito, e qual tipo específico de cursor explícito usar, depende das necessidades específicas do seu programa. Cursores implícitos são ótimos para operações simples, enquanto os explícitos brilham quando você precisa de mais controle e flexibilidade.

Pratique bastante esses conceitos e você logo se tornará um mestre em cursores! Eles são uma ferramenta poderosa no seu arsenal de desenvolvimento PL/SQL, permitindo que você crie aplicações de banco de dados robustas e eficientes.

Scroll to Top