Trigger Procedimientos Funciones
Trigger Procedimientos Funciones
Trigger Procedimientos Funciones
Triggers, procedimientos
y funciones en MySQL
1
Unidad 12. Triggers, procedimientos y funciones en MySQL IES Celia Viñas (Almería) - 2018/2019
2 Licencia 32
1.1 Procedimientos
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
3
Unidad 12. Triggers, procedimientos y funciones en MySQL IES Celia Viñas (Almería) - 2018/2019
1.2 Funciones
CREATE
[DEFINER = { user | CURRENT_USER }]
FUNCTION sp_name ([func_parameter[,...]])
RETURNS type
[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
1.3.1.1 IF-THEN-ELSE
1.3.1.2 CASE
CASE case_value
WHEN when_value THEN statement_list
[WHEN when_value THEN statement_list] ...
[ELSE statement_list]
END CASE
CASE
WHEN search_condition THEN statement_list
[WHEN search_condition THEN statement_list] ...
[ELSE statement_list]
END CASE
1.3.2.1 LOOP
[begin_label:] LOOP
statement_list
END LOOP [end_label]
Ejemplo:
Ejemplo:
DELIMITER $$
DROP PROCEDURE IF EXISTS ejemplo_bucle_loop$$
CREATE PROCEDURE ejemplo_bucle_loop(IN tope INT, OUT suma INT)
BEGIN
DECLARE contador INT;
SET contador = 1;
SET suma = 0;
bucle: LOOP
IF contador > tope THEN
LEAVE bucle;
END IF;
DELIMITER ;
CALL ejemplo_bucle_loop(10, @resultado);
SELECT @resultado;
1.3.2.2 REPEAT
[begin_label:] REPEAT
statement_list
UNTIL search_condition
END REPEAT [end_label]
Ejemplo:
DELIMITER $$
DROP PROCEDURE IF EXISTS ejemplo_bucle_repeat$$
CREATE PROCEDURE ejemplo_bucle_repeat(IN tope INT, OUT suma INT)
BEGIN
DECLARE contador INT;
SET contador = 1;
SET suma = 0;
REPEAT
SET suma = suma + contador;
SET contador = contador + 1;
UNTIL contador > tope
END REPEAT;
END
$$
DELIMITER ;
CALL ejemplo_bucle_repeat(10, @resultado);
SELECT @resultado;
1.3.2.3 WHILE
Ejemplo:
DELIMITER $$
DROP PROCEDURE IF EXISTS ejemplo_bucle_while$$
CREATE PROCEDURE ejemplo_bucle_while(IN tope INT, OUT suma INT)
BEGIN
DECLARE contador INT;
SET contador = 1;
SET suma = 0;
DELIMITER ;
CALL ejemplo_bucle_while(10, @resultado);
SELECT @resultado;
handler_action:
CONTINUE
| EXIT
| UNDO
condition_value:
mysql_error_code
| SQLSTATE [VALUE] sqlstate_value
| condition_name
| SQLWARNING
| NOT FOUND
| SQLEXCEPTION
En este ejemplo estamos declarando un handler que se ejecutará cuando se produzca el error 1051 de MySQL,
que ocurre cuando se intenta acceder a una tabla que no existe en la base de datos. En este caso la acción del
handler es CONTINUE lo que quiere decir que después de ejecutar las instrucciones especificadas en el cuerpo
del handler el procedimiento almacenado continuará su ejecución.
También podemos indicar el valor de la variable SQLSTATE. Por ejemplo, cuando se intenta acceder a una tabla
que no existe en la base de datos, el valor de la variable SQLSTATE es 42S02.
Es equivalente a indicar todos los valores de SQLSTATE que empiezan con 01.
Es equivalente a indicar todos los valores de SQLSTATE que empiezan con 02. Lo usaremos cuando estemos
trabajando con cursores para controlar qué ocurre cuando un cursor alcanza el final del data set. Si no hay más
filas disponibles en el cursor, entonces ocurre una condición de NO DATA con un valor de SQLSTATE igual a
02000. Para detectar esta condición podemos usar un handler para controlarlo.
Es equivalente a indicar todos los valores de SQLSTATE que empiezan por 00, 01 y 02.
-- Paso 1
DROP DATABASE IF EXISTS test;
CREATE DATABASE test;
USE test;
-- Paso 2
CREATE TABLE test.t (s1 INT, PRIMARY KEY (s1));
-- Paso 3
DELIMITER $$
CREATE PROCEDURE handlerdemo ()
BEGIN
DECLARE CONTINUE HANDLER FOR SQLSTATE '23000' SET @x = 1;
SET @x = 1;
INSERT INTO test.t VALUES (1);
SET @x = 2;
INSERT INTO test.t VALUES (1);
SET @x = 3;
END
$$
DELIMITER ;
CALL handlerdemo();
SELECT @x;
-- Paso 1
DROP DATABASE IF EXISTS test;
CREATE DATABASE test;
USE test;
-- Paso 2
CREATE TABLE test.t (s1 INT, PRIMARY KEY (s1));
-- Paso 3
DELIMITER $$
CREATE PROCEDURE handlerdemo ()
BEGIN
DECLARE EXIT HANDLER FOR SQLSTATE '23000' SET @x = 1;
SET @x = 1;
INSERT INTO test.t VALUES (1);
SET @x = 2;
INSERT INTO test.t VALUES (1);
SET @x = 3;
END
$$
DELIMITER ;
CALL handlerdemo();
SELECT @x;
Podemos utilizar el manejo de errores para decidir si hacemos ROLLBACK de una transacción. En el siguiente
ejemplo vamos a capturar los errores que se produzcan de tipo SQLEXCEPTION y SQLWARNING.
Ejemplo:
DELIMITER $$
CREATE PROCEDURE transaccion_en_mysql()
BEGIN
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
-- ERROR
ROLLBACK;
END;
START TRANSACTION;
-- Sentencias SQL
COMMIT;
END
$$
En lugar de tener un manejador para cada tipo de error, podemos tener uno común para todos los casos.
DELIMITER $$
CREATE PROCEDURE transaccion_en_mysql()
BEGIN
DECLARE EXIT HANDLER FOR SQLEXCEPTION, SQLWARNING
BEGIN
-- ERROR, WARNING
ROLLBACK;
END;
START TRANSACTION;
-- Sentencias SQL
COMMIT;
END
$$
1.6 Cursores
Los cursores nos permiten almacenar una conjunto de filas de una tabla en una estructura de datos que pode-
mos ir recorriendo de forma secuencial.
• Asensitive: The server may or may not make a copy of its result table.
• Read only: son de sólo lectura. No permiten actualizar los datos.
• Nonscrollable: sólo pueden ser recorridos en una dirección y no podemos saltarnos filas.
Cuando declaramos un cursor dentro de un procedimiento almacenado debe aparecer antes de las declaracio-
nes de los manejadores de errores (HANDLER) y después de la declaración de variables locales.
Las operaciones que podemos hacer con los cursores son las siguientes:
1.6.1.1 DECLARE
El primer paso que tenemos que hacer para trabajar con cursores es declararlo. La sintaxis para declarar un
cursor es:
1.6.1.2 OPEN
Una vez que hemos declarado un cursor tenemos que abrirlo con OPEN.
OPEN cursor_name
1.6.1.3 FETCH
Una vez que el cursor está abierto podemos ir obteniendo cada una de las filas con FETCH. La sintaxis es la
siguiente:
Cuando se está recorriendo un cursor y no quedan filas por recorrer se lanza el error NOT FOUND, que se co-
rresponde con el valor SQLSTATE «02000». Por eso cuando estemos trabajando con cursores será necesario
declarar un handler para manejar este error.
1.6.1.4 CLOSE
CLOSE cursor_name
Ejemplo:
-- Paso 1
DROP DATABASE IF EXISTS test;
CREATE DATABASE test;
USE test;
-- Paso 2
CREATE TABLE t1 (
id INT UNSIGNED PRIMARY KEY,
data VARCHAR(16)
);
CREATE TABLE t2 (
i INT UNSIGNED
);
CREATE TABLE t3 (
data VARCHAR(16),
i INT UNSIGNED
);
-- Paso 3
DELIMITER $$
DROP PROCEDURE IF EXISTS curdemo$$
CREATE PROCEDURE curdemo()
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE a CHAR(16);
DECLARE b, c INT;
DECLARE cur1 CURSOR FOR SELECT id,data FROM test.t1;
DECLARE cur2 CURSOR FOR SELECT i FROM test.t2;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN cur1;
OPEN cur2;
read_loop: LOOP
FETCH cur1 INTO b, a;
FETCH cur2 INTO c;
IF done THEN
LEAVE read_loop;
END IF;
IF b < c THEN
INSERT INTO test.t3 VALUES (a,b);
ELSE
INSERT INTO test.t3 VALUES (a,c);
END IF;
END LOOP;
CLOSE cur1;
CLOSE cur2;
END
-- Paso 4
DELIMITER ;
CALL curdemo();
DELIMITER $$
DROP PROCEDURE IF EXISTS curdemo$$
CREATE PROCEDURE curdemo()
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE a CHAR(16);
DECLARE b, c INT;
DECLARE cur1 CURSOR FOR SELECT id,data FROM test.t1;
DECLARE cur2 CURSOR FOR SELECT i FROM test.t2;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN cur1;
OPEN cur2;
CLOSE cur1;
CLOSE cur2;
END;
1.7 Triggers
CREATE
[DEFINER = { user | CURRENT_USER }]
TRIGGER trigger_name
trigger_time trigger_event
ON tbl_name FOR EACH ROW
[trigger_order]
trigger_body
Un trigger es un objeto de la base de datos que está asociado con una tabla y que se activa cuando ocurre un
evento sobre la tabla.
• INSERT: El trigger se activa cuando se inserta una nueva fila sobre la tabla asociada.
• UPDATE: El trigger se activa cuando se actualiza una fila sobre la tabla asociada.
• DELETE: El trigger se activa cuando se elimina una fila sobre la tabla asociada.
Ejemplo:
Crea una base de datos llamada test que contenga una tabla llamada alumnos con las siguientes columnas.
Tabla alumnos:
Una vez creada la tabla escriba dos triggers con las siguientes características:
• Trigger 1: trigger_check_nota_before_insert
– Se ejecuta sobre la tabla alumnos.
– Se ejecuta antes de una operación de inserción.
– Si el nuevo valor de la nota que se quiere insertar es negativo, se guarda como 0.
– Si el nuevo valor de la nota que se quiere insertar es mayor que 10, se guarda como 10.
• Trigger2 : trigger_check_nota_before_update
– Se ejecuta sobre la tabla alumnos.
– Se ejecuta antes de una operación de actualización.
– Si el nuevo valor de la nota que se quiere actualizar es negativo, se guarda como 0.
– Si el nuevo valor de la nota que se quiere actualizar es mayor que 10, se guarda como 10.
Una vez creados los triggers escriba varias sentencias de inserción y actualización sobre la tabla alumnos y
verifica que los triggers se están ejecutando correctamente.
-- Paso 1
DROP DATABASE IF EXISTS test;
CREATE DATABASE test;
USE test;
-- Paso 2
CREATE TABLE alumnos (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
nombre VARCHAR(50) NOT NULL,
apellido1 VARCHAR(50) NOT NULL,
apellido2 VARCHAR(50),
nota FLOAT
);
-- Paso 3
DELIMITER $$
DROP TRIGGER IF EXISTS trigger_check_nota_before_insert$$
CREATE TRIGGER trigger_check_nota_before_insert
BEFORE INSERT
ON alumnos FOR EACH ROW
BEGIN
IF NEW.nota < 0 THEN
set NEW.nota = 0;
ELSEIF NEW.nota > 10 THEN
set NEW.nota = 10;
END IF;
END
DELIMITER $$
DROP TRIGGER IF EXISTS trigger_check_nota_before_update$$
CREATE TRIGGER trigger_check_nota_before_update
BEFORE UPDATE
ON alumnos FOR EACH ROW
BEGIN
IF NEW.nota < 0 THEN
set NEW.nota = 0;
ELSEIF NEW.nota > 10 THEN
set NEW.nota = 10;
END IF;
END
-- Paso 4
DELIMITER ;
INSERT INTO alumnos VALUES (1, 'Pepe', 'López', 'López', -1);
INSERT INTO alumnos VALUES (2, 'María', 'Sánchez', 'Sánchez', 11);
INSERT INTO alumnos VALUES (3, 'Juan', 'Pérez', 'Pérez', 8.5);
-- Paso 5
SELECT * FROM alumnos;
-- Paso 6
UPDATE alumnos SET nota = -4 WHERE id = 3;
UPDATE alumnos SET nota = 14 WHERE id = 3;
UPDATE alumnos SET nota = 9.5 WHERE id = 3;
-- Paso 7
SELECT * FROM alumnos;
1.8 Ejercicios
1. Escribe un procedimiento que no tenga ningún parámetro de entrada ni de salida y que muestre el texto
¡Hola mundo!.
2. Escribe un procedimiento que reciba un número real de entrada y muestre un mensaje indicando si el
número es positivo, negativo o cero.
3. Modifique el procedimiento diseñado en el ejercicio anterior para que tenga un parámetro de entrada,
con el valor un número real, y un parámetro de salida, con una cadena de caracteres indicando si el nú-
mero es positivo, negativo o cero.
4. Escribe un procedimiento que reciba un número real de entrada, que representa el valor de la nota de
un alumno, y muestre un mensaje indicando qué nota ha obtenido teniendo en cuenta las siguientes
condiciones:
• [0,5) = Insuficiente
• [5,6) = Aprobado
• [6, 7) = Bien
• [7, 9) = Notable
• [9, 10] = Sobresaliente
• En cualquier otro caso la nota no será válida.
5. Modifique el procedimiento diseñado en el ejercicio anterior para que tenga un parámetro de entrada,
con el valor de la nota en formato numérico y un parámetro de salida, con una cadena de texto indicando
la nota correspondiente.
6. Resuelva el procedimiento diseñado en el ejercicio anterior haciendo uso de la estructura de control CASE
.
7. Escribe un procedimiento que reciba como parámetro de entrada un valor numérico que represente un
día de la semana y que devuelva una cadena de caracteres con el nombre del día de la semana corres-
pondiente. Por ejemplo, para el valor de entrada 1 debería devolver la cadena lunes.
1. Escribe un procedimiento que reciba el nombre de un país como parámetro de entrada y realice una
consulta sobre la tabla cliente para obtener todos los clientes que existen en la tabla de ese país.
2. Escribe un procedimiento que reciba como parámetro de entrada una forma de pago, que será una cade-
na de caracteres (Ejemplo: PayPal, Transferencia, etc). Y devuelva como salida el pago de máximo va-
lor realizado para esa forma de pago. Deberá hacer uso de la tabla pago de la base de datos jardineria.
3. Escribe un procedimiento que reciba como parámetro de entrada una forma de pago, que será una cade-
na de caracteres (Ejemplo: PayPal, Transferencia, etc). Y devuelva como salida los siguientes valores
teniendo en cuenta la forma de pago seleccionada como parámetro de entrada:
11. Utilice un bucle REPEAT para resolver el procedimiento del ejercicio anterior.
12. Utilice un bucle LOOP para resolver el procedimiento del ejercicio anterior.
1. Escribe una función que reciba un número entero de entrada y devuelva TRUE si el número es par o FALSE
en caso contrario.
2. Escribe una función que devuelva el valor de la hipotenusa de un triángulo a partir de los valores de sus
lados.
3. Escribe una función que reciba como parámetro de entrada un valor numérico que represente un día de
la semana y que devuelva una cadena de caracteres con el nombre del día de la semana correspondiente.
Por ejemplo, para el valor de entrada 1 debería devolver la cadena lunes.
4. Escribe una función que reciba tres números reales como parámetros de entrada y devuelva el mayor de
los tres.
5. Escribe una función que devuelva el valor del área de un círculo a partir del valor del radio que se recibirá
como parámetro de entrada.
6. Escribe una función que devuelva como salida el número de años que han transcurrido entre dos fechas
que se reciben como parámetros de entrada. Por ejemplo, si pasamos como parámetros de entrada las
fechas 2018-01-01 y 2008-01-01 la función tiene que devolver que han pasado 10 años.
Para realizar esta función puede hacer uso de las siguientes funciones que nos proporciona MySQL:
• DATEDIFF
• TRUNCATE
1. Escribe una función para la base de datos tienda que devuelva el número total de productos que hay en
la tabla productos.
2. Escribe una función para la base de datos tienda que devuelva el valor medio del precio de los productos
de un determinado fabricante que se recibirá como parámetro de entrada. El parámetro de entrada será
el nombre del fabricante.
3. Escribe una función para la base de datos tienda que devuelva el valor máximo del precio de los produc-
tos de un determinado fabricante que se recibirá como parámetro de entrada. El parámetro de entrada
será el nombre del fabricante.
4. Escribe una función para la base de datos tienda que devuelva el valor mínimo del precio de los produc-
tos de un determinado fabricante que se recibirá como parámetro de entrada. El parámetro de entrada
será el nombre del fabricante.
1. Crea una base de datos llamada test que contenga una tabla llamada alumno. La tabla debe tener
cuatro columnas:
Una vez creada la base de datos y la tabla deberá crear un procedimiento llamado insertar_alumno con
las siguientes características. El procedimiento recibe cuatro parámetros de entrada (id, nombre, apellido1,
apellido2) y los insertará en la tabla alumno. El procedimiento devolverá como salida un parámetro llamado
error que tendrá un valor igual a 0 si la operación se ha podido realizar con éxito y un valor igual a 1 en caso
contrario.
Deberá manejar los errores que puedan ocurrir cuando se intenta insertar una fila que contiene una clave pri-
maria repetida.
1. Crea una base de datos llamada cine que contenga dos tablas con las siguientes columnas.
Tabla cuentas:
Tabla entradas:
Una vez creada la base de datos y las tablas deberá crear un procedimiento llamado comprar_entrada con
las siguientes características. El procedimiento recibe 3 parámetros de entrada (nif, id_cuenta, id_butaca)
y devolverá como salida un parámetro llamado error que tendrá un valor igual a 0 si la compra de la entrada
se ha podido realizar con éxito y un valor igual a 1 en caso contrario.
Deberá manejar los siguientes errores que puedan ocurrir durante el proceso.
2. ¿Qué ocurre cuando intentamos comprar una entrada y le pasamos como parámetro un número de cuen-
ta que no existe en la tabla cuentas? ¿Ocurre algún error o podemos comprar la entrada?
1.8.7 Cursores
1. Escribe las sentencias SQL necesarias para crear una base de datos llamada test, una tabla llamada
alumnos y 4 sentencias de inserción para inicializar la tabla. La tabla alumnos está formada por las
siguientes columnas:
Una vez creada la tabla se decide añadir una nueva columna a la tabla llamada edad que será un valor calculado
a partir de la columna fecha_nacimiento. Escriba la sentencia SQL necesaria para modificar la tabla y añadir
la nueva columna.
Escriba una función llamada calcular_edad que reciba una fecha y devuelva el número de años que han
pasado desde la fecha actual hasta la fecha pasada como parámetro:
• Función: calcular_edad
• Entrada: Fecha
• Salida: Número de años (entero)
Ahora escriba un procedimiento que permita calcular la edad de todos los alumnmos que ya existen en la tabla.
Para esto será necesario crear un procedimiento llamado actualizar_columna_edad que calcule la edad
de cada alumno y actualice la tabla. Este procedimiento hará uso de la función calcular_edad que hemos
creado en el paso anterior.
2. Modifica la tabla alumnos del ejercicio anterior para añadir una nueva columna email. Una vez que he-
mos modificado la tabla necesitamos asignarle una dirección de correo electrónico de forma automática.
Escriba un procedimiento llamado crear_email que dados los parámetros de entrada: nombre, apellido1,
apellido2 y dominio, cree una dirección de email y la devuelva como salida.
• Procedimiento: crear_email
• Entrada:
– nombre (cadena de caracteres)
– apellido1 (cadena de caracteres)
– apellido2 (cadena de caracteres)
– dominio (cadena de caracteres)
• Salida:
– email (cadena de caracteres)
Ahora escriba un procedimiento que permita crear un email para todos los alumnmos que ya existen en la tabla.
Para esto será necesario crear un procedimiento llamado actualizar_columna_email que actualice la co-
lumna email de la tabla alumnos. Este procedimiento hará uso del procedimiento crear_email que hemos
creado en el paso anterior.
1.8.8 Triggers
1. Crea una base de datos llamada test que contenga una tabla llamada alumnos con las siguientes co-
lumnas.
Tabla alumnos:
Una vez creada la tabla escriba dos triggers con las siguientes características:
• Trigger 1: trigger_check_nota_before_insert
– Se ejecuta sobre la tabla alumnos.
– Se ejecuta antes de una operación de inserción.
– Si el nuevo valor de la nota que se quiere insertar es negativo, se guarda como 0.
– Si el nuevo valor de la nota que se quiere insertar es mayor que 10, se guarda como 10.
• Trigger2 : trigger_check_nota_before_update
– Se ejecuta sobre la tabla alumnos.
– Se ejecuta antes de una operación de actualización.
– Si el nuevo valor de la nota que se quiere actualizar es negativo, se guarda como 0.
– Si el nuevo valor de la nota que se quiere actualizar es mayor que 10, se guarda como 10.
Una vez creados los triggers escriba varias sentencias de inserción y actualización sobre la tabla alumnos y
verifica que los triggers se están ejecutando correctamente.
2. Crea una base de datos llamada test que contenga una tabla llamada alumnos con las siguientes co-
lumnas.
Tabla alumnos:
Escriba un procedimiento llamado crear_email que dados los parámetros de entrada: nombre, apellido1,
apellido2 y dominio, cree una dirección de email y la devuelva como salida.
• Procedimiento: crear_email
• Entrada:
– nombre (cadena de caracteres)
– apellido1 (cadena de caracteres)
– apellido2 (cadena de caracteres)
– dominio (cadena de caracteres)
• Salida:
– email (cadena de caracteres)
Una vez creada la tabla escriba un trigger con las siguientes características:
• Trigger: trigger_crear_email_before_insert
– Se ejecuta sobre la tabla alumnos.
– Se ejecuta antes de una operación de inserción.
– Si el nuevo valor del email que se quiere insertar es NULL, entonces se le creará automáticamente
una dirección de email y se insertará en la tabla.
– Si el nuevo valor del email no es NULL se guardará en la tabla el valor del email.
Nota: Para crear la nueva dirección de email se deberá hacer uso del procedimiento crear_email.
3. Modifica el ejercicio anterior y añade un nuevo trigger que las siguientes características:
Trigger: trigger_guardar_email_after_update:
4. Modifica el ejercicio anterior y añade un nuevo trigger que tenga las siguientes características:
Trigger: trigger_guardar_alumnos_eliminados:
2. Según la siguiente sentencia, ¿estamos haciendo una llamada a un procedimiento o a una función?
CALL resolver_ejercicio2()
1.
LOOP bucle:
statements
END bucle:
2.
bucle: LOOP
statements
END bucle;
3.
bucle:
LOOP bucle;
statements;
END bucle;
DECLARE a INT;
DECLARE a INT;
DECLARE a INT;
DECLARE a FLOAT;
DECLARE b VARCHAR(20);
DECLARE b HANDLER FOR SQLSTATE '02000';
8. ¿Puedo actualizar los datos de un cursor en MySQL? Si fuese posible actualizar los datos de un cursor, ¿se
actualizarían automáticamente los datos de la tabla?
9. Cuál o cuáles de los siguientes bucles no está soportado en MySQL: FOR, LOOP, REPEAT y WHILE.
10. Si el cuerpo del bucle se debe ejecutar al menos una vez, ¿qué bucle sería más apropiado?
• 0
• 9
• 10
• NULL
• El código entra en un bucle infinito y nunca alcanza la sentencia SELECT value
DELIMITER $$
CREATE PROCEDURE incrementor (OUT i INT)
BEGIN
REPEAT
SET i = i + 1;
UNTIL i > 9
END REPEAT;
END;
DELIMITER $$
CREATE PROCEDURE test ()
BEGIN
DECLARE value INT default 0;
CALL incrementor(value);
SELECT value;
END;
DELIMITER ;
CALL test();
• 0
• 9
• 10
• NULL
• El código entra en un bucle infinito y nunca alcanza la sentencia SELECT value
DELIMITER $$
CREATE PROCEDURE incrementor (IN i INT)
BEGIN
REPEAT
SET i = i + 1;
UNTIL i > 9
END REPEAT;
END;
DELIMITER $$
CREATE PROCEDURE test ()
BEGIN
DECLARE value INT default 0;
CALL incrementor(value);
DELIMITER ;
CALL test();
12. Realice los siguientes procedimientos y funciones sobre la base de datos jardineria.
a)
• Función: calcular_precio_total_pedido
• Descripción: Dado un código de pedido la función debe calcular la suma total del pedido. Tenga en cuenta
que un pedido puede contener varios productos diferentes y varias cantidades de cada producto.
• Parámetros de entrada: codigo_pedido (INT)
• Parámetros de salida: El precio total del pedido (FLOAT)
b)
• Función: calcular_suma_pedidos_cliente
• Descripción: Dado un código de cliente la función debe calcular la suma total de todos los pedidos reali-
zados por el cliente. Deberá hacer uso de la función calcular_precio_total_pedido que ha desarro-
llado en el apartado anterior.
• Parámetros de entrada: codigo_cliente (INT)
• Parámetros de salida: La suma total de todos los pedidos del cliente (FLOAT)
c)
• Función: calcular_suma_pagos_cliente
• Descripción: Dado un código de cliente la función debe calcular la suma total de los pagos realizados por
ese cliente.
• Parámetros de entrada: codigo_cliente (INT)
• Parámetros de salida: La suma total de todos los pagos del cliente (FLOAT)
d)
• Procedimiento: calcular_pagos_pendientes
• Descripción: Deberá calcular los pagos pendientes de todos los clientes. Para saber si un cliente tiene
algún pago pendiente deberemos calcular cuál es la cantidad de todos los pedidos y los pagos que ha
realizado. Si la cantidad de los pedidos es mayor que la de los pagos entonces ese cliente tiene pagos
pendientes.
• id_cliente
• suma_total_pedidos
• suma_total_pagos
• pendiente_de_pago
-- Paso 1
CREATE TABLE t (s1 INT, PRIMARY KEY (s1));
-- Paso 2
DELIMITER $$
CREATE PROCEDURE handlerexam(IN a INT, IN b INT, IN c INT, OUT x INT)
BEGIN
DECLARE EXIT HANDLER FOR 1036 SET x = 10;
DECLARE EXIT HANDLER FOR 1062 SET x = 30;
SET x = 1;
INSERT INTO t VALUES (a);
SET x = 2;
INSERT INTO t VALUES (b);
SET x = 3;
INSERT INTO t VALUES (c);
SET x = 4;
END
$$
¿Qué devolvería la última sentencia SELECT @x en cada caso (a y b)? Justifique su respuesta. Sin una justifica-
ción válida la respuesta será considerada incorrecta.
-- a)
CALL handlerexam(1, 2, 3, @x);
SELECT @x;
-- b)
CALL handlerexam(1, 2, 1, @x);
SELECT @x;
-- Paso 1
CREATE TABLE t (s1 INT, PRIMARY KEY (s1));
-- Paso 2
DELIMITER $$
CREATE PROCEDURE test(IN a INT, OUT b INT)
BEGIN
SET b = 0;
WHILE a > b DO
SET b = b + 1;
IF b != 2 THEN
INSERT INTO t VALUES (b);
END IF
END WHILE;
END;
¿Qué valores tendría la tabla t y qué valor devuelve la sentencia SELECT value en cada caso (a y b)? Justifique
la respuesta. Sin una justificación válida la respuesta será considerada incorrecta.
-- a)
CALL test(-10, @value);
SELECT @value;
-- b)
CALL test(10, @value);
SELECT @value;
15. Escriba un procedimiento llamado obtener_numero_empleados que reciba como parámetro de entra-
da el código de una oficina y devuelva el número de empleados que tiene.
Escriba una sentencia SQL que realice una llamada al procedimiento realizado para comprobar que se ejecuta
correctamente.
16. Escriba una función llamada cantidad_total_de_productos_vendidos que reciba como parámetro
de entrada el código de un producto y devuelva la cantidad total de productos que se han vendido con
ese código.
Escriba una sentencia SQL que realice una llamada a la función realizada para comprobar que se ejecuta correc-
tamente.
17. Crea una tabla que se llame productos_vendidos que tenga las siguientes columnas:
Escriba un procedimiento llamado estadísticas_productos_vendidos que para cada uno de los produc-
tos de la tabla producto calcule la cantidad total de unidades que se han vendido y almacene esta información
en la tabla productos_vendidos.
18. Crea una tabla que se llame notificaciones que tenga las siguientes columnas:
Escriba un trigger que nos permita llevar un control de los pagos que van realizando los clientes. Los detalles
de implementación son los siguientes:
• Nombre: trigger_notificar_pago
• Se ejecuta sobre la tabla pago.
• Se ejecuta después de hacer la inserción de un pago.
• Cada vez que un cliente realice un pago (es decir, se hace una inserción en la tabla pago), el trigger deberá
insertar un nuevo registro en una tabla llamada notificaciones.
Escriba algunas sentencias SQL para comprobar que el trigger funciona correctamente.
1.10 Recursos
Licencia
Esta obra está bajo una licencia de Creative Commons Reconocimiento-NoComercial-CompartirIgual 4.0 Inter-
nacional.
32