Cursor em 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.
Bom post. Melhor explicado do que outros artigos sobre cursores dos sites “conhecidos”. Ex: http://www.criarweb.com/artigos/cursores-sql.html. Esse é o primeiro site retornado pelo google na pesquisa: CURSORES + SQL.
Parabens!!…..muito simple.
Parabéns pela forma didática que vc explicou, ficou parecendo bem “fácil”, otimo.
Sugiro agora uma pauta falando de manipulacao de datas e horas, que no Oracle parece bem complicado.
Mais uma vez, parabéns..
O b r i g a d o .
gostei da matéria pois estou fazendo PL/SQL na universidade, se puder colocar mais matérias seria bom , agradeço.