Trabalhando com Packages PL/SQL

Neste artigo apresentaremos a utilização de packages PL/SQL, que são áreas de armazenamento de sub-programas, constantes, dentre outros tipos suportados pela linguagem PL/SQL.

Um package é uma coleção de objetos PL/SQL agrupados logicamente sob o nome de pacote. Os packages podem incluir procedures, functions, cursores, declarações, tipos e também variáveis​​. Há inúmeras vantagens em coletar objetos em um package. Mais a frente serão vistos os benefícios de sua utilização.

Os packages geralmente possuem duas partes, uma que se refere a spec e a segunda parte que é o body. A spec é o que chamamos de interface para o package. É nela que declaramos os tipos, variáveis, constantes, exceções, cursores e subprogramas que poderão ser referenciados a partir de partes externas ao package. Por outro lado, no body definimos as consultas para os cursores e o código para os subprogramas. Em alguns casos pode ser que não haja a necessidade de se ter um body.

Em outras palavras, Package PL/SQL é um grupo de funções relacionadas, procedimentos, tipos, cursores, dentre outros. Os packages são como uma biblioteca, pois uma vez escrito é armazenado no banco de dados Oracle e pode ser usado por muitas aplicações.

De um certo modo, podemos imaginar a spec como sendo uma interface e o body como sendo uma caixa preta. Sabendo disso, podemos entender então que é possível depurar, aprimorar ou substituir bodies de um package sem precisar alterar as especificações do package. Para criar um spec de um package utilizamos a instrução SQL CREATE PACKAGE. E para a criação de um bod, utilizamos a instrução CREATE PACKAGE BODY.

A spec do package é a interface pública de suas aplicações. O público significa que a função armazenada, procedimentos, tipos, são acessíveis a partir de outras aplicações. Já o body contém o código que implementa as especificações do pacote.

O que podemos ter num package PL/SQL?

Vamos ver a seguir o que podemos definir em um pacote PL/SQL:

Quais as vantagens de utilização de packages PL/SQL?

A utilização de packages tem uma longa história no que diz respeito a engenharia de softwares, oferecendo características importantes de fácil manutenção, reutilização de código, muitas vezes em esforços dentro de uma equipe de desenvolvimento para o desenvolvimento de grandes sistemas. Apresentaremos então alguns dos principais pontos vantajosos na utilização de packages.

Os Packages param as dependências em cascata e evitam recompilações desnecessárias. Podemos pensar no seguinte exemplo, se alterarmos o body de uma function que está num package, o Oracle não irá recompilar outros subprogramas que chamam por esta function. Estes subprogramas só dependeram dos parâmetros e valores de retorno que serão declarados na especificação, então eles só são recompilados se houverem mudanças na spec e não quando as mudanças são no body.

Criando PL/SQL package specification

A especificação do package é necessário quando você cria um novo package. A especificação do package lista todos os objetos que são acessíveis ao público a partir de outras aplicações. A especificação do package também fornece as informações que os desenvolvedores precisam saber para usar a sua interface. Em suma, a especificação do package é a sua API.

Se a especificação do package não contém quaisquer funções armazenadas, procedures e nenhum código privado sendo necessário, então não precisamos ter um corpo para o package. Estes packages podem conter apenas as definições dos tipos e declaração de variáveis. Essas variáveis ​​são conhecidas como dados do pacote. O escopo dos dados é global para as aplicações. Devido a isso é necessário encapsular tudo que não seja necessário como público e fazer uso das funções gets e sets para ler e escrever os dados. Ao fazer isso, podemos evitar que os dados dos package sejam alterados de forma errônea.

De acordo com a Listagem 1, seguem as instruções de como criar um package sem o body.

Listagem 1. Criação do package sem o body, apenas com as specs

CREATE [OR REPLACE] PACKAGE package_name [ AUTHID { CURRENT_USER | DEFINER } ] { IS | AS } [definitions of public TYPES ,declarations of public variables, types, and objects ,declarations of exceptions ,pragmas ,declarations of cursors, procedures, and functions ,headers of procedures and functions] END [package_name];

A instrução CREATE PACKAGE é usada para definir uma nova especificação do pacote. Caso queiramos reconstruir o pacote existente, podemos usar a palavra-chave REPLACE em vez de CREATE. Na especificação do pacote podemos definir novos tipos, declarar variáveis ​​globais, tipos, objetos, exceções, cursores, procedimentos e funções.

De acordo com a Listagem 2, temos um exemplo de criação de uma nova especificação de pacote chamado funcionário. O pacote de funcionário contém duas funções: get_nomeCompleto() e get_salario() com base na identificação do funcionário.

Listagem 2. Criação do package funcionário

CREATE OR REPLACE PACKAGE funcionario AS // get nome completo do funcionario FUNCTION get_nomeCompleto(n_func_id NUMBER) RETURN VARCHAR2; // get salario do funcionario FUNCTION get_salario(n_func_id NUMBER) RETURN NUMBER; END funcionario;

Agora criaremos o corpo para o package, de acordo com a Listagem 3.

No body do package PL/SQL fica todo o código que implementa as funções armazenadas, procedures e cursores listados na especificação do package.

Listagem 3. Criação do body para o package funcionário

CREATE [OR REPLACE] PACKAGE BODY package_name { IS | AS } [definitions of private TYPEs ,declarations of private variables, types, and objects ,full definitions of cursors ,full definitions of procedures and functions] [BEGIN sequence_of_statements [EXCEPTION exception_handlers ] ] END [package_name];

A sintaxe é similar à da criação da spec, exceto pela palavra-chave BODY e o código implementado das especificações do package.

O corpo da package pode conter uma seção de inicialização do pacote opcional que aparece no final do corpo de package. As seções de inicialização das packages começam com a palavra-chave BEGIN e terminam com a seção do EXCEPTION ou a palavra-chave END que finaliza o pacote. A seção de inicialização do pacote é executada quando o aplicativo faz referência ao elemento do package pela primeira vez.

Agora que apresentamos o body do package, faremos um exemplo completo para o package funcionário iniciado anteriormente. Apresentamos o nosso exemplo na Listagem 4.

Listagem 4. Criação do exemplo completo de uma package com spec e body

/* Package funcionario body */ CREATE OR REPLACE PACKAGE BODY funcionario AS // get funcionário nomeCompleto FUNCTION get_nomeCompleto(n_func_id NUMBER) RETURN VARCHAR2 IS v_nomeCompleto VARCHAR2(46); BEGIN SELECT primeiro_nome || ',' || ultimo_nome INTO v_nomeCompleto FROM funcionarios WHERE empresa_id = n_func_id; RETURN v_nomeCompleto; EXCEPTION WHEN NO_DATA_FOUND THEN RETURN NULL; WHEN TOO_MANY_ROWS THEN RETURN NULL; END; // end get_nomeCompleto get salario FUNCTION get_salario(n_func_id NUMBER) RETURN NUMBER IS n_salario NUMBER(8,2); BEGIN SELECT salario INTO n_salario FROM funcionarios WHERE empresa_id = n_func_id; RETURN n_salario; EXCEPTION WHEN NO_DATA_FOUND THEN RETURN NULL; WHEN TOO_MANY_ROWS THEN RETURN NULL; END; END funcionario;

Ainda falta chamarmos nosso package, que será visto na Listagem 6. Para fazermos referência a nosso package utilizamos a seguinte notação mostrada na Listagem 5.

Listagem 5. Chamada do package

package_name.package_element

Listagem 6. chamando o package funcionário

SET SERVEROUTPUT ON SIZE 1000000; DECLARE n_salario NUMBER(8,2); v_nome VARCHAR2(46); n_func_id NUMBER := &empresa_id; BEGIN v_nome := funcionario.get_nomeCompleto(n_func_id); n_salario := funcionario.get_salario(n_func_id); IF v_nome IS NOT NULL AND n_salario IS NOT NULL THEN dbms_output.put_line('Funcionário: ' || v_nome); dbms_output.put_line('Recebe salário = ' || n_salario); END IF; END;

Artigos relacionados