Cursores
Published: 2023-11-10 19:09:45


**Introdução:**
 
Cursores são elementos importantes na programação de banco de dados Oracle e em outros sistemas gerenciadores de banco de dados. Eles atuam de forma essencial com consultas e processamento de registros no seu banco de dados. O Cursor é uma ferramenta que permite a seleção, iteração e manipulação de dados dentro de tabelas. Ele pode ser visto como um ponteiro ou uma estrutura de controle que nos dá acesso aos resultados de uma query/consulta SQL, com isso, podemos atualizar informações, buscar por registros em tabelas, procurar por resultados e realizar operações de manipulação  dentro do banco de dados. 
Podemos ver o banco de dados como uma biblioteca gigante, onde é armazenado vários livros em várias estantes, onde ali é guardado informações importantes para uma empresa, os cursores nesse caso atuariam como um bibliotecário, onde ele te daria acesso aos livros e faria uma manipulação cuidadosa dos livros em cada estante representada. Os cursores auxiliam na implementação de lógica de negócios no Oracle, eles podem ser classificados como cursores implícitos e explícitos como veremos a seguir. É uma forma aprimorada de utilização do SQL na PL/SQL, uma alternativa ao uso de variáveis, pois com os cursores não é necessário a declaração de muitas variáveis e a execução de várias queries e loops, toda essa informação será armazenada no próprio cursor.
 
**Definição:**

Um cursor em bancos de dados é uma estrutura que ajuda na navegação e manipulação de conjuntos de resultados. Nas operações de banco de dados relacional, as operações acontecem em conjuntos completos de linhas que atendem as condições do comando WHERE quando se tem uma instrução SELECT. Em situações de aplicativos interativos e online, pode ser ineficiente trabalhar com conjunto completo de resultados como uma única unidade, esses necessitam trabalhar por linha ou por pequenos blocos de linha uma por vez, e os cursores auxiliam exatamente nisso. 
Um cursor é implementado por meio de uma biblioteca de cursores, geralmente é um software no sistema de banco de dados ou a uma API de acesso aos dados, essa biblioteca gerencia de forma simultânea os atributos dos dados que são retornados, como a posição no conjunto de resultados, o número de linhas retornadas e a opção de progresso ou não no conjunto de resultados. 
O cursor é como um indicador de posição no conjunto de resultados, que nos permite executar as operações linha por linha, com ou sem retorno da tabela original, eles vão retornar esse conjunto de resultado de acordo com as tabelas do banco de dados. Ele ajuda quando precisamos que o resultado seja feito linha por linha em vez de um conjunto de resultados de uma vez só, com os cursores, posso especificar e indicar a posição atual no conjunto de resultados, recuperar linha com base na posição atual, modificar seus dados, definir níveis diferentes de prioridade para as alterações feitas. 
Existem dois tipos de cursores no Oracle Database, os implícitos e explícitos.
 
**Cursores Implícitos:**

 São criados automaticamente pelo Oracle em operações DML no banco de dados quando são executadas, são capazes de buscar apenas uma linha por vez, eles não podem ser nomeados e por isso não podem ser controlados ou citados em outro lugar do código, apenas nos referir ao cursor mais recente por meio de seus atributos. Eles são mais vulneráveis a erros, possuem menos controle pragmático e podem ser menos flexíveis. 

**Cursores Explícitos:**

 São criados de forma manual pelo usuário, eles podem buscar por várias linhas, menos suscetíveis a erros, contém maior controle sobre as operações, eles possuem mais flexibilidade em comparação aos cursores implícitos, mas exigem um pouco mais de esforço para configurar. 

**SINTAXE:**

 `-- Declaração
DECLARE FuncionarioCursor CURSOR FOR   SELECT 
[Id],
[Desempenho]
FROM 
dbo.Funcionario
ORDER BY 
[Nome] 
-- Inicialização
OPEN FuncionarioCursor 
-- Variáveis
DECLARE @Id INT 
DECLARE @Desempenho INT 
-- Leitura da primeira linha do cursorFETCH NEXT FROM FuncionarioCursor   INTO @Id, @Desempenho 
-- Início do laço
WHILE @@FETCH_STATUS = 0  BEGIN  
-- Operações
IF @Desempenho >= 90
EXEC dbo.Promover @Id
ELSE IF @Desempenho >= 70 EXEC dbo.Bonificar @Id
-- Leitura da próxima linha do cursor
FETCH NEXT FROM FuncionarioCursor   INTO @Id, @Desempenho 
END   
-- Encerramento
CLOSE FuncionarioCursor
DEALLOCATE FuncionarioCursor`


**Vantagens do uso dos cursores:**
 
-     Controle de Navegação: 
Cursores fornecem um meio de navegação e registros individualmente em um conjunto de resultados, nos ajudando em operações especificas em cada linha do código.
 
-     Processamento de Linha a Linha:  
Quando há necessidade de processamento de dados linha a linha, principalmente em casos em que se depende do estado ou valores específicos de cada linha, os cursores podem nos ajudar.
 -     Manipulação de Dados Complexa:  
Manipulação de dados complexos onde se precisa de mais controle durante a execução. Desvantagens do uso dos cursores: 
-     Consumo de Recursos:  
Os cursores exigem consumo de recursos, como memória e CPU, pelo motivo de grandes conjuntos de resultados sendo processados linha a linha 
-     Desempenho: 
Influencia no desempenho em casos de grandes conjuntos de dados, em muitos casos as operações podem ser mais eficazes do que operações linha a linha 
-     Complexidade de Código:  
Aumentando a complexidade do código devido aos cursores, torna o programa mais difícil de ser entendido e mantido por outros desenvolvedores pelo uso de cursores. 
-     Bloqueio de Recursos: 
Podem resultar em bloqueio de recursos temporários, isso pode gerar problemas de concorrência e afetar o desempenho geral do sistema.

**Exemplos de aplicações no mercado** 

Relatórios Customizados:
Empresas muitas vezes precisam criar relatórios customizados, onde a estrutura dos dados varia e não pode ser gerada por consultas simples. Os cursores podem ser usados para percorrer os resultados de consultas mais complexas e montar relatórios personalizados.

Processamento de Dados em Lote:
Em processos de ETL (Extract, Transform, Load) ou durante a migração de dados, os cursores podem ser usados para percorrer grandes conjuntos de dados e realizar transformações específicas, como normalização de dados, aplicação de regras de negócios ou padronização.

Manutenção de Dados Específicos:
Em cenários onde é necessário aplicar atualizações, exclusões ou inserções de dados com base em regras específicas e complexas, os cursores permitem processar registros individualmente de acordo com essas regras.

Processamento de Transações Financeiras:
Em setores financeiros, especialmente para cálculos ou processamento de transações que requerem lógicas detalhadas para cada registro, os cursores podem ser úteis para iterar através dos registros e aplicar cálculos financeiros.

Validação de Dados:
Durante processos de auditoria ou validação de dados, os cursores podem ajudar a percorrer os registros em busca de inconsistências ou para aplicar validações específicas em cada linha.

**Conclusão:**

Os cursores são ferramentas poderosas para manipular dados linha por linha, trazendo flexibilidade para lidar com situações específicas. No entanto, em termos de performance, eles perdem para outras formas de controlar dados, e a manutenção de código com cursores pode ser mais trabalhosa devido à quantidade de detalhes.
Muitas vezes, é viável substituir cursores por operações que lidam com conjuntos de dados de uma vez. No entanto, é comum encontrar o uso de cursores quando os desenvolvedores não estão familiarizados com estratégias mais eficientes para lidar com bancos de dados, deixando de usar recursos como joins em atualizações ou exclusões, ou aproveitar os resultados de selects para inserções.
A recomendação principal é evitar o uso de cursores sempre que possível. Quando não houver alternativas, é fundamental implementá-los com cuidado, levando em consideração o impacto no desempenho e na manutenção do código.




**Tutorial Prático:** Utilizando Cursores no Oracle Database

**Introdução**

Neste tutorial, você aprenderá a utilizar cursores no Oracle Database para navegar e manipular conjuntos de resultados. Os cursores são ferramentas essenciais para processar dados de forma eficiente em operações linha a linha. Abordaremos tanto cursores implícitos quanto explícitos, com exemplos práticos para ilustrar seu uso.

**Pré-requisitos**

Certifique-se de ter acesso a um ambiente Oracle Database e a permissões adequadas para criar e executar cursores.

**Conteúdo do Tutorial**

**1.Cursores Implícitos - Navegação Simples:**
**Objetivo:** Demonstraremos como usar cursores implícitos para navegar por um conjunto de resultados simples.

**Exemplo de Código:**

SQL
```
-- Declaração Implícita
DECLARE
  v_nome VARCHAR2(50);
BEGIN
  FOR rec IN (SELECT nome FROM funcionarios) LOOP
    v_nome := rec.nome;
    -- Operações com v_nome
  END LOOP;
END;
```
**2.Cursores Explícitos - Atualização Condicional:**
**Objetivo:** Criaremos um cursor explícito para percorrer funcionários e atualizar salários com base em condições específicas.

**Exemplo de Código:**

SQL
```
-- Declaração Explícita
DECLARE
  CURSOR c_funcionarios IS
    SELECT id, salario FROM funcionarios FOR UPDATE;
  v_id funcionarios.id%TYPE;
  v_salario funcionarios.salario%TYPE;
BEGIN
  FOR rec IN c_funcionarios LOOP
    v_id := rec.id;
    v_salario := rec.salario;

    -- Lógica de Atualização Condicional
    IF v_salario < 5000 THEN
      UPDATE funcionarios SET salario = salario * 1.1 WHERE id = v_id;
    END IF;
  END LOOP;
  COMMIT;
END;
```
**3. Scrolling Cursors(cursores de rolagem) - Movimentação Bidirecional:**

**Objetivo:** Exploraremos cursores explícitos com capacidade de movimentação bidirecional.

**Exemplo de Código:**

SQL
```
-- Declaração com Scrolling
DECLARE
  CURSOR c_produtos IS
    SELECT nome FROM produtos ORDER BY nome
    FOR UPDATE OF nome;
  v_nome produtos.nome%TYPE;
BEGIN
  OPEN c_produtos;
  FETCH c_produtos INTO v_nome; -- Posicionamento inicial

  -- Movimentação Bidirecional
  LOOP
    -- Processamento
    EXIT WHEN c_produtos%NOTFOUND;
    FETCH c_produtos INTO v_nome;
  END LOOP;

  CLOSE c_produtos;
END;
```
**4. Manipulação de Dados Complexa - Uso de Funções:**
**Objetivo:** Utilizaremos cursores para aplicar funções complexas aos dados.

**Exemplo de Código:**

sql
```
-- Declaração com Funções
DECLARE
  CURSOR c_clientes IS
    SELECT id, saldo FROM clientes;
  v_id clientes.id%TYPE;
  v_saldo clientes.saldo%TYPE;
BEGIN
  FOR rec IN c_clientes LOOP
    v_id := rec.id;
    v_saldo := rec.saldo;

    -- Aplicação de Função
    UPDATE clientes SET saldo = minha_funcao(v_saldo) WHERE id = v_id;
  END LOOP;
  COMMIT;
END;
```
**5.** Relatório Customizado - Construção Dinâmica:
**Objetivo:** Criaremos um cursor dinâmico para gerar um relatório customizado.

**Exemplo de Código:**

SQL
```
-- Cursor Dinâmico para Relatório
DECLARE
  v_colunas VARCHAR2(1000) := 'id, nome, salario';
  v_query VARCHAR2(1000) := 'SELECT ' || v_colunas || ' FROM funcionarios';
  CURSOR c_relatorio IS EXECUTE IMMEDIATE v_query;
  v_id funcionarios.id%TYPE;
  v_nome funcionarios.nome%TYPE;
  v_salario funcionarios.salario%TYPE;
BEGIN
  OPEN c_relatorio;
  LOOP
    FETCH c_relatorio INTO v_id, v_nome, v_salario;
    EXIT WHEN c_relatorio%NOTFOUND;

    -- Processamento do Relatório
  END LOOP;
  CLOSE c_relatorio;
END;
```
**Conclusão:**

Este tutorial fornece uma base sólida para o uso de cursores no Oracle Database. Ao aplicar os conceitos aprendidos nos exemplos práticos, você poderá melhorar a eficiência e a flexibilidade de suas operações de banco de dados. Lembre-se de adaptar os exemplos às necessidades específicas do seu ambiente de trabalho.





Por: 

Ellen,
Philipe.

Referencias:
 
Leans.microsoft , Acervo Lima, Oracle, PostgreSQL, Microsoft SQL Server, Stack Overflow, Udemy, Redspark.