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