UD8 Programacion BD
UD8 Programacion BD
UD8 Programacion BD
Bases de datos
JCCA
[Unidad 8
Programación de
B.D con MySQL]
Sumario
1.- Introducción.................................................................................................................................. 4
1.1.- Procedimientos, funciones y triggers en MySQL....................................................................4
1.2.- Ventajas de su utilización.......................................................................................................5
2.- Variables y tipos de datos.............................................................................................................. 6
2.1 Variables de sesión...................................................................................................................7
3.- Cursores......................................................................................................................................... 8
4.- Procedimientos............................................................................................................................10
4.1.- DELIMETER...........................................................................................................................12
4.2.- Parámetros de entrada, salida y entrada/salida...................................................................13
5.- Funciones.....................................................................................................................................15
5.1.- Características de la función................................................................................................ 17
6.- Estructuras de control..................................................................................................................18
6.1.- Condicional IF.......................................................................................................................18
6.2.- Condicional CASE................................................................................................................. 19
6.3.- Instrucciones repetitivas: bucles..........................................................................................20
6.3.1.- LOOP.............................................................................................................................20
6.3.2.- REPEAT … UNTIL........................................................................................................... 20
6.3.3.- WHILE........................................................................................................................... 22
7.- Manejo de errores....................................................................................................................... 22
8.- Realizar transacciones con procedimientos almacenados...........................................................24
9.- Triggers........................................................................................................................................ 25
10.- Bibliografía.................................................................................................................................28
2
Unidad 8: Programación de bases de datos Bases de datos
OBJETIVOS
En esta unidad se pretende alcanzar los siguientes objetivos:
• Identificar las diversas formas de automatizar tareas.
• Identificar las herramientas disponibles para editar guiones.
• Definir y utilizar guiones para automatizar tareas.
• Utilizar estructuras de control de flujo.
• Aplicar las funciones proporcionadas por el sistema gestor.
• Definir funciones de usuario.
• Definir disparadores.
• Utilizar cursores.
• Desarrollar progresivamente actitudes profesionales como la importancia del trabajo en
equipo, la sistematicidad, el orden y la limpieza, la búsqueda de soluciones creativas y el
uso de un lenguaje técnico cada vez más preciso.
3
Unidad 8: Programación de bases de datos Bases de datos
1.- Introducción
La ejecución de sentencias SQL de forma independiente implica una comunicación continua entre
la aplicación y la base de datos, con el consiguiente tráfico de red. Por ese motivo, ISO definió el
estándar SQL/PSM (SQL/persistent stored modules, SQL/módulos almacenados persistentes),
integrado en el estándar ANSI/SQL desde 1999.
En esta unidad vamos a estudiar los procedimientos, funciones y triggers de MySQL, que son
objetos que contienen código SQL y se almacenan asociados a una base de datos.
• Procedimientos almacenados: El más común de las rutinas almacenados. Resuelven un
determinado problema cuando son llamadas y pueden aceptar varios parámetros de
entrada y devolver varios de salida.
• Funciones almacenadas: Similares a los procedimientos salvo que sólo devuelven un valor
como parámetro de salida. La ventaja que presentan las funciones es que pueden ser
utilizadas dentro de instrucciones SQL y por tanto aumentan considerablemente las
capacidades de este lenguaje.
• Triggers o desencadenadores o disparadores: Son rutinas que se activan (“disparan”) ante
un determinado suceso ocurrido dentro de la base de datos.
4
Unidad 8: Programación de bases de datos Bases de datos
Procesamiento de datos
Bloques BEGIN/END con instrucciones de control (codicionales
y repetitivas)
Fin
Con la instrucción RETURN para devolver un valor en el caso
de funciones almacenadas
• Mayor seguridad y robustez en la base de datos. Es posible limitar los permisos de acceso
de usuario a las rutinas almacenadas y no a las tablas directamente. De este modo
evitamos problemas derivados de una aplicación mal programada que haga un mal uso de
las tablas.
• Mejor mantenimiento de las aplicaciones que acceden a las rutinas almacenadas y por
tanto disminución de la posibilidad de aparición de errores. En lugar de que cada aplicación
cliente disponga de sus propios programas para realizar operaciones de inserción de
consulta o actualización, las rutinas almacenadas permiten centralizar los métodos de
acceso y actualización anteriores presentando una interfaz común para todos los
programas.
• Mayor portabilidad de las aplicaciones (relacionada con el punto anterior) puesto que la
lógica de la aplicación ya queda implementada en las rutinas almacenados permitiendo al
programador centrarse sólo en su interfaz.
• Debido a la fuerte integración con el lenguaje SQL, no se necesita de ningún tipo de
conector o driver como ODBC (Open DataBase Connectivity) o JDBC (Java DataBase
Connectivity) para poder construir y ejecutar sentencias SQL. Bastará agrupar estas últimas
bajo una rutina almacenada que se llamará en el momento en el que se necesite.
• Reducción del tráfico de red. El cliente llama a un procedimiento del servidor enviándole
unos datos. Éste los recibe y tras procesarlos devuelve unos resultados. Por la red no viajan
nada más que los datos.
5
Unidad 8: Programación de bases de datos Bases de datos
La declaración de variables se realiza antes del comienzo de las instrucciones (y antes de los
cursores y manejadores de errores que se veremos mas adelante en esta unidad). Se utiliza la
sintaxis siguiente:
Se pueden declarar varias variables del mismo tipo seguidas y separadas por comas. Al mismo
tiempo que se declaran las variables se pueden definir asignándoles un valor inicial mediante la
cláusula DEFAULT; si no se les asigna ninguno entonces las variables quedan definidas al valor
NULL.
En el momento de la declaración hay que indicar el tipo de datos1 de la variable; pueden utilizarse
cualquiera de los que hemos empleado en la unidad 5 para la creación de las tablas.
Todas las variables que se pueden utilizar deben ser escalares, es decir, un solo valor.
En este caso y a diferencia de otros lenguajes es necesario especificar la sentencia SET para asignar
valores a las variables. Se puede en una sola instrucción realizar varias asignaciones.
Mediante las variables se pueden recuperar datos de una consulta SQL. Si la consulta devuelve un
único valor, podemos utilizar SET
Ejemplo:
1 Unidad 5. Apartado 4
6
Unidad 8: Programación de bases de datos Bases de datos
Ejemplo:
Podemos emplear variables para guardar información de una orden SQL, pero debemos
asegurarnos que solamente devuelve una fila. En este caso empleamos la cláusula INTO dentro del
SELECT.
Ejemplo:
USE bd_ud6_a1;
SELECT dnacimiento INTO @fechaNacimiento
FROM Talumno
WHERE pkid=2;
SELECT @fechaNacimiento;
Podemos emplear varias variables a la vez. Cada columna del SELECT (y en el orden en el que se
encuentran) se va a corresponder con una variable del INTO (en el mismo orden que el SELECT). El
número de columnas y variables debe de ser la misma.
Ejemplo
USE bd_ud6_a1;
SELECT cNombre, dnacimiento INTO @nombre, @fechaNacimiento
FROM Talumno
WHERE pkid=2;
SELECT @nombre,@fechaNacimiento;
7
Unidad 8: Programación de bases de datos Bases de datos
3.- Cursores
También podemos recuperar los datos de una consulta SQL independientemente del número de
campos y registros que devuelva la consulta, mediante el uso de un cursor.
Cuando declaramos un cursor dentro de un procedimiento almacenado debe aparecer antes de las
declaraciones de los manejadores de errores (HANDLER) y después de la declaración de variables
locales.
Los cursores son estructuras de almacenamiento volátil que albergan el resultado de una
consulta y permiten recorrer todos sus registros de forma secuencial.
2) Abrir el cursor
OPEN nombre_del_cursor;
3) Recorrer el cursor
Cada vez que se ejecuta la sentencia FETCH se lee un nuevo registro y el puntero del cursor avanza
una posición. Si la consulta devuelve varios campos sus valores se pueden almacenar en varias
variables, separadas por comas.
Para recorrer un cursor se utiliza un bucle2 que se ejecuta hasta que se terminan de leer todas las
filas. Cuando se está recorriendo un cursor y no quedan filas por recorrer se lanza el error NOT
FOUND, que se corresponde con el valor SQLSTATE ‘02000’. Por eso cuando estemos trabajando con
cursores será necesario declarar un handler para manejar este error, como por ejemplo:
DECLARE CONTINUE HANDLER FOR NOT FOUND SET fin = TRUE;
4. Cerrar el cursor
Cuando hemos terminado de trabajar con un cursor tenemos que cerrarlo.
CLOSE nombre_del_cursor
8
Unidad 8: Programación de bases de datos Bases de datos
Recorriendo el cursor
Después del OPEN, el cursor se sitúa justo antes de la primera Al realizar la primera orden de FETCH podemos recuperar los
fila de resultados del SELECT datos de la primera fila.
Al realizar el siguiente FETCH podemos recuperar los datos de la Al realizar el siguiente FETCH podemos recuperar los datos de la
siguiente fila (fila 2) siguiente fila (fila3)
Al realizar el siguiente FETCH podemos recuperar los datos de la Al realizar el siguiente FETCH podemos recuperar los datos de la
siguiente fila (fila 4) siguiente fila (fila 5)
9
Unidad 8: Programación de bases de datos Bases de datos
Ejemplo:
4.- Procedimientos
Un procedimiento almacenado es un conjunto de instrucciones SQL que se almacena asociado a
una base de datos. Es un objeto que se crea con la sentencia CREATE PROCEDURE y se invoca con la
sentencia CALL. Un procedimiento puede tener cero o muchos parámetros de entrada y cero o
muchos parámetros de salida
Sintaxis
CREATE
[DEFINER = { user | CURRENT_USER }]
PROCEDURE sp_name ([proc_parameter[,...]])
[characteristic ...] routine_body
proc_parameter:
[ IN | OUT | INOUT ] param_name type
func_parameter:
param_name type
type:
Any valid MySQL data type
characteristic:
COMMENT 'string'
| LANGUAGE SQL
| [NOT] DETERMINISTIC
| { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }
| SQL SECURITY { DEFINER | INVOKER }
routine_body:
Valid SQL routine statement
10
Unidad 8: Programación de bases de datos Bases de datos
donde:
• sp_name, es el nombre de la rutina almacenada
• parameter, son los parámetros que en general se caracterizan por un tipo y un nombre. El
tipo puede ser de entrada (IN), salida (OUT) o entrada/salida (INOUT)
• routine_body, es el cuerpo de la rutina formado generalmente por sentencias SQL. En caso
de haber más de una deben ir dentro de un bloque delimitado por sentencias BEGIN y END.
• DETERMINISTIC, indica si es determinista o no, es decir, si siempre produce el mismo
resultado
• CONTAINS SQL/NO SQL, especifica si contiene sentencias SQL o no
• MODIFIES SQL DATA/READS SQL DATA, indica si las sentencias modifican o no los datos.
• SQL SECURITY, determina si debe ejecutarse con permisos del creador (DEFINER) o del que
invoca (INVOKER).
Todos los procedimientos o funciones se crean asociados a una base de datos que será la activa
en ese momento o la que pongamos como prefijo en el nombre del mismo.
Como hemos comentado, un procedimiento se crea dentro de una base de datos concreta. Si no
indicamos la base de datos, lo hará en la base de datos activa (recordar que en MysqlWorkBench
es la que se visualiza en negrilla). Cuando ejecutemos la orden CREATE PROCEDURE, podemos
cambiar antes la base de datos activa con la orden SQL: USE nombre_bd. Otra forma de indicar en
qué base de datos debe crearse el procedimiento es anteponiendo al nombre del mismo, el
nombre de la base de datos seguido por un punto, de la forma: CREATE PROCEDURE
nombreBD.nombreProcedimiento()
11
Unidad 8: Programación de bases de datos Bases de datos
El comando que permite ver información de los procedimientos y funciones así como las líneas de
código es el siguiente:
CALL nombre_prodedimiento([parámetros]);
4.1.- DELIMETER
Para definir un procedimiento almacenado es necesario modificar temporalmente el carácter
separador que se utiliza para delimitar las sentencias SQL.
La palabra clave DELIMITER indica el carácter de comienzo y fin del procedimiento. Típicamente
sería un (;) pero dado que necesitamos un (;) para cada sentencia SQL dentro del procedimiento es
conveniente usar otro carácter, normalmente se usan $$. En los ejemplos que vamos a realizar en
esta unidad vamos a utilizar los caracteres $$ para delimitar las instrucciones SQL, pero seria
posible utilizar cualquier otro carácter.
Mysql toma como delimitador de sentencias SQL el punto y coma por defecto. Quiere decir que
cada vez que encuentra un punto y coma intenta ejecutar la orden SQL. Debemos de ver al
procedimiento almacenado como un todo, como si fuera una única instrucción que queremos que
Mysql ejecute entera. Si mantubiesemos el punto y coma para el procedimiento y quisiésemos
poner una orden SQL dentro del procedimiento almacenado, intentará ejecutarla y no la
interpretará como parte del procedimiento almacenado; por este motivo tenemos que cambiarlo.
12
Unidad 8: Programación de bases de datos Bases de datos
CALL bd_ud6_p1.hola_mundo();
COMMENT 'comentario'
Esto nos permitirá, una vez creada la rutina, que nos muestre la
descripción/comentario al pulsar sobre ella.
Actividad 1 (1 a 4)
13
Unidad 8: Programación de bases de datos Bases de datos
14
Unidad 8: Programación de bases de datos Bases de datos
SET @np=7521;
CALL bd_ud6_a2.num_dep_empleado(@np);
SELECT @np AS "Nº de Dpto.";
Actividad 1 (5 a 11)
5.- Funciones
Las funciones almacenadas son similares a los procedimientos salvo que sólo devuelven un valor.
Por tanto gran parte de lo que se ha expuesto en el apartado de procedimientos es válido aquí.
La devolución del valor se produce utilizando la cláusula RETURN y no mediante variables OUT o
INOUT. No aparece en la sintaxis, pues no se puede utilizar, los parámetros IN, OUT, INOUT. Todos
los parámetros pasados a la función se definen implícitamente del tipo IN.
La ventaja que presentan las funciones es que pueden ser utilizadas dentro de instrucciones SQL y
por tanto aumentan considerablemente las capacidades de este lenguaje.
15
Unidad 8: Programación de bases de datos Bases de datos
Sintaxis:
CREATE
[DEFINER = { user | CURRENT_USER }]
FUNCTION sp_name ([func_parameter[,...]])
RETURNS type
[characteristic ...] routine_body
func_parameter:
param_name type
type:
Any valid MySQL data type
characteristic:
COMMENT 'string'
| LANGUAGE SQL
| [NOT] DETERMINISTIC
| { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }
| SQL SECURITY { DEFINER | INVOKER }
routine_body:
Valid SQL routine statement
Ejemplo:
CALL bd_ud6_a2.salario_empleado(7499);
16
Unidad 8: Programación de bases de datos Bases de datos
• READS SQL DATA: Indica que la función no modifica los datos de la base de datos y que
contiene sentencias de lectura de datos, como la sentencia SELECT.
• MODIFIES SQL DATA: Indica que la función sí modifica los datos de la base de datos y que
contiene sentencias como INSERT, UPDATE o DELETE.
Para poder crear una función en MySQL es necesario indicar al menos una de estas tres
características:
• DETERMINISTIC
• NO SQL
• READS SQL DATA
Si no se indica al menos una de estas características obtendremos un error.
Parámetros de entrada: recuerda, en una función todos los parámetros son de entrada, por lo
tanto, no será necesario utilizar la palabra reservada IN delante del nombre de los parámetros.
Actividad 2
17
Unidad 8: Programación de bases de datos Bases de datos
6.1.- Condicional IF
Actividad 3 (1 y 2)
18
Unidad 8: Programación de bases de datos Bases de datos
CASE expresión
WHEN valor1 THEN
instrucciones
[WHEN valor2 THEN
instrucciones ...]
[ELSE
instrucciones]
END CASE;
CASE
WHEN condición1 THEN
instrucciones
[WHEN condición2 THEN
instrucciones ...]
[ELSE
instrucciones]
END CASE;
19
Unidad 8: Programación de bases de datos Bases de datos
Actividad 3 (3 y 4)
6.3.- Instrucciones repetitivas: bucles
6.3.1.- LOOP
[etiqueta:] LOOP
instrucciones
END LOOP [etiqueta];
Todas las instrucciones comprendidas entre las palabras reservadas LOOP Y END LOOP (bucle), se
ejecutan un número de veces hasta que la ejecución del bucle se encuentra con la instrucción
LEAVE etiqueta. En ese momento se abandona el bucle.
La sentencia ITERATE etiqueta se utiliza para forzar que la ejecución del bucle termine en el
momento donde se encuentra con esta instrucción y continúe por el principio del bucle
6.3.2.- REPEAT … UNTIL
[etiqueta:] REPEAT
instrucciones
UNTIL expresión
END REPEAT [etiqueta];
Las instrucciones se ejecutarán hasta que sea cierta la expresión. Por lo menos el conjunto de
instrucciones se ejecuta una vez pues la evaluación de la expresión se hace posterior a la ejecución
de las instrucciones
20
Unidad 8: Programación de bases de datos Bases de datos
21
Unidad 8: Programación de bases de datos Bases de datos
6.3.3.- WHILE
[etiqueta:] WHILE condición DO
instrucciones
END WHILE [etiqueta];
Actividad 3 (5 a 8)
22
Unidad 8: Programación de bases de datos Bases de datos
Como hemos ya hemos visto en puntos anteriormente, este comportamiento se puede controlar
definiendo los manejadores de error o handlers.
Una handler es un bloque de instrucciones SQL que se ejecuta cuando se verifica una condición
tras una excepción (error) generada por el servidor
Las acciones posibles que podemos seleccionar para el manejador puede ser de tres tipos:
• CONTINUE: La excepción o error generado no interrumpe el código de la rutina, es decir la
ejecución de la rutina continua.
• EXIT: Permite poner fin al bloque de instrucciones o rutina en el que se genera la
excepción.
• UNDO: No está soportado en MySQL
23
Unidad 8: Programación de bases de datos Bases de datos
Actividad 4
En lugar de tener un manejador para cada tipo de error, podemos tener uno común para todos los
casos:
24
Unidad 8: Programación de bases de datos Bases de datos
Actividad 5
9.- Triggers
Los triggers, también llamados desencadenadores o disparadores, son rutinas almacenadas que
se ejecutan (“disparan”) automáticamente en respuesta a algún suceso que ocurre en la base de
datos. En MySQL ese tipo de suceso se corresponde con alguna instrucción DML (INSERT, UPDATE,
DELETE) sobre alguna tabla.
Suponen un mecanismo para asegurar la intregridad de los datos. Se emplean también como un
método para realizar operaciones de auditoría sobre la base de datos. No hay que abusar de su
utilización pues ello puede traer consigo una sobrecarga del sistema y por tanto un bajo
rendimiento del mismo.
Donde:
• DEFINER ={cuenta_usuario | CURRENT_USER } indica con qué privilegios se ejecutan las
instrucciones del trigger. La opción por defecto es CURRENT_USER, que indica que las
instrucciones se ejecutan con los privilegios del usuario que lanzó la instrucción de creación
del trigger. La opción cuenta_usuario por otro lado hace que el trigger se ejecute con los
privilegios de dicha cuenta.
• Nombre del trigger. Sigue las mismas normas que para nombrar cualquier objeto de la base
de datos.
• BEFORE | AFTER. Señala cuando se ejecuta el trigger, antes (before) o después (alter) de la
instrucción DML que lo provocó.
• UPDATE | INSERT | DELETE. Define la operación DML asociada al trigger.
• FOR EACH ROW. Indica que el trigger se ejecutará por cada fila de la tabla afectada por la
operación DML. Esto es, si tenemos asociado un trigger a la operación de borrado de una
tabla y se eliminan con una sola instrucción 6 filas de ésta última, el trigger se ejecutará 6
veces, una por cada fila eliminada. Otros gestores de bases de datos (así como futuras
implementaciones de MySQL) consideran también el otro estándar
https://dev.mysql.com/doc/refman/5.7/en/declare-handler.htmlde ANSI, la cláusula FOR
EACH STATEMENT. Con esta segunda opción, el trigger se ejecutaría por cada operación
DML realizada; en el ejemplo anterior, la instrucción de borrado daría lugar a que sólo se
ejecutara el trigger una sola vez en lugar de 6 (filas afectadas) con esta futura cláusula.
25
Unidad 8: Programación de bases de datos Bases de datos
• Cuerpo del trigger: El conjunto de instrucciones que forman esta rutina almacenada. Si son
más de una irán en un bloque BEGIN … END. No pueden contener una instrucción CALL de
llamada a un procedimiento almacenado
En el ejemplo anterior, crea una fila nueva en la tabla Talumnos como consecuencia de la
instrucción de la línea 24 y otra también idéntica en la tabla Talumnos_replica debido a la
ejecución automática del conjunto de instrucciones del trigger.
Consideraciones:
Debido a que un disparador está asociado con una tabla en particular, no se pueden tener
múltiples disparadores con el mismo nombre dentro de una tabla. También se debería tener en
cuenta que el espacio de nombres de los disparadores puede cambiar en el futuro de un nivel de
tabla a un nivel de base de datos, es decir, los nombres de disparadores ya no sólo deberían ser
únicos para cada tabla sino para toda la base de datos. Para una mejor compatibilidad con
desarrollos futuros, se debe intentar emplear nombres de disparadores que no se repitan dentro
de la base de datos.
26
Unidad 8: Programación de bases de datos Bases de datos
Adicionalmente al requisito de nombres únicos de disparador en cada tabla, hay otras limitaciones
en los tipos de disparadores que pueden crearse. En particular, no se pueden tener dos
disparadores para una misma tabla que sean activados en el mismo momento y por el mismo
evento. Por ejemplo, no se pueden definir dos BEFORE INSERT o dos AFTER UPDATE en una misma
tabla. Es improbable que esta sea una gran limitación, porque es posible definir un disparador que
ejecute múltiples sentencias empleando el constructor de sentencias compuestas BEGIN ... END
luego de FOR EACH ROW. (Más adelante en esta sección puede verse un ejemplo).
También hay limitaciones sobre lo que puede aparecer dentro de la sentencia que el disparador
ejecutará al activarse:
• El disparador no puede utilizar sentencias que inicien o finalicen una transacción, tal
como START TRANSACTION, COMMIT, o ROLLBACK.
Las palabras clave OLD y NEW permiten acceder a columnas en los registros afectados por un
disparador. (OLD y NEW no son sensibles a mayúsculas). En un disparador para INSERT, solamente
puede utilizarse NEW.nom_col; ya que no hay una versión anterior del registro. En un disparador
para DELETE sólo puede emplearse OLD.nom_col, porque no hay un nuevo registro. En un
disparador para UPDATE se puede emplear OLD.nom_col para referirse a las columnas de un
registro antes de que sea actualizado, y NEW.nom_col para referirse a las columnas del registro
luego de actualizarlo.
Una columna precedida por OLD es de sólo lectura. Es posible hacer referencia a ella pero no
modificarla. Una columna precedida por NEW puede ser referenciada si se tiene el privilegio
SELECT sobre ella. En un disparador BEFORE, también es posible cambiar su valor con SET
NEW.nombre_col = valor si se tiene el privilegio de UPDATE sobre ella. Esto significa que un
disparador puede usarse para modificar los valores antes que se inserten en un nuevo registro o se
empleen para actualizar uno existente.
27
Unidad 8: Programación de bases de datos Bases de datos
Dicho todo lo anterior, diremos que dentro del trigger puedo acceder a dos 'alias' de la tabla a la
que afecta el trigger con las mismas columnas que la tabla original:
NEW: Tabla que posee los datos de cada columna con los nuevos valores.
OLD: Tabla que posee los datos de cada columna con los valores antiguos.
Operaciones
UPDATE:
NEW: Valores nuevos
OLD: Valores antiguos
INSERT
NEW: Valores nuevos
OLD: NO EXISTE
DELETE
NEW: NO EXISTE
OLD: Valores antiguos
Actividad 6
Prácticas
10.- Bibliografía
• Bases de datos. Editorial Garceta
• https://mariadb.com/kb/en/documentation/
• https://mariadb.com/kb/es/usando-mariadb/
• https://dev.mysql.com/doc/refman/8.0/en/
28