Banco de Dados - Oracle

PL/SQL - Função

Uma função é muito semelhante a um procedimento. Ambos aceitam argumentos, que podem ter qualquer modo. Ambos são formas diferentes de blocos de PL/SQL, com seções declarativas, executável e de exceções...

por Márcio Novelli



Uma função é muito semelhante a um procedimento. Ambos aceitam argumentos, que podem ter qualquer modo. Ambos são formas diferentes de blocos de PL/SQL, com seções declarativas, executável e de exceções. Ambos podem ser armazenados na base de dados e declarados num bloco. (As funções e os procedimentos que não são armazenados na base de dados será analisados mais para frente conforme for descrevendo minhas colunas semanalmente). Porém , uma chamada de procedimento é uma instrução PL/SQL por si só, enquanto que uma chamada de função é chamada como parte de uma expressão.

Logo abaixo um exemplo de uma função que devolve TRUE se a turma especificada ultrapassar 90% da sua capacidade e FALSE em qualquer outra situação .

CREATE OR REPLACE FUNCTION RetornaEstudante (
  p_Departamento  classes.departmento%TYPE,
  p_Curso               classes.curso%TYPE)
  RETURN BOOLEAN IS

  v_numero_estudantes            NUMBER;
  v_valor_maximo_estudantes      NUMBER;
  v_RetornaValor                 BOOLEAN;
  v_Porcentual_Cheio             CONSTANT NUMBER := 90;

BEGIN
  SELECT numero_estudantes, valor_maximo_estudantes
    INTO v_numero_Epl/sql studantes, v_valor_maximo_estudantes
    FROM classes
    WHERE departmento = p_Departmento
    AND curso = p_Course;

  -- se classe cheia entao  
  -- v_Porcentual_Cheio, retorna  TRUE. Retorna falso em outra situacao.

  IF (v_numero_estudantes / v_valor_maximo_estudantes * 100)> v_Porcentual_Cheio 
 THEN
    v_RetornaValor := TRUE;
  ELSE
    v_RetornaValor := FALSE;
  END IF;

  RETURN v_RetornaValor;
END RetornaEstudante;
/

A função RetornaEstudante devolve um valor booleano. Pode ser chamada a partir do bloco de PL/SQL seguinte. Observe que a chamada de função não é uma instrução por si só, e utilizada como parte da instrução IF dentro do ciclo.

DECLARE
  CURSOR c_Classes IS - cursor to tipo c (c_classes)
    SELECT departmento, curso
      FROM classes;
BEGIN
  FOR v_ClassesRecord IN c_Classes LOOP
        IF RetornaEstudante(v_ClassesRecord.departmento, v_ClassRecord.curso) THEN
      INSERT INTO tabela_temporaria (char_coluna) VALUES 
        (v_ClassesRecord.departamento || " " || v_ClassesRecord.curso ||
         "  RetornaEstudantes Cheio!!! ");
    END IF;
  END LOOP;
END;
/

Sintaxe das Funções

A sintaxe para criar uma função armazenada é muito semelhante a sintaxe de um procedimento.

Create [OR REPLACE] FUNCTION nome_função
[(argumento[{IN | OUT | IN OUT}] tipo,
…
[(argumento[{IN | OUT | IN OUT}] tipo,
RETURN tipo_retorno { IS | AS }
corpo_funcao

Em que nome_função e o nome da função, argumento e tipo são iguais ao dos procedimentos, tipo_retorno e o tipo do valor que a função devolve e corpo_função é o bloco de PL/SQL que contém o código da função.

Tal como nos procedimentos, a lista de argumentos é opcional. Neste caso, nao existem parênteses quer na declaração da função quer na chamada da função. Porém, o tipo de retorno é necessário, visto que a chamada da função faz parte de uma expressão. O tipo da função é utilizado para determinar o tipo da expressão que contém a chamada da função.

A Instrução RETURN

Dentro do corpo da função, a instrução RETURN é utilizada para desenvolver o controle ao ambiente de chamada com um valor. A sintaxe geral da instrução RETURN é

RETURN expressão;

em que expressão é o valor a devolver. O valor expressão será convertido para o tipo especificado na cláusula RETURN da definição da função, se ainda não for desse tipo. Quando a instrução RETURN é executada, o controle é imediatamente retomado pelo ambiente de chamada.

Pode existir mais que uma instrução RETURN numa função, embora apenas uma seja executada.

Logo abaixo segue um exemplo contendo várias instrução RETURN diferentes na função, apenas uma será executada. Neste caso a ser executada é determinado pelo grau de ocupação da turma da sala especificada por p_departamento e p_curso.

CREATE OR REPLACE FUNCTION InfoClasses (

  /* retorna cheio full" se classes completa (cheia), 
  
  p_Departamento classes.departamento%TYPE,
  p_curso        classes.curso%TYPE)
  RETURN VARCHAR2 IS

 
  v_numero_estudantes       NUMBER;
  v_valor_maximo_estudantes NUMBER;
  v_Porcentual_Cheio        NUMBER;
BEGIN

  SELECT numero_estudantes,valor_maximo_estudantes
    INTO v_numero_estudantes,v__valor_maximo_estudants
    FROM classes
    WHERE departamento = p_Departamento
    AND curso = p_Curso;

  -- calcular a porcentagem.
  v_Porcentual_Cheio:= v_numero_estudantes / v_valor_Maximo_estudantes* 100;

  IF v_Porcentual_Cheio = 100 THEN
    RETURN "sala cheia"; 
  ELSIF v_Porcentual_Cheio> 80 THEN
    RETURN "quase cheia";
  ELSE
    RETURN "vazia";
  END IF;
END InfoClasses;
/

Quando é utilizada numa função, a instrução RETURN tem de ter uma expressão associada. Contudo, a instrução RETURN também pode ser utilizada num procedimento.

Estilos das Funções

. As funções podem devolver mais do que um valor através dos parâmetros OUT

. O código das funções tem seções declarativas, executáveis e de tratamento de exceções.

. As funções podem aceitar valores por omissão.

Pergunta

Então quando é apropriado utilizar uma função e quando é apropriado utilizar um procedimento?

Normalmente, depende do número de valores que se espera que o subprograma devolva e da forma como esses valores serão utilizados.

REGRA GERAL

Se existir mais do que um valor de retorno, deve utilizar-se um procedimento. Se só existir um valor de retorno, pode ser utilizada uma função.

Embora seja legal uma função ter parâmetros OUT (e, assim, devolver mais do que um valor), é considerado mau estilo e pouco recomendável.

Abraços e até a próxima matéria !!!!!!!!!!!

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).