Funciones y paquetes PL/SQL

Funciones y paquetes
PL/SQL
Jonathan Medina Gómez
Facultad de ingeniería
Universidad de Antioquia
Funciones
● Una función es un subprograma que retorna un valor
simple.
● Las funciones se pueden invocar dentro de una
expresión.
● Si un subprograma posee exactamente un argumento
de salida, es mejor crear una función que un
procedimiento ya que así se puede involucrar
directamente en las expresiones
Sintaxis
CREATE
[(
[,
RETURN
IS
[OR REPLACE] FUNCTION nombre_función
arg1 [modo] tipo
arg2 [modo] tipo...])]
tipo_de_dato
[<<Declaración de variables>>]
BEGIN
<<Instrucciones>>
[EXCEPTION]
<<Manejador de excepciones>>
END;
/
Ejemplo
CREATE OR REPLACE FUNCTION area_circulo (radio IN NUMBER)
RETURN NUMBER IS
pi CONSTANT NUMBER(5,4) := 3.1416;
BEGIN
RETURN ( radio * radio * pi );
END;
/
Invocación en SQL*Plus:
VAR a NUMBER;
EXECUTE :a := area_circulo(3);
PRINT a;
Ejercicio
Elaborar una función que devuelva el factorial de un número.
n > 0: n*(n-1)!
n! =
n=0:1
n < 0: error (-1)
- Elaborarlo recursivo
- Elaborarlo no recursivo
Solución recursiva
CREATE OR REPLACE FUNCTION factorialr
Rango:
(n NATURAL)
0,1,...2147’
RETURN NUMBER IS
BEGIN
IF n = 0 THEN RETURN 1;
ELSE RETURN n * factorialr(n-1);
END IF;
END;
/
Solución iterativa
CREATE OR REPLACE FUNCTION factorialnr
(n NATURAL)
RETURN NUMBER IS
fact NUMBER := 1;
BEGIN
FOR k IN 1..n LOOP
fact := fact * k;
END LOOP;
RETURN fact;
END;
/
Las funciones se pueden usar en las
consultas
CREATE TABLE numero(num NUMBER(10) PRIMARY KEY);
INSERT INTO numero VALUES(1);
INSERT INTO numero VALUES(3);
SELECT 'El factorial de ' || num ||
' es ' || factorialr(num) AS fact
FROM numero;
Incluso se puede hacer algo como:
SELECT 'El factorial de ' || factorialr(num) ||
' es ' || factorialnr(factorialr(num)) AS fact
FROM numero;
Paquete
● Un paquete es una agrupación de funciones, procedimientos
y variables.
● Clasifican los subprogramas de acuerdo con una categoría
elegida por el programador o diseñador
● Un paquete consta de 2 partes:
○ Especificación: Definiciones de variable “públicas” y
prototipos de los subprogramas.
○ Cuerpo (BODY): Implementación de los subprogramas
descritos en la especificación y variables privadas
Sintaxis
Especificación
Cuerpo
CREATE PACKAGE nom_paquete IS
CREATE PACKAGE BODY nom_paquete IS
-- Variables públicas
-- Declaración de subprogramas
(públicos)
-- Variables privadas
/* Implementación de subprogramas
privados */
/* Implementación de subprogramas
declarados en la especificación */
END;
/
END;
/
Ejemplo de la especificación
CREATE OR REPLACE PACKAGE matematico IS
FUNCTION factorial(n NATURAL) RETURN NUMBER;
FUNCTION dist_puntos(x1 NUMBER, y1 NUMBER, x2
NUMBER, y2 NUMBER)
RETURN NUMBER;
END;
/
Ejemplo del cuerpo
CREATE OR REPLACE PACKAGE BODY matematico IS
--Subprograma privado
FUNCTION fact (n NATURAL) RETURN NUMBER IS
BEGIN
IF n = 0 THEN RETURN 1;
ELSE RETURN n*fact(n-1);
END IF;
END;
--Subprograma privado
PROCEDURE error(mensaje VARCHAR) IS
BEGIN
DBMS_OUTPUT.PUT_LINE(mensaje);
END;
Continuación del cuerpo
FUNCTION factorial(n NATURAL) RETURN NUMBER IS
--Subprograma Público
BEGIN
IF (n > 20) THEN error( ' Valor demasiado grande ' );
RETURN -1;
ELSE RETURN fact(n);
END IF;
END;
--Subprograma Público
FUNCTION dist_puntos(x1 NUMBER, y1 NUMBER, x2 NUMBER, y2 NUMBER)
RETURN NUMBER IS
BEGIN
RETURN (SQRT(POWER(x2 - x1,2) + POWER(y2 - y1,2) ) );
END;
END; --Fin del paquete
/
Para ejecutar:
a.
VAR a NUMBER;
EXECUTE :a := matematico.factorial(3);
PRINT a. Imprime 6
b.
EXECUTE :a := matematico.dist_puntos(0,0,1,1);
PRINT a. Imprime 1.4142...
c.
EXECUTE :a := matematico.factorial(-5);
Error
d.
EXECUTE matematico.error('Mensaje');
Error, el subprograma es privado
Invocación desde un SELECT
CREATE TABLE punto(
coordx NUMBER(10), coordy NUMBER(10),
PRIMARY KEY(coordx, coordy) );
INSERT INTO punto VALUES(0,0);
INSERT INTO punto VALUES(1,1);
INSERT INTO punto VALUES(0,4);
Invocación desde un SELECT
SELECT 'La distancia del origen a (' ||
coordx || ',' || coordy || ')' || ' es ' ||
matematico.dist_puntos(0,0,coordx,coordy) AS
distancia
FROM punto;
Ejercicio
Realice una función que imprima los N
primeros valores de la serie fibonacci.
fibonacci(10) => 0, 1, 1, 2, 3, 5, 8, 13, 21, 34