Академический Документы
Профессиональный Документы
Культура Документы
6.2
Trigger Layout
BEFORE CREATE TRIGGER <trigger_name> AFTER INSERT UPDATE DELETE OR
OLD NEW
FOR EACH ROW <table_name> FOR EACH STATEMENT
ON
EXECUTE PROCEDURE
<function_name>
<arguments>
);
6.3
Extensiones SQL-99
s Entre las propuestas definidas en el estndar SQL-99
6.4
Por qu PL/pgSQL
s Permite crear funciones que se ejecutan en el
servidor (versus otras aproximaciones como JDBC que se ejecutan en el cliente con "overhead" de comunicaciones).
s La propia base de datos se encarga de compilar y
6.5
el uso de pl/pgSQL (a menos que template1 ya este autorizada) createdb mydatab createlang plpgsql mydatab
s En los laboratorios debera estar "autorizado" por defecto
6.6
DECLARE --variables inicializada con NULL cada vez --que se entra en el bloque [...] BEGIN --comandos; [...] END;
s No se pueden definir transacciones dentro de una funcin
6.7
PL/pgSQL estructura
CREATE FUNCTION nombre_funcin (argumentos) RETURNS type AS ' DECLARE declaracion; [...] BEGIN statement; [...] END; ' LANGUAGE 'plpgsql';
s Una funcin puede constar de varios bloques y estos pueden
--variables
--comandos
estar anidados
6.8
PL/pgSQL: Generalidades
s Los tipos de datos pasados a la funcin se dan en parntesis
cadena de caracteres (ntese, que el cuerpo empieza y acaba con comillas simples) (escape doble)
s Tras la cadena el lenguaje usado para crear la funcin se define
usando la orden "LANGUAJE" (otros lenguajes posibles son PL/PERL, PL/TCL, C, etc)
6.9
CREATE OR REPLACE FUNCTION una_funcion () RETURNS int4 AS ' DECLARE an_integer int4; --variables BEGIN an_integer := 10 * 10; --comandos RETURN an_integer; END; ' LANGUAGE 'plpgsql'; ____________________________
select una_funcion(); una_funcion -----------100 (1 row)
6.10
Tipos de Variables-I
s
Ejemplos de variables:
id_usuario INTEGER; cantidad NUMERIC(5,2); url VARCHAR; -- Mas sobre los tipos siguientes ms adelante micampo mitabla.campo%TYPE; mitupla mitabla%ROWTYPE;
s The general syntax of a variable declaration is:
6.11
Tipos de Variables II
s Todos los tipos de variable definidos para SQL son vlidos en
PL/pgSQL
s No es imprescindible conocer el tipo de variables de los atributos
DECLARE BEGIN
5 %ROWTYPE reserva sitio para toda la tupla 5 Reteniendo la estructura de los datos
DECLARE
mivar payroll%ROWTYPE;
6.12
Ms sobre Variables
s CREATE FUNCTION mifuncion(INTEGER, CHAR, ) s Se pueden pasar hasta 16 variables
CREATE FUNCTION cal_longitud (text) RETURNS int4 AS ' DECLARE intext ALIAS FOR $1; --primer parametro resultado int4; . . .
6.14
6.15
Ejercicio
s En la base de datos de pelculas crear dos funciones que nos
sirvan para llenar la tabla reparto, dando el nombre de la pelicula y el nombre del actor
CREATE TABLE PELICULA( ID INTEGER, -- Identificador nico TITULO CHAR(70), -- Titulo de la pelcula AGNO DECIMAL(4), -- Ao de estreno PUNTUACION FLOAT, -- Puntuacin media VOTOS INTEGER, -- Numero de votos PRIMARY KEY (ID)); -CREATE TABLE ACTOR ( ID INTEGER, -- Identificador nico NOMBRE CHAR(35), -- Nombre del actor/actriz PRIMARY KEY (ID)); -CREATE TABLE REPARTO( PELICULA_ID INTEGER, -- referencia a la tabla PELICULA ACTOR_ID INTEGER, -- referencia a la tabla ACTOR_ID ORD INTEGER, -- Orden en el reparto -- La estrella es 1, ... -FOREIGN KEY (PELICULA_ID ) REFERENCES PELICULA(ID), FOREIGN KEY (ACTOR_ID) REFERENCES ACTOR(ID), PRIMARY KEY (PELICULA_ID, ACTOR_ID));
6.16
Control de Flujo
s Los programas no suelen ejecutarse de principio a fin sin
exceptuar ninguna lnea de cdigo. PL/pgSQL contiene estructuras de control que permiten seleccionar las lneas de cdigo que sern ejecutarse en tiempo real.
s IFTHENELSEELSE IF
5 ejecucin condicional
s LOOPS, WHILE LOOPS, FOR LOOPS
5 iteraciones 5 bucles
6.17
Ejemplo IF/ELSE
s Programa que calcula la longitud de dos cadenas y devuelve la
longitud mayor. CREATE OR REPLACE FUNCTION cadena_mas_larga(text, text) RETURNS int4 AS ' DECLARE in_uno ALIAS FOR $1; in_dos ALIAS FOR $2; lon_uno int4; lon_dos int4; result int4; BEGIN lon_uno := (SELECT LENGTH(in_uno)); lon_dos := (SELECT LENGTH(in_dos)); IF lon_uno > lon_dos THEN RETURN lon_uno; ELSE RETURN lon_dos; END IF; END; 'LANGUAGE 'plpgsql'; s NOTA 1: se pueden hacer condiciones mas complicadas usando OR y AND s NOTA 2: Como PL/pgSQL se agrupa en bloques no hacen falta parntesis en torno a IF
6.18
(FOR)
CREATE OR REPLACE FUNCTION cuentac(text,text) RETURNS INT4 AS ' DECLARE intext ALIAS FOR $1; inchar ALIAS FOR $2; lon int4; resultado int4; i int4; tmp char; BEGIN lon := length(intext)+1; i:=1; resultado:=0; WHILE i <= lon LOOP tmp := substr(intext,i,1); IF tmp = inchar THEN resultado := resultado +1; END IF; i:=i+1; END LOOP; RETURN resultado; END ' LANGUAGE 'plpgsql'; -- SELECT cuentac('qwertytq','q');
6.19
Excepciones
s RAISE se usa para imprimir mensajes y, en el caso de
5 RAISE NOTICE ' No hagas eso!' '; 5 RAISE NOTICE ' 'El seor' ' || id || ' 'no est en casa' '; 5 RAISE NOTICE ' 'el seor % no est en casa' ' , id;
6.20
Excepciones: Ejemplo
Calcular la suma de los enteros de n a m (usar la formula (p+1)*p/2 CREATE OR REPLACE FUNCTION suma(int4, int4) RETURNS int4 AS ' DECLARE inicio ALIAS FOR $1; fin ALIAS FOR $2; resultado int; BEGIN IF (inicio <1) THEN RAISE EXCEPTION ''inicio debe ser mayor que 1''; ELSE IF(inicio <= fin) THEN resultado := (fin+1)*fin/2 (inicio-1)*inicio/2; ELSE RAISE EXCEPTION ''El valor inicial % debe ser menor que el final %'', inicio, fin; END IF; END IF; RETURN resultado; END ' LANGUAGE 'plpgsql'; SELECT suma(1,3); $$
s
6.21
SELECT y Bucles
CREATE OR REPLACE FUNCTION trae_pelicula (integer) RETURNS text AS ' DECLARE pelicula_id ALIAS FOR $1; encontrada_pelicula pelicula%ROWTYPE; BEGIN SELECT INTO encontrada_pelicula * FROM pelicula WHERE id = pelicula_id; RETURN encontrada_pelicula.titulo || '' encontrada_pelicula.agno || '')''; ('' ||
6.22
SELECT y Bucles
Cuantas tuplas empiezan con una letra determinada CREATE OR REPLACE FUNCTION cuenta_letra (text) RETURNS int4 AS ' DECLARE caracter ALIAS FOR $1; temporal record; tmp_caracter text; resultado int4; BEGIN resultado:=0; FOR temporal IN SELECT titulo FROM pelicula LOOP tmp_caracter :=substr(temporal.titulo,1,1); IF tmp_caracter = caracter THEN resultado := resultado +1; END IF; END LOOP; RETURN resultado; END; 'LANGUAGE 'plpgsql'; SELECT cuenta_letra('A');
s
6.23
Persona Puja
Puja Objeto
PERSONA
OBJETO
Subastado por Rechazar pujas no admisibles 10% menos que puja anterior Un da ms tarde
6.24
TABLAS
CREATE TABLE persona( id SERIAL, --identificador unico PRIMARY KEY(id) ); CREATE TABLE objeto( id SERIAL, --identificador unico persona_id INT, fecha_salida TIMESTAMP DEFAULT now(), vendido int DEFAULT 0, -- 1 vendido, 0 no vendido precio_salida NUMERIC(10,2), PRIMARY KEY(id), FOREIGN KEY (persona_id) REFERENCES persona(id) ); CREATE TABLE puja( objeto_id INT, persona_id INT, fecha TIMESTAMP, cuantia NUMERIC(10,2), FOREIGN KEY (objeto_id) REFERENCES objeto(id), FOREIGN KEY (persona_id) REFERENCES persona(id), PRIMARY KEY(persona_id,objeto_id,fecha) );
6.25
DATOS
--poblar la tabla ---persona (id) -INSERT INTO persona VALUES (1);-INSERT INTO persona VALUES (2);-INSERT INTO persona VALUES (3);-INSERT INTO persona VALUES (4);-INSERT INTO persona VALUES (5);----objeto(id, persona_id,fecha_salida,vendido,precio_salida) -INSERT INTO objeto VALUES (1,1,now(),DEFAULT,23);-INSERT INTO objeto VALUES (2,1,now()+'-1.1 day',DEFAULT,23); INSERT INTO objeto VALUES (3,3,now()+'-3.14 day',DEFAULT,23); INSERT INTO objeto VALUES (4,3,now()+'-2.9 day',DEFAULT,23); INSERT INTO objeto VALUES (5,3,now()+'-5.9 day',DEFAULT,23); INSERT INTO objeto VALUES (6,4,now()+'-5.9 day',DEFAULT,23); INSERT INTO objeto VALUES (7,4,now()+'-0.9 day',DEFAULT,23); INSERT INTO objeto VALUES (8,5,now()+'-0.8 day',DEFAULT,23); INSERT INTO objeto VALUES (9,5,now()+'-1.34 day',DEFAULT,23); INSERT INTO objeto VALUES (10,5,now()+'-5.9 day',DEFAULT,23); ---puja (objeto_id,persona_id,fecha) -INSERT INTO puja VALUES (1,1,now()+'1 hour',10.34); INSERT INTO puja VALUES (1,1,now()+'2 hour',10.34); INSERT INTO puja VALUES (1,1,now()+'3 hour',10.34); INSERT INTO puja VALUES (1,1,now()+'4 hour',10.34); INSERT INTO puja VALUES (1,1,now()+'5 hour',10.34); INSERT INTO puja VALUES (1,1,now()+'10 hour',10.34); INSERT INTO puja VALUES (10,1,now()+'1 hour',10.34); INSERT INTO puja VALUES (9,1,now()+'1 hour',10.34);
6.26
Ejemplo funcin en C
Ejemplo de Funcin en C
s Cdigo
#include "postgres.h" #include <string.h> /* by value */ int add_one(int arg) { return arg + 1; } s Compilacin gcc -fpic -c foo.c -I /usr/include/pgsql/server/ gcc -shared -o foo.so foo.o
6.28
CREATE FUNCTION add_one(integer) RETURNS integer AS '/tmp/foo.so', 'add_one' LANGUAGE C STRICT; _______________________________
s add_one.so es la librera dinmica con la funcin s Ms informacin en: s Recordar que C no soporta todos los tipos usados
6.29
Se acab