Variáveis em Packages
Packages são uma ferramenta muito poderosa dentro do banco de dados. Podemos incluir diversas functions, procedures, tipos de dados, collections e etc, todas agrupadas e organizadas de acordo com a lógica do negócio. Facilitando muito assim o trabalho de todos.
As vezes, queremos compartilhar variáveis dentro dos componentes do packages, algo que é comum entre várias partes do mesmo. Ou queremos ter uma variável global, onde todos podem ter o acesso. Mas é aí que existe um perigo. Pois, se uma variável for declarada no package, ela será visível a todos, eserá pública, sendo assim, alguém poderá modificá-la, resultado em erros posteriores. Vejamos como isso pode ocorrer.
CREATE OR REPLACE PACKAGE teste AS
pv_teste NUMBER := 1;
END teste;
No exemplo acima, podemos ver um package extremamente simples, que contem apenas uma variável pública, que é visível para todos que tenham acesso ao package. Agora imagem que uma função ou procedure dependa dessa variável e que alguém faça exatamente o que nos mostra o exemplo a seguir.
BEGIN
teste.pv_teste := 2;
dbms_output.put_line(teste.pv_teste);
END;
O valor a ser impresso será 2 e não 1. Declarar variáveis dentro do package é uma prática que deverá ser evitada. Caso seja necessário fazer isso, para que vários usuários tenham acesso a essa variável, ela deverá ser declarada como CONSTANT. Veja a seguir como ficaria.
CREATE OR REPLACE PACKAGE teste AS
pv_teste CONSTANT NUMBER := 1;
END teste;
BEGIN
teste.pv_teste := 2;
dbms_output.put_line(teste.pv_teste);
END;
Assim, ao tentar alterar o conteúdo da variável um erro seria lançado. Isso protege o valor da variável. Caso não seja necessário que ninguém acesse essa variável de modo direto, mas sim que exista uma variável compartilhada somente para o funcionamento interno dos componentes do package, como procedures e functions, devemos evitar declarar essa variável no package. Ao invés disso ela deverá ser declarada do corpo package. Vejamos como ficaria.
CREATE OR REPLACE PACKAGE teste AS
pv_var1 NUMBER := 1;
PROCEDURE pf_teste;
END teste;
CREATE OR REPLACE PACKAGE BODY teste AS
pv_var2 NUMBER := 1;
PROCEDURE pf_teste IS
BEGIN
dbms_output.put_line(pv_var2);
END;
END teste;
BEGIN
teste.pv_var1 := 2;
dbms_output.put_line('pv_var1: '||teste.pv_var1);
teste.pv_var2 := 2;
dbms_output.put_line('pv_var1: '||teste.pv_var2);
END;
Assim, dessa forma, o conteúdo da variável pv_var1 será modificado, mas ao tentar modificar o da variável pv_var2 será lançado um erro, como se não existisse essa variável. Sendo assim a variável pv_var2 é privada. Caso seja necessário acessar o conteúdo dela, existe a procedure teste.pf_teste que retorna o valor da variável para exibição no console. Dessa mesma maneira, poderíamos criar uma procedure para modificar a variável pv_var2. Isso é algo bem comum e conhecido em outras linguagens de programação como JAVA por exemplo. Onde as variáveis são privadas e é criado métodos getters e setters para acesso e modificação da variável. Então, tomem cuidado ao utilizar variáveis em packages, estejam atentos ao que foi discutido aqui.
Referência
- Oracle 12c SQL Reference
- Oracle Docs Packages
- Oracle Docs Constant
Abraço