Banco de Dados - Oracle

PL/SQL - Procedimentos (parte 2)

O corpo de um procedimento é um bloco de pl/sql com seção declarativas, executáveis e de exceções...

por Márcio Novelli



O Corpo do Procedimento

O corpo de um procedimento é um bloco de pl/sql com seção declarativas, executáveis e de exceções. A seção declarativa esta localizada entre a palavra-chave IS ou AS e a palavra-chave BEGIN. A seção executável (a única que e obrigatória) esta localizada entre as palavras-chave BEGIN e EXCEPTION. A seção de excepcoes esta localizada entre as palavras-chave EXECPTION e END.

OBS.: NAO EXISTE PALAVRA-CHAVE DECLARE NUMA DECLARACAO DE PROCEDIMENTOS OU DE FUNCAO; EM VEZ DELA E UTILIZADA A PALAVRA-CHAVE IS OU AS.

A estrutura de um procedimento tem o seguinte aspecto:

CREATE OR REPLACE PROCEDURE nome_procedimento AS
/* SECCAO DECLARATIVA */
BEGIN
/* EXECUTAVEL */
EXCEPTION
/* EXECEPCOES */
END nome_procedimento;

Opcionalmente, o nome do procedimento pode ser incluído apos a instrução END final na declaração do procedimento. Se existir um identificador a seguir a END, tem como corresponder ao nome do procedimento. E considerado bom estilo incluir o identificador, visto que enfatiza a instrução END, que corresponde a instrução CREATE.

Restrições aos parâmetros formais

/*  A declaração de procedimento seguinte e ilegal e gerada um erro de compilação  - illegal */

SET echo off
PROMPT Parametro iLegal…
SET echo on

CREATE OR REPLACE PROCEDURE Parametro (
  p_Parametro1 IN OUT VARCHAR2(10),
  p_Parametro2 IN OUT NUMBER(3,2)) AS
BEGIN
  p_Parametro1 := "marcio_novelli";
  p_Parametro2 := 12.3;
END Parametro;
/
show erros

/*  A declaração de procedimento seguinte e legal  - declaração correta abaixo */

SET echo off
PROMPT Parametro Legal…
SET echo on

CREATE OR REPLACE PROCEDURE Parametro (
  p_Parametro1 IN OUT VARCHAR2,
  p_Parametro2 IN OUT NUMBER) AS
BEGIN
  p_Parametro1 := "marcio_novelli";
  p_Parametro2 := 12.3;
END Parametro;
/

Pergunta

Quais são então as restrições a p_Parametro1 e p_Parametro2?
As restrições tem origem nos parâmetros reias. Se chamarmos Parâmetro com

DECLARE
  v_Variavel1 VARCHAR2(40);
  v_Variavel2 NUMBER(3,4);
BEGIN
  Parametro(v_Variavel1, v_Variavel2);
END;
/

p_Parametro1 tera um comprimento Maximo 40 (tendo origem no parâmetro real v_Parametro1) e p_Parametro2 tera precisão 3 e escala 4 (tendo origem no parâmetro real v_Parametro2). É importante estar consciente deste fato. Considere o seguinte bloco,que também chama Parametro

DECLARE
  v_Variavel1 VARCHAR2(10);
  v_Variavel2 NUMBER(3,4);
BEGIN
  Parametro(v_Variavel1, v_Variavel2);
END;
/

A única diferença entre este bloco e o anterior e que v_Variavel1,e conseqüentemente p_Parametro1, tem um comprimento de 10 em vez de 40.
Visto que Parâmetro(nome do procedimento) atribui uma cadeia de caracter com um comprimento de (MARCIO NOVELLI) 14 VARCHAR2(e conseqüentemente v_Variavel1) nao existe espaço suficiente na cadeia .Isto ocorrera um erro Oracle quando o procedimento for chamado:

ORA-6502: NUMERIC OR VALUE ERROR

OBS: PARA EVITAR ERROS COMO ORA-6502, DOCUMENTE TODOS OS REQUISITOS DE RESTRICOES DOS PARAMETROS REAIS QUANDO O PROCEDIMENTO FOR CRIADO. ESTA DOCUMENTACAO DEVE SER CONSTITUIDA POR COMENTARIOS ARMAZENADOS COM O PROCEDIMENTO E DEVE INCLUIR UMA DESCRICAO DO QUE E EFETUADO PELO PROCEDIMENTO,PARA ALEM DE QUAISQUER DEFINICOES DE PARAMETROS

%TYPE e parâmetros de procedimento - A única forma de restringir um parâmetro formal e utilizando %TYPE.Se um parâmetro formal for declarado com %TYPE e o tipo subjacente for restringido, a restrição aplica-se-a ao parâmetro formal e nao ao parâmetro real. Se declararmos Parâmetro com:

CREATE OR REPLACE PROCEDURE Parametro (
  p_Parametro1 IN OUT VARCHAR2,
  p_Parametro2 IN OUT estudantes.credito%TYPE) AS
BEGIN
  p_Parametro2 := 12345;
END Parametro;
/

/*  
CREATE TABLE estudantes (
  Numero_id        NUMBER(5) PRIMARY KEY,
  nome                 VARCHAR2(20),
  sobre_nome       VARCHAR2(20),
  curso                  VARCHAR2(30),
  credito                NUMBER(3)
  );
*/

p_Parametro2 será restringido com precisão 3, visto que é a precisão da coluna credito. Mesmo que chamemos Parâmetro(procedure) com um parâmetro real que tenha a precisão adequada,e a precisão formal que prevalece.

SET echo off
PROMPT Chamando parametro Ilegal (ORA-6502)...
SET echo on

DECLARE
  v_Variavel1 VARCHAR2(1);
  v_Variavel2  NUMBER;  
BEGIN
.
.
 Parametro(v_Variavel1, v_Variavel2);
END;
/

Nota: acima dará origem ao erro ORA-6502.

Notação nomeada e posicional

Em todos os códigos (exemplos) citados acima , os argumentos reais estão associados aos argumentos formais pela posição . Dada uma declaração do procedimento como:

CREATE OR REPLACE PROCEDURE Notacao (
  p_ParametroA VARCHAR2,
  p_ParametroB NUMBER,
  p_ParametroC BOOLEAN,
  p_ParametroD DATE) AS
BEGIN
  NULL;
END Notacao;
/

e um bloco de chamada como:

DECLARE
  v_Variavel1 VARCHAR2(10);
  v_Variavel2 NUMBER(7,6);
  v_Variavel3 BOOLEAN;
  v_Variavel4 DATE;
BEGIN
  Notacao(v_Variavel1, v_Variavel2, v_Variavel3, v_Variavel4);
END;
/

Os parâmetros reais estão associados aos parâmetros formais pela posição: v_variavel1 esta associado a p_ParametroA , e assim sucessivamente. Isto e designado por notação posicional.

Notação Posicional

A notação posicional e mais utilizada e também e a notação utilizada em outras linguagens da terceira geração, tais como C.

Em alternativa, podemos chamar o procedimento utilizando a notação nomeada:

DECLARE
  v_Variavel1 VARCHAR2(10);
  v_Variavel2 NUMBER(7,6);
  v_Variavel3 BOOLEAN;
  v_Variavel4 DATE;
BEGIN
  Notacao(p_ParametroA => v_Variavel1, 
                 p_ParametroB => v_Variavel2,
                 p_ParametroC => v_Variavel3,
                 p_ParametroD => v_Variavel4);
END;
/

Geralmente utilizo a notação posicional, porque prefiro escrever código sucinto. Porém é importante utilizar bons nomes para os parâmetros reais. Por outro lado, se o procedimento aceitar um grande numero de argumentos, e desejável utilizar a notação nomeada, visto que e mais fácil corresponder os parâmetros formais e reais. Contudo, os parâmetros com tantos argumentos são relativamente raros.

Um forte abraço a todos, e até o próximo artigo!

Márcio Novelli

Márcio Novelli - Analista de Sistemas, Consultor Oracle 8i e 9i e chefe dos projetos do banco de dados Oracle pela empresa Walnut Telecomunicação e Informática LTDA - www.walnut.com.br. Bacharel em Ciência da Computação pela Universidade de Marília (UNIMAR). Especialização em Oracle 8i na Faculdade de Tecnologia IBTA (Instituto Brasileiro de Tecnologia Avançada - S.P). Certificado Introduction to Oracle9i: SQL Oracle9i Database Administration: Fundamentals I
Escreve artigos também para os sites da revista SQL Magazine (www.sqlmagazine.com.br), Portal Fire Masters (http://www.portalfiremasters.com.br/) e Freecode (www.freecode.com.br).