Documentos de Académico
Documentos de Profesional
Documentos de Cultura
BASE DE DATOS
SEMANA 6
[ BASE DE DATOS ]
CONTENIDO
Presentación ………………………………….. 3
1. DESARROLLO TEMÁTICO …………………… 3
• Funciones …………………………………. 4
• Cursores …………………………………… 4
• Procedimientos Almacenados ……………. 5
• Disparadores ………………………………. 7
Conclusiones ……………………………………. 10
1.1. BIBLIOGRAFÍA ………………………………. 10
2 [ POLITÉCNICO GANCOLOMBIANO EN ALIANZA CON WHITNEY INTERNATIONAL SYSTEM ]
PRESENTACIÓN
Como podemos observar el SQL no es un lenguaje de programación propiamente dicho, sino
simplemente un lenguaje de acceso a bases de datos puesto que no incorpora
construcciones de control que permitan representar el flujo de control y de la información a
través de un procedimiento software.
En esta lectura realizaremos una breve descripción del lenguaje y de los componentes del
mismo, describiendo la estructura clásica de los programas PL/pgsql. Se trata de unas
nociones básicas que permitirán a todos los participantes comprender los ejemplos
propuestos a los largo del curso e iniciarse en la programación de aplicaciones con PL/pgsql.
1. DESARROLLO TEMÁTICO
Los programas PL/pgsql se estructuran agrupando las declaraciones o cláusulas del lenguaje
en distintos bloques o secciones encargadas de tareas específicas, como son:
• Declaración de las variables de la interfaz del programa y de las variables internas
de ejecución. Se pueden utilizar los tipos de datos definidos por el SGBD y tipos de
datos definidos por el usuario para definir las variables y asignar valores a las
mismas.
• Flujo de control y operación de las tareas para las cuales se construye el programa.
Se hace uso de los verbos de control de flujo y de sentencias SQL.
Cada una de estas secciones viene identificada por una cláusula de cabecera de forma que la
estructura general de un procedimiento es la siguiente:
DECLARE
Declaración de las variables utilizadas
BEGIN
Cuerpo del procedimiento
END;
No se debe confundir el uso de las sentencias de agrupamiento BEGIN/END de PL/pgSQL con
los comandos de la base de datos que sirven para el control de las transacciones. Las
funciones y procedimientos disparadores no pueden iniciar o realizar transacciones y
Postgres no soporta transacciones anidadas.
[ BASE DE DATOS ] 3
Funciones
Como en cualquier lenguaje de programación PL/pgsql permite la declaración de
subprogramas (subrutinas) denominados funciones. Las funciones pueden ser invocadas
desde un programa PL/pgsql u otra función.
Una función PL/pgsql tiene como objetivo realizar un proceso y devolver un valor al
programa o subprograma que la invocó. Las funciones permiten la declaración de una
interfaz mediante la cual se les puede transferir una lista de valores. Un ejemplo de la
implementación de funciones es:
• Función Factorial
• El nombre de la función a crear.
CREATE FUNCTION fib(int4)
/* El tipo de datos que será devuelto. El tipo de datos que será devuelto puede
ser declarado como tipo básico, complejo, tipo setof u opaque. Modificadores
setof indican que la función devolverá un grupo de objetos, antes que un solo
objeto. */
RETURNS int4
/* Una cadena de letras que define la función y cuyo sentido depende del
lenguaje. Puede ser un nombre interno de función, el sendero a un fichero de
objeto, una cuestión en SQL o texto en un lenguaje procedimental. */
AS $$
DECLARE
a int4;
res int4:=0;
BEGIN
a := $1;
IF(a = 1 OR a = 2) THEN
res:= 1;
ELSE
res := fib(a‐2) + fib(a‐1);
END IF;
RETURN res;
END;
$$
/* Puede ser 'C', 'sql', 'internal' o 'plname', donde 'plname' es el nombre de un
lenguaje procedimental creado. */
Language 'plpgsql';
Cursores
Un cursor es un área de memoria de trabajo en la que se almacena la información de salida
de la sentencia SQL y que es necesario declarar para posteriormente poder acceder a las
4 [ POLITÉCNICO GANCOLOMBIANO EN ALIANZA CON WHITNEY INTERNATIONAL SYSTEM ]
tuplas que componen la salida de la sentencia. En lugar de ejecutar una consulta completa a
la vez, es posible crear un cursor que encapsula la consulta, y después lee el resultado de la
consulta un par de filas a la vez.
El siguiente ejemplo recorre la tabla PRODUCTO usando un CURSOR:
‐ Crear y usar el cursor
BEGIN WORK;
DECLARE micursor CURSOR
FOR SELECT * FROM producto;
‐ FETCH selecciona filas usando un cursor
‐ FORWARD selecciona la(s) siguiente(s) filas
‐ Seleccionar las primeras 3 filas en el cursor micursor
FETCH FORWARD 3 IN micursor;
‐ BACKWARD selecciona la(s) fila(s) anteriores
‐ Seleccionar la fila anterior
FETCH BACKWARD 1 IN micursor;
‐ Cerrar el cursor y commit WORK
CLOSE micursor;
COMMIT WORK;
Se recomienda usar los cursores sólo dentro de transacciones, ya que los datos que
almacenan abarcan múltiples consultas de usuario. Para mayor información:
http://www.postgresql.org/docs/8.1/static/sql‐declare.html.
Procedimientos almacenados
Un procedimiento almacenado es un conjunto nombrado de sentencias SQL y de
procedimientos. Este conjunto nombrado se guarda en la base de datos. Los procedimientos
almacenados son invocados por nombre.
[ BASE DE DATOS ] 5
Los procedimientos almacenados se invocan como una unidad. Por consiguiente, cuando
desea representarse una transacción de actualización múltiple, puede crearse un
procedimiento que se guarda en la base de datos. El contenido completo del
procedimiento almacenado se transmite y ejecuta, con lo que se evita la evita la
transmisión y ejecución de sentencias SQL individuales por la red. Por consiguiente, el
uso de procedimientos almacenados reduce sustancialmente el tráfico por la red, con lo
que se mejora el rendimiento.
Ejemplo:
Supongamos que tenemos una tabla ps_stock que almacena la información de los productos
por comprar
CREATE TABLE ps_stock (
ps_code int4 NOT NULL,
ps_descript varchar(35) NOT NULL
);
Queremos que haya una función comprar_producto() que haga lo siguiente:
• Cree una tabla nueva llamada ps_stock que almacene los datos de los
productos que tengan p_onhand = 0 o sea los productos que hay que renovar
para luego poner a la venta.
• Busque en la tabla producto todos los productos que ya no estén en stock y
los inserte en la tabla comprar_producto
• Nos devuelva la cantidad de productos que ya no se encuentran en stock;
CREATE OR REPLACE FUNCTION comprar_producto()
RETURNS int4
AS $$
DECLARE
cont_pro int4;
fila_pro producto%ROWTYPE;
BEGIN
SELECT COUNT(*) INTO cont_pro FROM producto WHERE p_onhand = 0;
FOR fila_pro IN SELECT * FROM producto WHERE p_onhand=0
LOOP
INSERT INTO ps_stock VALUES (fila_pro.p_code, fila_pro.p_descript);
END LOOP;
RETURN cont_pro;
6 [ POLITÉCNICO GANCOLOMBIANO EN ALIANZA CON WHITNEY INTERNATIONAL SYSTEM ]
END;
Language 'plpgsql';
Como ayuda para interpretar las líneas del procedimiento almacenado se observa que:
- DECLARE se utiliza para especificar las variables utilizadas en el procedimiento. Debe
especificarse tanto el nombre de la variable como su tipo de datos.
- IN / OUT indica si el parámetro es de entrada o de salida o de ambas.
- Data Type es uno de los tipos de datos SQL de procedimientos utilizado en el SGBD.
Los tipos de datos normalmente concuerdan con los tipos de datos utilizados en la
sentencia de creación de tabla del SGBD.
Disparadores
Un disparador es un código SQl de procedimientos que automáticamente es invocado por el
SGBD cuando ocurre un evento de manipulación de datos. Es útil recordar que:
• Un disparador siempre se invoca antes o después de que una fila de datos se
selecciona, inserta o actualiza.
• Un disparador siempre está asociado con una tabla de base de datos.
• Cada base de datos puede o no tener uno o más disparadores.
• Un disparador se ejecuta como parte de la transacción que lo activó.
Los disparadores son fundamentales para la operación y manejo apropiados de una base de
datos. Por ejemplo:
• Pueden utilizarse disparadores para hacer que se cumplan restricciones que pueden
ser aplicadas a niveles de diseño y ejecución de SGBD.
• Los disparadores agregan funcionalidad con la automatización de acciones críticas y
el suministro de advertencias y sugerencias apropiadas para la reutilización de
acciones de recuperación. De hecho, uno de los usos más comunes de los
disparadores es mejorar la aplicación de la integridad referencial.
[ BASE DE DATOS ] 7
• Pueden utilizarse disparadores para actualizar valores de tabla, insertar registros en la
tabla e invocar otros procedimientos almacenados.
Para ver cómo se crea y utiliza un disparador, se examinará el siguiente ejemplo:
Nuestra tabla PRODUCTO tiene la capacidad de almacenar la información más actual e
importante para nuestro sistema de control de compras, pero hay otro tipo de información
que no es capaz de almacenar (por lo menos ahora), la información del cambio de datos.
Nuestra tabla PRODUCTO no tiene memoria de los cambios que han sufrido sus tuplas, si
alguien viene y cambia el precio de venta (producto.p_price), no hay forma de obtener el
precio anterior.
Si alguien borra un PRODUCTO, tampoco sabremos que artículo ha sido borrado ni por quien.
Esto nos lleva a la primera gran área de utilización de los disparadores (triggers), la auditoria
de tablas.
Las acciones que debe realizar nuestro trigger son:
1. Necesitamos llevar un registro de todos los cambios relevantes en nuestra tabla
PRODUCTO, para empezar queremos tener un seguimiento de los cambios en los precios
de los PRODUCTOS.
2. También queremos almacenar en algún lugar todos aquellos PRODUCTOS que hayan
sido eliminados, también queremos guardar sus respectivos historiales de cambios.
Lo primero que vamos a hacer es crear una tabla que vaya a almacenar los cambios de precio
de nuestra tabla PRODUCTO, la llamaremos: producto_actualizado
CREATE TABLE producto_actualizado
(
pa_code int4 NOT NULL,
pa_descript varchar(35) NOT NULL,
pa_lastprice numeric(9,2) NOT NULL,
pa_newprice numeric(9,2) NOT NULL,
pa_user varchar(100) NOT NULL,
pa_date date NOT NULL,
CONSTRAINT pa_producto_fk FOREIGN KEY (pa_code) REFERENCES producto(p_code)
);
CREATE FUNCTION pa_producto_tri()
RETURNS trigger
AS $$
BEGIN
8 [ POLITÉCNICO GANCOLOMBIANO EN ALIANZA CON WHITNEY INTERNATIONAL SYSTEM ]
IF(TG_OP = 'UPDATE') THEN
IF(OLD.p_price != NEW.p_price) THEN
INSERT INTO producto_actualizado VALUES (
OLD.p_code, OLD.p_descript, OLD.p_price, NEW.p_price, current_user, current_date
);
END IF;
END IF;
RETURN NULL;
END;
$$
Language 'plpgsql';
CREATE TRIGGER actualizar_producto
AFTER UPDATE ON producto
FOR EACH ROW
EXECUTE PROCEDURE pa_producto_tri();
Como ayuda para interpretar las líneas del anterior código se observa que:
• Pueden existir varios bloques o sub‐bloques en la sección de sentencias de un bloque.
Los sub‐bloques pueden ser usados para ocultar las variables a los bloques más
externos.
• TG_OP: variable de tipo string que indica que tipo de evento está ocurriendo.
• current_user: es el nombre del usuario que está actualmente conectado a la base de
datos y que ejecuta las sentencias.
• current_date: es la fecha actual del servidor, no del cliente.
• NEW: variable compuesta que almacena los nuevos valores de la tupla que se está
modificando.
• OLD: variante compuesta que almacena los valores antiguos de la tupla que se está
modificando
• Normalmente una de las sentencias es el valor del retorno, usando la palabra RETURN.
• Un trigger se ejecuta:
1. antes o después de una inserción (INSERT)
[ BASE DE DATOS ] 9
2. antes o después de una actualización (UPDATE)
3. antes o después de un borrado (DELETE)
• Después de Actualizar (UPDATE) sobre la tabla PRODUCTO, para cada fila, ejecutar la
función pa_producto_tri.
CONCLUSIONES
• El código de SQL de procedimientos es ejecutado por el SGBD cuando es invocado
–directa o indirectamente‐ por el usuario final.
1.1. BIBLIOGRAFÍA
• C.J. Date, Introducción a los Sistemas de Bases de Datos, 5. ª edición, Adison Wesley
Iberoamericana, 1993.
• Korth y A. Siulberschatz, Fundamentos de Bases de Datos, 4. ª edición, McGraw‐Hill,
Madrid, 2002.
• Elmasri, R. & Navathe, S.B. “Fundamentals Of Database Systems” Third Edition.
Addison‐ Wesley Pubs. 2000.
• Rob, Peter.; Coronel, Carlos. “Sistemas de Bases de Datos: diseño, implementación y
administración”, Quinta Edición, THOMSON, 2002.
10 [ POLITÉCNICO GANCOLOMBIANO EN ALIANZA CON WHITNEY INTERNATIONAL SYSTEM ]