Cursores no Oracle – Parte 1

Falar sobre cursores é abordar um assunto polêmico... Já que a maioria dos desenvolvedores não sabem quando utilizá-los...

Por isso antes de você fazer como eu, que até poucos meses criava cursores para praticamente tudo, você deve lembrar que cursores (explícitos) consomem muitos recursos do servidor, facilitando a ocorrência de deadlocks que poderiam ser evitados.

Vamos falar sobre um pouquinho de teoria antes do exemplo prático...

Primeiro, vamos definir um cursor como um arquivo temporário que armazena e controla as linhas retornadas de um comando select... Creio que esta definição gere algumas polêmicas, mas para a minha explicação esta definição ajudará bastante.

No Oracle, temos dois tipos de cursores os cursores implícitos e os cursores explícitos. 

Vamos começar pelo mais simples deles, que você já usou milhares de vezes, que é o cursor implícito.

Todo comando de Insert, Delete, Update e Select (QUANDO RETORNA APENAS UMA LINHA) é tratado pelo Oracle como um cursor implícito.

Como o intuito deste artigo não é falar de todos os comandos DML e DDL, estaremos focados nos cursores explícitos!

Estes cursores precisam ser declarados e os dados retornados da consulta são acessados através de variáveis.

Vamos dividir a criação de cursores em quatro passos básicos:

1.       Declaração;

2.       Abertura;

3.       Atribuição dos valores às variáveis;

4.       Fechamento.

Vou resumir o que acontece em cada uma das etapas...

Na declaração do cursor atribuímos um nome a ele, e um comando SELECT. Quando este cursor é aberto, o comando select é executado. Com o cursor aberto podemos atribuir valores retornados pelo select às variáveis, manipulá-las e então fechar o cursor para liberar os recursos do servidor.

Você pode criar diversos cursores, mas deve estar ciente que é preciso tomar cuidado com a memória alocada para eles.

Outra coisa bem legal sobre os cursores é que eles podem receber parâmetros, e estes parâmetros podem ser inicializados com um valor default.

Agora que você já conhece um pouquinho melhor os cursores vamos criar um exemplo. Para isso criei uma procedure e comentei cada passo.

create or replace procedure PrcTesteCursor

As

       --Declarando as variáveis que serão manipuladas

       vID int;

       vNome varchar2(100);

 

       --Criando o cursor que fará um select na tabela de clientes...

        cursor cC1 is

       SELECT ID, NOME FROM TBLCLIENTE ORDER BY ID;

      

begin

       --Abrindo o cursor

       open cC1;

                 

       --instrução de início do loop

       loop

            dbms_output.put_line('********************************************************');

                  

            --Atribuindo o retorno da consulta, às variáveis

            fetch cC1 into vID, vNome;

           

            /*

           *** %RowCount

           Este atributo retorna o número da linha em que o cursor está.

           */

           dbms_output.put_line('Estou "varrendo" a linha ' || cC1%rowcount );

           

         

            --Incluindo uma condição para saída do loop

           

            /*

            *** EXIT-WHEN

            estas keywords são usadas para testar de uma determinada condição é verdadeira,

            no caso do exemplo abaixo, o loop será executado, até que não existam itens

            dentro do cursor

           

            *** %NotFound

            este é um atributo do cursor que retorna um booleano ( seu valor default é true)

            indicando se existem itens dentro do cursor*/

            exit when cC1%notfound;

      

            --Neste exemplo eu irei escrever o valor das variáveis somente...

            dbms_output.put_line('ID: ' || vID);

            dbms_output.put_line('Nome: ' || vNome);

           

            /*

            *** %Found

            Este atributo é o oposto no atributo %NotFound, logo ele verifica se existem

            itens no cursor

            */

            if (cC1%found) then

                dbms_output.put_line('Usando o atributo "%Found" para verificar se existem registros no cursor');

            end if;

           

           

       --instrução para finalizar o loop    

       end loop;

      

       --Fechando o cursor para disponibilizar os recursos que estavam sendo utilizados

       close cC1;

      

      /*

      *** ; %IsOpen

      Este atributo verifica se o cursor esta aberto.

      */  

      if (cC1%isopen) then

          dbms_output.put_line('O cursor está aberto!');

      else

           dbms_output.put_line('O cursor foi fechado com sucesso!');

      end if;

           

end ;

Executando esta procedure obtive o seguinte resultado:

********************************************************

Estou "varrendo" a linha 1

ID: 2

Nome: Adonirandina

Usando o atributo "%Found" para verificar se existem registros no cursor

********************************************************

Estou "varrendo" a linha 2

ID: 3

Nome: Rivadaviana

Usando o atributo "%Found" para verificar se existem registros no cursor

********************************************************

Estou "varrendo" a linha 3

ID: 4

Nome: Carrolindini

Usando o atributo "%Found" para verificar se existem registros no cursor

********************************************************

Estou "varrendo" a linha 4

ID: 5

Nome: Adalgiso

Usando o atributo "%Found" para verificar se existem registros no cursor

********************************************************

Estou "varrendo" a linha 5

ID: 6

Nome: Braulinildo

Usando o atributo "%Found" para verificar se existem registros no cursor

********************************************************

Estou "varrendo" a linha 6

ID: 7

Nome: Rubélinja

Usando o atributo "%Found" para verificar se existem registros no cursor

********************************************************

Estou "varrendo" a linha 6

O cursor foi fechado com sucesso!

Este é o primeiro artigo de uma série que estou escrevendo sobre os cursores…

No próximo arigo (que sairá rapidinho…) vamos falar sobre as outras estruturas de repetição (LOOP) em cursores.

Em caso de qualquer dúvida, não exitem em entrar em contato comigo!!! Meu email é dani@wbsoft.com.br .

Abraços,

Danielle