Cursor no Oracle- PL/SQL

Fala PessoAll,

Bom, verificando com o pessoal de algumas listas de e-mails sobre Oracle e um pessoal que trabalha aqui comigo no desenvolvimento Oracle, verifiquei que existem algumas dúvidas quanto a utilização de Cursores no desenvolvimento PL/SQL. Por este motivo, estarei mostrando aqui algumas formas de utilizarmos cursores e explicando algumas vantagens e desvantagens, claro… No meu ponto de vista!

Para os exemplos que irei fazer, vou usar uma tabela simples de clientes que pode ser criada e populada com o script abaixo:


create table clientes(codigo number(5), nome varchar2(50), cpf number(11));
insert into clientes (codigo, nome, cpf) values (1, 'CLIENTE 1 DA SILVA', 00100200301);
insert into clientes (codigo, nome, cpf) values (2, 'CLIENTE 2 DA SILVA', 00200200302);
insert into clientes (codigo, nome, cpf) values (3, 'CLIENTE 3 DA SILVA', 00300200303);
insert into clientes (codigo, nome, cpf) values (4, 'CLIENTE 4 DA SILVA', 00400200304);
insert into clientes (codigo, nome, cpf) values (5, 'CLIENTE 5 DA SILVA', 00500200305);
insert into clientes (codigo, nome, cpf) values (6, 'CLIENTE 6 DA SILVA', 00600200306);
insert into clientes (codigo, nome, cpf) values (7, 'CLIENTE 7 DA SILVA', 00700200307);
commit;

A primeira forma de utilizarmos um cursor é declarando ele na cláusula Declare do seu bloco PL/SQL. Esta utilização tem o nome de Cursor Explícito

Vamos ao exemplo de procedure que usa este recurso:


create or replace procedure entendendoCursor is
--Declarando o cursor
Cursor C_RetornaCliente is
Select codigo,
nome,
cpf
from clientes;

–Declarando variável que receberá cada linha retornada do cursor
rCli C_RetornaCliente%rowtype;

Begin
–Comando para abrir o cursor
Open C_RetornaCliente;

–Faz um laço para percorrer todas as linhas do cursor
Loop
–Lê a linha encontrada e coloca os valores na variável rCli.
Fetch C_RetornaCliente into rCli;
–“Avisa” para a rotina que caso não encontre mais nada, pode sair do laço.
Exit when C_RetornaCliente%notFound;

–Exibe na tela as informações do cliente
dbms_output.put_line(‘Código: ‘||rCli.codigo||’ Nome: ‘||rCli.nome||’ CPF: ‘||rCli.cpf);
End loop;

–Fecha o cursor.
Close C_RetornaCliente;
End;

Este exemplo percorre os registros encontrados no cursor e os exibe na tela.

Bom, na minha opinião esta é a forma mais “chata” de fazer, pois como pode ser observado, precisamos criar um cursor lá na área onde declaramos as variáveis que serão utilizadas no programa, depois temos que declarar uma outra variável que será do tipo rowtype do cursor (rowtype é quando você cria uma variável que irá receber os valores de acordo com o que for retornado no cursor, e acessamos os campos depois assim: Var.Campo, podemos ver isso no código acima), depois temos que abrir o cursor, dar um fetch para colocar na variável e depois do uso fechar o cursor! Ufa! Cansei até de “falar” tudo isso!! Sem contar que você ao analisar uma rotina que seja grande (umas 3000 linhas por exemplo) onde suas declarações (inclusive seu cursor) está lá em cima do código e de repente você encontra um Open CursorX;… Nossa! Lá vamos nós fazer uma viagem até a parte de cima da aplicação, encontrar a declaração deste cursor pra poder entender o que ele faz e etc.

Torna muito trabalhoso para manutenção, na minha opinião!

Uma outra forma de utilizar os cursores é colocando a query na hora em que vamos de fato utilizar os dados que ela retorna, ou seja, no meio da aplicação mesmo. Chamamos isso de Cursor Implícito.

Repetindo o caso acima só que desta forma, teríamos a nossa procedure da seguinte forma:


create or replace procedure entendendoCursor is
Begin
--Faz o Loop já informando a variável de retorno (rCli neste caso) e o select que será executado
For rCli in (Select codigo,
nome,
cpf
from clientes)
Loop
--Exibe na tela as informações do cliente
dbms_output.put_line('Código: '||rCli.codigo||' Nome: '||rCli.nome||' CPF: '||rCli.cpf);
End loop;
End;

Mais simples não? No primeiro exemplo temos 29 linhas e no segundo nossa procedure cai para 12 linhas. Além de escrever menos, fica bem mais simples de ler em caso de um código grande e além de tudo, não precisamos ficar com a responsabilidade de abrir cursor, ler cursor, coloca na variável, verifica se acabou os dados para sair do laço (%notFound), fecha cursor e etc, o banco faz tudo isso para nós, por isso que chamamos de Cursor Implícito, porque todo esse controle é feito pelo banco digamos que “por baixo dos panos”!

Bom, esta é minha humilde opinião quanto ao uso de cursores, lembrando que cada um tem sua forma de fazer, creio eu que a forma mais simples sempre é a melhor para fazer e claro, para dar manutenção posteriormente. Lembro ainda que existem outras formas de realizarmos selects nos nossos programas PL/SQL, podemos usar query´s dinâmicas e etc, quem manda é o freguês!!

Lembro ainda que é extremamente interessante comentar nossos códigos, escrever de forma de se algum outro desenvolvedor pegue para dar manutenção consiga entender o que está sendo feito a cara passo do nosso código.

Espero que gostem e comentem!!

Até a próxima!

Atc.
Gerson Júnior

8 ideias sobre “Cursor no Oracle- PL/SQL

  1. rodrigo

    Boa noite, amigo
    Será q vc poderia me ajudar.
    Fiz os comandos que vc escreveu, mas não apresenta nada.
    Abaixo segue o código que fiz, será que fiz algo errado? Obrigado.

    create or replace procedure entendendoCursor is
    Cursor C_RetornaCliente is
    Select codigo,nome,cpf from clientes;
    rCli C_RetornaCliente%rowtype;
    Begin
    Open C_RetornaCliente;
    Loop
    Fetch C_RetornaCliente into rCli;
    Exit when C_RetornaCliente%notFound;
    dbms_output.put_line(‘Código: ‘||rCli.codigo||’ Nome: ‘||rCli.nome||’ CPF: ‘||rCli.cpf);
    End Loop;
    Close C_RetornaCliente;
    End;
    /

    Responder
    1. oracle Autor do post

      Olá Rodrigo.

      Obrigado pela visita…
      Cara, sua procedure está certinha… rodou perfeito!
      Só vejo duas opções para não aparecer nada:

      1 – Sua tabela CLIENTES não tem dado nenhum.
      2 – Você está rodando pelo SQL PLUS e não setou o SERVEROUTPUT para ON.

      Fiz o seguinte passo a passo para testar aqui, e como pode ver, funcionou corretamente:

      SQL> CONN DBTUNING/DBTUNING@ORCL
      Conectado.
      SQL> create or replace procedure entendendoCursor is
      2 Cursor C_RetornaCliente is
      3 Select codigo,nome,cpf from clientes;
      4 rCli C_RetornaCliente%rowtype;
      5 Begin
      6 Open C_RetornaCliente;
      7 Loop
      8 Fetch C_RetornaCliente into rCli;
      9 Exit when C_RetornaCliente%notFound;
      10
      11 dbms_output.put_line(‘Código: ‘||rCli.codigo||’ Nome: ‘||rCli.nome||’ CPF: ‘||rCli.cpf);
      12 End Loop;
      13 Close C_RetornaCliente;
      14 End;
      15 /

      Procedimento criado.

      SQL> CREATE TABLE CLIENTES(CODIGO NUMBER, NOME VARCHAR2(10), CPF NUMBER);

      Tabela criada.

      SQL> INSERT INTO CLIENTES VALUES (1, ‘GERSON JR’, ‘12345678909’);

      1 linha criada.

      SQL> INSERT INTO CLIENTES VALUES (2, ‘TESTE PROC’, ‘22222222222’);

      1 linha criada.

      SQL> INSERT INTO CLIENTES VALUES (3, ‘PROCEDURE’, ‘55555555555’);

      1 linha criada.

      SQL> COMMIT;

      Commit concluÝdo.

      SQL> SET SERVEROUTPUT ON
      SQL> BEGIN
      2 entendendoCursor;
      3 END;
      4 /
      Código: 1 Nome: GERSON JR CPF: 12345678909
      Código: 2 Nome: TESTE PROC CPF: 22222222222
      Código: 3 Nome: PROCEDURE CPF: 55555555555

      Procedimento PL/SQL concluÝdo com sucesso.

      SQL>

      Responder

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *