PL Gestión y Modelación de Datos

Anuncio
PL
Gestión y Modelación de Datos
PL
●
●
●
●
●
PL/pgSQL es un lenguaje de programación
procedimental
Permite crear funciones en la base de datos
PostgreSQL
Las funciones agrupan secuencias de
sentencias SQL y sentencias de programación
Reduce la carga de comunicación entre el
cliente y la base de datos
Mejora el performance de los programas
PL – CREATE FUNCTION
CREATE OR REPLACE FUNCTION identifier
(arguments) RETURNS type AS '
DECLARE
declaration;
[...]
BEGIN
statement;
[...]
END;
' LANGUAGE 'plpgsql';
DROP FUNCTION [ IF EXISTS ] name (arguments)
[ CASCADE | RESTRICT ]
PL – CREATE FUNCTION
CREATE OR REPLACE FUNCTION cuadrado (integer)
RETURNS integer AS '
DECLARE
cuad integer;
BEGIN
cuad = $1 * $1;
RETURN cuad;
END;
' LANGUAGE 'plpgsql';
postgres=> \i cuadrado.sql
CREATE FUNCTION
postgres=> select cuadrado (10);
PL – CREATE FUNCTION
●
●
●
●
●
No se puede usar REPLACE para cambiar el nombre
o tipo de los argumentos, ni el tipo de retorno
● Permite sobrecarga del nombre de la función
Los argumentos tienen un modo (IN, OUT, INOUT),
un nombre y un tipo
● IN por defecto
El nombre del lenguaje puede ser también C, internal
Cuando se borra la función en cascada
automáticamente se borran los objetos que
dependen de ella (ej. Triggers)
Comentarios: - - comentario línea
/* comentario de
Bloque */
PL – DECLARE
●
●
Alias para los argumentos
Variables
variable_name [ CONSTANT ] data_type [ NOT NULL ]
[ { DEFAULT | := } value ];
Ejemplo:
CREATE OR REPLACE FUNCTION AgregarPais
(CHAR(2), VARCHAR(40), TEXT )
RETURNS boolean AS '
DECLARE
-- Alias para los argumentos
codigo ALIAS FOR $1;
nombre ALIAS FOR $2;
region ALIAS FOR $3;
-- Variables
cod_region SMALLINT;
PL – STATEMENTS
●
●
●
●
●
●
●
●
●
Asignación (:=)
SELECT INTO
IF – THEN – ELSE – END IF
LOOP – END LOOP
WHILE – LOOP – END LOOP
FOR – IN – LOOP – END LOOP
RAISE
Llamado a Funciones
RETURN
PL – STATEMENTS
CREATE OR REPLACE FUNCTION AgregarRegion (varchar(40))
RETURNS timestamp AS '
-- Agrega una region siguiendo el consecutivo del código
DECLARE
-- Alias para los argumentos
nombre ALIAS FOR $1;
-- Variables
codigo SMALLINT;
hora TIMESTAMP;
BEGIN
hora := ''now'';
SELECT INTO codigo MAX(cod_region) FROM region ;
-- Calcula nuevo codigo (anterior + 1)
codigo := codigo + 1;
-- Inserta la nueva region
INSERT INTO region VALUES (codigo, nombre, hora);
RETURN hora;
END; '
LANGUAGE 'plpgsql';
PL – STATEMENTS - timestamp
CREATE OR REPLACE FUNCTION AgregarRegionBAD (text)
RETURNS boolean AS '
-- Agrega una region siguiendo el consecutivo del código
DECLARE
-- Alias para los argumentos
nombre ALIAS FOR $1;
-- Variables
codigo SMALLINT;
-- hora TIMESTAMP;
BEGIN
-- hora := ''now'';
SELECT INTO codigo cod_region FROM region ORDER BY
cod_region DESC;
-- Calcula nuevo codigo (anterior + 1)
codigo := codigo + 1;
-- Inserta la nueva region
INSERT INTO region VALUES (codigo, nombre, ''now'');
RETURN TRUE;
END; ' LANGUAGE 'plpgsql';
PL – STATEMENTS
CREATE OR REPLACE FUNCTION AgregarRegionALT (varchar(40))
RETURNS timestamp AS '
-- Agrega una region siguiendo el consecutivo del código
DECLARE
-- Alias para los argumentos
nombre ALIAS FOR $1;
-- Variables
codigo SMALLINT;
hora TIMESTAMP;
BEGIN
hora := ''now'';
SELECT codigo cod_region FROM region ORDER BY cod_region
DESC ;
-- Calcula nuevo codigo (anterior + 1)
codigo := codigo + 1;
-- Inserta la nueva region
INSERT INTO region VALUES (codigo, nombre, hora);
RETURN hora;
END; ' LANGUAGE 'plpgsql'';
PL – IF – THEN – ELSE – END IF
CREATE FUNCTION identifier (arguments) RETURNS
type AS '
DECLARE
declarations
BEGIN
IF condition THEN
Statement; […]
[ ELSE
statement; […] ]
END IF;
END; ' LANGUAGE 'plpgsql';
PL – IF – THEN – ELSE – END IF
CREATE OR REPLACE FUNCTION BuscarNombreOApellido
(TEXT, TEXT)
RETURNS TEXT AS '
-- Busca si hay un empleado con el nombre o el apellido dados
DECLARE
apellido TEXT; nombre TEXT;
BEGIN
SELECT INTO nombre, apellido nombres, apellidos
FROM empleado WHERE nombres = $1 OR apellidos = $2;
IF NOT FOUND THEN
RETURN ''No encontro'';
ELSE IF nombre = $1 THEN
RETURN ''Encontro Nombre'';
ELSE RETURN ''Encontro Apellido'';
END IF;
END IF;
END; ' LANGUAGE 'plpgsql';
PL – LOOP – END LOOP
[ <<label>> ]
LOOP
statement;
[...]
EXIT [ label ] [ WHEN condition ];
END LOOP;
●
<<label>> permite especificar a que LOOP
se refiere un EXIT, cuando hay loops anidados
PL – WHILE – END LOOP
[ <<label>> ]
WHILE condition LOOP
statement;
[...]
END LOOP;
PL – FOR – END LOOP
[ <<label>> ]
FOR identifier IN [ REVERSE ] expression1 ..
expression2 LOOP
statement;
[...]
END LOOP;
[ <<label>> ]
FOR { record_variable | %rowtype_variable } IN
select_statement LOOP
statement;
[...]
END LOOP;
PL – FOR – IN – END LOOP
CREATE OR REPLACE FUNCTION NombreApellido ()
RETURNS TEXT AS '
-- Busca si hay un empleado con el nombre o el apellido dados
DECLARE
nombreyApellido TEXT;
textOutput TEXT := E'' '';
BEGIN
FOR nombreyApellido IN SELECT nombres||'' ''||apellidos
FROM empleado ORDER BY nombres, apellidos LOOP
textOutput := textOutput || nombreyApellido||E''\n'';
END LOOP;
RETURN textOutput;
END; '
LANGUAGE 'plpgsql';
PL – FOR – ROWTYPE
CREATE OR REPLACE FUNCTION NombreApellidoROW ()
RETURNS TEXT AS '
-- Retorna nombres y apellidos de los empleados
DECLARE
rowData empleado%ROWTYPE;
textOutput TEXT := '' '';
BEGIN
FOR rowData IN SELECT *
FROM empleado ORDER BY nombres, apellidos LOOP
textOutput := textOutput || rowData.nombres ||
rowData.apellidos||E''\n'';
END LOOP;
RETURN textOutput;
END; '
LANGUAGE 'plpgsql';
PL – RAISE
RAISE level ''message string'' [, identifier [...] ];
●
●
Levels:
● DEBUG: envia el mensaje al log, y al cliente
si la BD esta en modo depuración
● NOTICE: envia el mensaje al log y al cliente
● EXCEPTION: envia el mensaje al log y al
cliente, y aborta la ejecución
Identifier: nombre de las variables que va a
incluir en el mensaje (debe marcarse con %
en el texto)
PL – RAISE
CREATE OR REPLACE FUNCTION RaiseError ()
RETURNS boolean AS '
DECLARE
var1 integer;
var2 integer;
BEGIN
var1 := 10;
var2 := 15;
RAISE EXCEPTION ''Error en % y en %'', var1, var2;
END; '
LANGUAGE 'plpgsql';
PL – Llamado a Funciones
SELECT function_identifier(arguments);
variable_identifier :=
function_identifier(arguments);
PERFORM function_identifier(arguments);
Ejercicio
●
Con la base de datos de empleados:
●
●
Escriba una función que busque los máximos jefes
(jefes que no tiene jefe), y retorne un conjunto de
registros tipo texto donde los nombres de cada
jefe esta seguido por los nombres de sus
subalternos inmediatos
Escriba una función que retorne una cadena en la
que los jefes máximos aparecen con nivel 0, sus
subalternos con nivel 1, y los subalternos de ellos
con nivel 2, y así sucesivamente
Descargar