Cursores são áreas compostas de linhas e colunas armazenadas em memória que servem para armazenar o resultado de uma seleção que retorna nenhuma, uma ou diversas linhas. Os cursores, no banco de dados Oracle podem ser explícitos e implícitos, mas no momento irei abordar somente os cursores explícitos. Com o uso de cursores é possível selecionar um conjunto de linhas e manipular o resultado desta consulta linha a linha, dentro de um código PL/SQL (Program Language SQL), como stored procedures, triggers e código escritos dentro de ferramentas Oracle como o Developer, Designer ou Discoverer.
O cursor deve ser declarado na cláusula DECLARE de um código PL/SQL:
CURSOR nome_do_cursor (Relação_de_Parâmetros) IS
SELECT ...
[FOR UPDATE OF colunas]
Relação_de_Parâmetros pode ter o seguinte formato:
Nome_do_Parametro tipo_de_dado {:= / DEFAULT} valor_inicial
Após sua declaração, os cursores podem ser manipulados de forma extensa ou de forma resumida. Quando se utiliza a forma extensa, que é menos recomendada, os seguintes comandos são utilizados em combinação com uma estrutura de looping:
- OPEN — abre o cursor, executando a consulta (comando SELECT) relacionada ao cursor, preenchendo parte de uma área de memória conhecida como private SQL area. Nesse momento, o ponteiro do cursor estará indicando o primeiro dos registros resultantes da consulta. A partir de então, para acessar dados desse cursor, o banco não será novamente acessado, pois todos os registros estarão disponíveis em memória após a execução do comando OPEN. Caso o cursor receba parâmetros é neste momento que os mesmos serão repassados.
- FETCH — disponibiliza a linha corrente do cursor para as variáveis correspondentes e posiciona o ponteiro na próxima linha do cursor. As linhas armazenadas no cursor somente poderão ser processadas quando seu conteúdo for transferido para variáveis que possam ser manipuladas no PL/SQL.
- CLOSE — fecha o cursor. Após sua manipulação, o cursor deve ser fechado com o comando CLOSE, para que a área de memória ocupada pelo resultado da consulta gerado por ele seja liberada.
Na forma reduzida, por sua vez, os comandos anteriores são substituídos pelo comando FOR unicamente:
- FOR — controla de modo completo a acesso ao cursor, substituindo os três comandos anteriores, executando, automaticamente as seguintes ações:
- cria a variável (do tipo registro) que irá receber os dados. Essa variável não deverá ser explicitamente declarada (DECLARE);
- abre o cursor;
- realiza a cópia das linhas uma a uma (FETCH), a cada iteração do comando;
- controla o final do cursor, e
- fecha o cursor.
A cada iteração do loop o ponteiro vai avançar pelos registros selecionados, começando sempre pelo primeiro, no qual estará posicionado na primeira iteração do comando FOR.
A seguir apresento um exemplo e a estrutura comparativa entre as duas formas de se trabalhar com cursores.
Declare
Cursor Cur_Cli Is
Select cd_cliente, nm_cliente
From Cliente;
Reg_Cli Cur_Cli%Rowtype;
Begin
Open Cur_Cli;
Loop
Fetch Cur_Cli
Into Reg_Cli;
Exit When
Cur_Cli%NotFound;
Dbms_Output.Put_Line
(Reg_Cli.nm_cliente);
End Loop;
Close Cur_Cli;
End;
Declare
Cursor Cur_Cli Is
Select cd_cliente, nm_cliente
From Cliente;
Begin
For Reg_Cli in Cur_Cli
Loop
Dbms_Output.Put_Line
(Reg_Cli.nm_cliente);
End Loop;
End;
Abaixo é possível ver a comparação entre o uso de uma estrutura expandida e uma simplificada. Repare na forma expandida, as linhas em vermelho que são suprimidas ao optar-se pela forma simplificada utilizando o comando FOR.