Oracle PL/SQL Packages como criar Pacotes PL/SQL no Oracle

Neste material, você aprenderá sobre:

  • Criação e Estrutura de Pacotes
  • Instanciação e Inicialização de Pacotes
  • Pacotes SERIALLY_REUSABLE

Os pacotes PL/SQL são uma poderosa ferramenta de organização e modularização de código no Oracle Database. Eles permitem agrupar procedimentos, funções, variáveis e outros objetos relacionados, proporcionando melhor gerenciamento de código e encapsulamento.

Lab 15.1: Criando Pacotes PL/SQL

Após este laboratório, você será capaz de:

  • Criar uma Especificação de Pacote
  • Implementar um Corpo de Pacote

Imagine um pacote PL/SQL como uma caixa de ferramentas bem organizada. Assim como uma caixa de ferramentas tem compartimentos para diferentes tipos de ferramentas, um pacote PL/SQL agrupa objetos relacionados, como procedimentos, funções e variáveis, em uma única unidade lógica.

Criando uma Especificação de Pacote

A especificação de pacote é como o rótulo na parte externa da caixa de ferramentas. Ela lista todas as ferramentas (ou, no nosso caso, objetos PL/SQL) que estão disponíveis para uso, sem mostrar os detalhes internos de como essas ferramentas funcionam.

Pense na especificação do pacote como um contrato entre o desenvolvedor do pacote e os usuários do pacote. Ela define claramente o que o pacote oferece, sem revelar como ele faz isso internamente.

Listing 15.1 Criando uma Especificação de Pacote

Vamos criar um pacote para gerenciar funcionários:

Por exemplo emp_mgmt_pkg_spec.sql:

Neste exemplo, estamos criando uma “caixa de ferramentas” chamada emp_mgmt_pkg para gerenciar funcionários. Observe como declaramos tipos personalizados (emp_record_type e emp_table_type) e três subprogramas públicos.

Explicação Detalhada:

  1. Tipos Personalizados:
    • emp_record_type: É como criar um molde personalizado para armazenar informações de um funcionário. Imagine-o como um formulário com campos específicos para cada detalhe do funcionário.
    • emp_table_type: Este é como um arquivo de fichas, onde cada ficha é um emp_record_type. Ele nos permite trabalhar com múltiplos funcionários de uma vez.
  2. Subprogramas Públicos:
    • get_employee: Esta função é como um localizador de funcionários. Você fornece um ID e ela retorna todas as informações daquele funcionário.
    • update_salary: Este procedimento é como um formulário de atualização de salário. Você informa o ID do funcionário e o novo salário, e ele faz a atualização.
    • get_department_employees: Esta função é como um relatório de departamento. Você informa o ID do departamento e ela retorna informações de todos os funcionários daquele departamento.

Implementando o Corpo do Pacote

O corpo do pacote é onde a mágica acontece. Se a especificação é o rótulo da caixa de ferramentas, o corpo é o interior da caixa, onde as ferramentas realmente estão e como elas funcionam.

Listing 15.2 Criando o Corpo do Pacote

Vamos implementar o corpo do nosso pacote:

Exemplo emp_mgmt_pkg_body.sql:

Explicação Detalhada:

  1. Cursor Privado:
    • emp_cur: Este cursor é como um scanner interno que lê informações de funcionários de um departamento específico. É privado, o que significa que só pode ser usado dentro do pacote.
  2. Implementação de get_employee:
    • Esta função é como um robô de busca. Ele vai ao “arquivo” (tabela employees), procura a “ficha” do funcionário com o ID fornecido e retorna todas as informações.
    • Se não encontrar o funcionário, ele “grita” (lança um erro) dizendo que o funcionário não foi encontrado.
  3. Implementação de update_salary:
    • Este procedimento é como um formulário de atualização automática. Ele preenche o novo salário na “ficha” do funcionário.
    • Se não conseguir encontrar a “ficha” para atualizar, ele também “grita” um erro.
    • O COMMIT no final é como carimbar “APROVADO” no formulário, tornando a mudança permanente.
  4. Implementação de get_department_employees:
    • Esta função é como um assistente que pega todas as “fichas” de funcionários de um departamento e as organiza em uma pasta.
    • Ele usa o cursor emp_cur para “escanear” cada ficha e a coloca na “pasta” (v_emp_table).

Analogia Final

Pense no pacote como um departamento de RH bem organizado:

  • A especificação do pacote é como o balcão de atendimento, onde você vê quais serviços estão disponíveis.
  • O corpo do pacote é o escritório nos fundos, onde o trabalho real acontece.
  • As funções e procedimentos são como os diferentes serviços oferecidos pelo RH (buscar informações de funcionários, atualizar salários, listar funcionários de um departamento).
  • Os tipos personalizados são como os formulários padronizados que o RH usa para manter tudo organizado.

Ao usar pacotes, você está essencialmente criando um “mini-aplicativo” dentro do banco de dados, com uma interface clara (especificação) e uma implementação bem organizada (corpo), facilitando a manutenção e o uso do código.

Lab 15.2: Instanciação e Estado do Pacote

Após este laboratório, você entenderá:

  • Como os pacotes são instanciados
  • O conceito de estado do pacote

Instanciação de Pacotes

Imagine um pacote PL/SQL como um robô assistente sofisticado. Quando você liga esse robô pela primeira vez em uma sessão de banco de dados, ele passa por um processo de “inicialização” – isso é o que chamamos de instanciação do pacote.

O Processo de Instanciação

  1. Carregamento: O Oracle carrega o pacote na memória.
  2. Inicialização de Variáveis: Todas as variáveis públicas do pacote são inicializadas com seus valores padrão ou especificados.
  3. Execução do Código de Inicialização: Se houver algum código de inicialização no corpo do pacote (fora de qualquer procedimento ou função), ele é executado.

Analogia: Pense nisso como ligar seu smartphone pela manhã. Ele carrega o sistema operacional (carregamento do pacote), configura suas configurações padrão (inicialização de variáveis) e verifica notificações ou atualizações pendentes (execução do código de inicialização).

Estado do Pacote

O estado do pacote refere-se aos valores atuais de suas variáveis e ao status de seus cursores em um determinado momento. É como a “memória” do nosso robô assistente.

Características do Estado do Pacote:

  1. Persistência na Sessão: O estado persiste durante toda a sessão do usuário.
  2. Compartilhamento: Todos os usuários da sessão compartilham o mesmo estado do pacote.
  3. Reinicialização: O estado é reiniciado quando a sessão termina ou quando o pacote é recompilado.

Analogia: Imagine o estado do pacote como o bloco de notas do nosso robô assistente. Ele mantém anotações (valores de variáveis) durante todo o dia de trabalho (sessão), e todos que interagem com o robô veem as mesmas anotações. No final do dia (fim da sessão), o bloco de notas é limpo para o próximo dia.

Vamos ver um exemplo prático:

Por exemplo pkg_state_demo.sql:

Explicação Detalhada:

  1. Variável de Pacote (v_count):
    • É como um contador que nosso robô assistente mantém.
    • Inicializada com 0 quando o pacote é instanciado.
  2. Procedimento increment_count:
    • É como um botão no robô que, quando pressionado, aumenta o contador em 1.
  3. Função get_count:
    • É como pedir ao robô para mostrar o valor atual do contador.
  4. Código de Inicialização:
    • A mensagem “Pacote state_demo_pkg inicializado.” é exibida quando o pacote é instanciado pela primeira vez.
  5. Bloco de Teste:
    • Mostra como o estado do pacote (o valor de v_count) muda e persiste entre chamadas de procedimentos.

Implicações Práticas do Estado do Pacote

  1. Compartilhamento de Dados: Útil para manter informações que precisam ser compartilhadas entre diferentes partes de uma aplicação.
  2. Cuidado com Concorrência: Se múltiplos usuários estão alterando o estado do pacote simultaneamente, pode haver problemas de concorrência.
  3. Desempenho: Manter estado pode melhorar o desempenho, evitando a necessidade de recuperar informações repetidamente.
  4. Limpeza: É importante considerar a limpeza ou reinicialização do estado quando necessário, especialmente em aplicações de longa duração.

Analogia Final

Pense no estado do pacote como um quadro branco em uma sala de reuniões:

  • O quadro é limpo no início do dia (instanciação do pacote).
  • Durante o dia, várias pessoas podem escrever e ler informações do quadro (manipulação do estado do pacote).
  • Todos na sala podem ver o que está escrito (compartilhamento do estado).
  • No final do dia, o quadro é limpo novamente (fim da sessão ou recompilação do pacote).

Entender o estado do pacote é crucial para desenvolver aplicações PL/SQL eficientes e confiáveis, permitindo que você aproveite ao máximo o compartilhamento de dados e a persistência de informações durante uma sessão de banco de dados.

Lab 15.3: Pacotes SERIALLY_REUSABLE

Após este laboratório, você saberá:

  • Como criar e usar pacotes SERIALLY_REUSABLE
  • As diferenças entre pacotes regulares e SERIALLY_REUSABLE

Conceito de Pacotes SERIALLY_REUSABLE

Pacotes SERIALLY_REUSABLE são uma variação especial dos pacotes PL/SQL padrão, projetados para otimizar o uso de memória em cenários específicos.

Analogia: Imagine um restaurante fast-food muito movimentado. Em um restaurante normal (pacote padrão), cada cliente teria sua própria mesa reservada durante toda a refeição, mesmo depois de terminar de comer. Em um restaurante SERIALLY_REUSABLE, assim que um cliente termina e sai, a mesa é imediatamente limpa e disponibilizada para o próximo cliente.

Características dos Pacotes SERIALLY_REUSABLE

  1. Liberação de Memória: Após cada “chamada” ao pacote, a memória é liberada.
  2. Reinicialização: O pacote é reinicializado a cada nova chamada.
  3. Não Persistência: O estado não persiste entre chamadas.

Criando um Pacote SERIALLY_REUSABLE

Para criar um pacote SERIALLY_REUSABLE, usamos a pragma SERIALLY_REUSABLE tanto na especificação quanto no corpo do pacote.

Por examplo serially_reusable_demo.sql:

Explicação Detalhada

  1. PRAGMA SERIALLY_REUSABLE:
    • Esta diretiva informa ao Oracle que o pacote deve ser tratado como serialmente reutilizável.
    • É como colocar um aviso de “Limpar Mesa Após Uso” em cada mesa do nosso restaurante fast-food.
  2. v_last_employee:
    • Esta variável armazena o ID do último funcionário processado.
    • Em um pacote normal, este valor persistiria entre chamadas. Aqui, ele é “esquecido” após cada uso.
  3. set_last_employee e get_last_employee:
    • Estes são como o garçom que anota o pedido (set) e traz a comida (get).
    • Em um pacote SERIALLY_REUSABLE, é como se o garçom “esquecesse” o pedido anterior assim que o entrega.
  4. Bloco de Teste:
    • O primeiro bloco define um valor e o recupera imediatamente – isso funciona como esperado.
    • O segundo bloco tenta recuperar o valor definido anteriormente, mas ele não existe mais.

Quando Usar Pacotes SERIALLY_REUSABLE

  1. Alto Volume de Transações: Ideal para aplicações com muitas transações curtas.
  2. Memória Limitada: Útil quando a memória do servidor é uma preocupação.
  3. Sem Necessidade de Estado Persistente: Quando você não precisa manter informações entre chamadas.

Analogia Expandida

Imagine uma linha de produção em uma fábrica:

  • Pacote Padrão: Cada trabalhador tem sua própria estação de trabalho permanente com todas as ferramentas.
  • Pacote SERIALLY_REUSABLE: Os trabalhadores compartilham estações de trabalho. Cada um usa a estação, completa sua tarefa, limpa tudo e passa para o próximo.

Considerações Importantes

  1. Desempenho: Pode ser mais lento para operações frequentes devido à reinicialização constante.
  2. Debugging: Pode ser mais difícil de debugar devido à natureza transitória do estado.
  3. Limitações: Não pode ser usado em triggers ou referenciado diretamente em SQL.

Atenção!

Pacotes SERIALLY_REUSABLE não são adequados para todas as situações. Use-os com cautela e apenas quando os benefícios de economia de memória superarem a necessidade de manter o estado entre chamadas.

Exercício Prático

Tente modificar o exemplo dado para incluir um contador que rastreie quantas vezes o pacote foi chamado. Observe como o contador se comporta diferentemente em um pacote SERIALLY_REUSABLE comparado a um pacote padrão.

Compreender os pacotes SERIALLY_REUSABLE adiciona uma ferramenta poderosa ao seu arsenal de desenvolvimento PL/SQL, permitindo otimizações de memória em cenários específicos de alto volume e baixa persistência de estado.

Atenção!

Pacotes SERIALLY_REUSABLE não podem ser referenciados em triggers ou diretamente em instruções SQL.

Comparação Detalhada: Pacotes Padrão vs. SERIALLY_REUSABLE

Para entender melhor as diferenças, vamos criar dois pacotes similares – um padrão e um SERIALLY_REUSABLE – e compará-los:

Por exemplo package_comparison.sql:

Análise do Resultado

Quando você executa este script, verá algo como:

Explicação

  1. Pacote Padrão:
    • O contador mantém seu valor (2) entre as chamadas.
    • É como um contador manual que você deixa na sua mesa; ele mantém o valor até que você o resete explicitamente.
  2. Pacote SERIALLY_REUSABLE:
    • O contador é reiniciado para 0 na nova chamada.
    • É como um contador digital que volta a zero automaticamente após cada uso.

Cenários de Uso

  1. Pacotes Padrão:
    • Ideal para manter estado entre chamadas.
    • Útil para caching de dados, contadores persistentes, ou manter informações de sessão.
    • Exemplo: Um pacote que mantém preferências do usuário durante uma sessão de aplicação web.
  2. Pacotes SERIALLY_REUSABLE:
    • Ideal para operações isoladas que não dependem de estado anterior.
    • Útil em ambientes com muitos usuários concorrentes onde a memória é uma preocupação.
    • Exemplo: Um pacote que processa transações bancárias individuais, onde cada transação é independente.

Considerações de Desempenho

  1. Overhead de Inicialização:
    • Pacotes SERIALLY_REUSABLE têm um pequeno overhead de reinicialização a cada chamada.
    • Em operações muito frequentes, isso pode impactar o desempenho.
  2. Uso de Memória:
    • Pacotes padrão consomem mais memória, especialmente com muitas sessões concorrentes.
    • Pacotes SERIALLY_REUSABLE são mais eficientes em termos de memória em larga escala.

Exercício Avançado

Tente criar um pacote SERIALLY_REUSABLE que simule um gerador de números de pedido. O pacote deve:

  1. Gerar um número de pedido único a cada chamada.
  2. Resetar o contador para 1 no início de cada dia.
  3. Usar a data atual como parte do número do pedido.

Dica: Você precisará combinar o uso de variáveis de pacote com funções de data do Oracle para alcançar este comportamento.

Conclusão

Pacotes SERIALLY_REUSABLE são uma ferramenta poderosa no arsenal do desenvolvedor PL/SQL, oferecendo uma maneira de otimizar o uso de memória em cenários específicos. No entanto, eles não são uma solução universal e devem ser usados com compreensão clara de suas implicações. A escolha entre pacotes padrão e SERIALLY_REUSABLE depende das necessidades específicas de sua aplicação, considerando fatores como persistência de estado, concorrência de usuários e requisitos de memória.

Scroll to Top