Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Propósito
Elaborar una función con un parámetro de entrada, que debe ser de tipo Entero y
cuyo posible dato debe existir en la columna film_id de la tabla film, la cual debe
retornar: quienes han alquilado la película, nombre_persona, fecha_renta,
fecha_devolucion.
DELIMITER $$
# Inicio - Bloque de creacion
USE SAKILA $$
CREATE FUNCTION alquiler_pelicula_persona (v_film_id SMALLINT)
RETURNS TEXT
DETERMINISTIC
# Fin - Bloque de creacion
# Inicio - Bloque de implementacion
BEGIN
SET @datos = (SELECT GROUP_CONCAT(f.datos)
FROM (
SELECT CONCAT(f.title,',',c.first_name,'
',c.last_name,',',r.rental_date,',',r.return_date,'|') datos
FROM sakila.film f
INNER JOIN sakila.inventory i
ON (f.film_id = i.film_id)
INNER JOIN sakila.rental r
ON (i.inventory_id = r.inventory_id)
INNER JOIN sakila.customer c
ON (r.customer_id = c.customer_id)
WHERE f.film_id = v_film_id
GROUP BY f.title, c.first_name, c.last_name, r.rental_date,
r.return_date, c.customer_id
) f);
RETURN @datos;
END $$
# Fin - Bloque de implementacion
DELIMITER ;
Sección de pruebas
SET @rentas = alquiler_pelicula_persona(1);
SELECT @rentas;
Explicación
Para conocer cómo se relacionan las entidades entre sí dentro del sistema, fue
necesario revisar previamente el Diagrama Entidad - Relación, para así definir los
valores de entrada, llamando la función y utilizando un subquery con varios INNER
JOIN y se obtuvo los datos específicos vinculados en una tupla, esta queda
asociada a la variable datos, que fue la variable que se retornó, el tipo de dato
utilizado fue texto, ya que permite guardar cadenas de caracteres grandes como lo
precisa el ejercicio.
Resultado
DELIMITER $$
# Inicio - Bloque de creacion
USE SAKILA $$
CREATE FUNCTION alquiler_pelicula_persona_arr (v_film_id SMALLINT)
RETURNS JSON
DETERMINISTIC
# Fin - Bloque de creacion
# Inicio - Bloque de implementacion
BEGIN
RETURN (
SELECT JSON_ARRAYAGG(f_d.datos) json_array
FROM (
SELECT JSON_OBJECT(f.title,CONCAT(c.first_name,'
',c.last_name),r.rental_date,r.return_date) datos
FROM sakila.film f
INNER JOIN sakila.inventory i
ON (f.film_id = i.film_id)
INNER JOIN sakila.rental r
ON (i.inventory_id = r.inventory_id)
INNER JOIN sakila.customer c
ON (r.customer_id = c.customer_id)
WHERE f.film_id = v_film_id
GROUP BY f.title, c.first_name, c.last_name, r.rental_date,
r.return_date, c.customer_id
) f_d
);
END $$
# Fin - Bloque de implementacion
DELIMITER ;
Sección de pruebas
SET @rentas = alquiler_pelicula_persona_arr (1);
SELECT JSON_EXTRACT(@rentas, '$[1]'); # Obtener primer elemento
Explicación
Para el desarrollo de esta función se buscó un Array SQL como resultado, se utilizó
la misma lógica implementada en el desarrollo anterior con la diferencia que aquí se
implementó una variable de tipo de JSON que tiene funcionamiento de un arreglo, el
cual permite escoger posiciones específicas.
Resultado
Procedimiento almacenado
Propósito
Realizar un procedimiento que tenga como parámetros lo siguiente:
Solución propuesta
Sentencia SQL
SELECT CONCAT('[',GROUP_CONCAT(f_a.actor_nombre),']')
INTO v_actores
FROM (
SELECT CONCAT(a.first_name,' ',a.last_name) actor_nombre
FROM sakila.film f
INNER JOIN sakila.film_actor fa
ON (f.film_id = fa.film_id)
INNER JOIN sakila.actor a
ON (fa.actor_id = a.actor_id)
WHERE f.film_id = v_film_id
) f_a;
END $$
# Fin - Bloque de implementacion
DELIMITER ;
Sección de pruebas
SET @cantidad_rentas = 0;
CALL actores_peliculas(1, @cantidad_rentas, @actores);
SELECT @cantidad_rentas, @actores;
Explicación
Se definen los parámetros de entrada en base a los requisitos establecidos,
posterior a esto se asigna el valor de la cantidad de la cantidad de veces que se
rentó una película (variable v_film_id) a la variable v_cantidad_rentas, para ello se
hace uso de la función JSON_LENGTH, función integrada de MySQL para retornar
el tamaño de una variable tipo JSON, que obtendrá el tamaño del valor retornado
por la función creada en la sección anterior.
Realizado lo anterior, se realiza una consulta a las tablas film, film_actor y actor,
haciendo un cruce entre las tres para identificar los actores que han participado en
la película ingresada.
Resultado:
Trigger
Propósito
Definir una columna nueva en la tabla store de tipo numérica INT, que debe ser
mayor a cero y cuyo nombre sea num_empleados, que deberá contener el número
de empleados asociados por tienda. Cuando se inserte una nueva tienda a la tabla
store se debe disparar una inserción de datos aleatorios en la tabla staff, simulando
la contratación de los empleados necesarios para la tienda.
DELIMITER $$
CREATE TRIGGER staff_insertar AFTER INSERT ON sakila.store FOR EACH ROW
# Inicio - Bloque de implementacion
BEGIN
IF NEW.num_empleados IS NOT NULL AND NEW.num_empleados > 1 THEN # Se
insertan valores si no es nulo o si es mayor a uno diferente del
administrador
SET @nombre_array =
JSON_ARRAY('Raul','Gabriel','Maria','Natalia','Sara');
SET @apellido_array =
JSON_ARRAY('Garcia','Bustamante','Hernandez','Cruz','Santonilli');
SET @password_array =
JSON_ARRAY('12435','54321','11111','22222','33333');
SET @i = 1;
insertar: LOOP
SET @i = @i + 1;
SET @temp_nombre = JSON_EXTRACT(@nombre_array, CONCAT('$
[',FLOOR(RAND()*(JSON_LENGTH(@nombre_array)-1+1)),']'));
Explicación
Se define el disparador como tipo INSERT para que el disparador se active después
de la inserción de una fila. Se crean tres variables que contendrán datos por defecto
para el nombre, apellido y password; las cuales serán ingresadas en la tabla staff.
Posterior a esto se crea el ciclo “insertar”, en el cual se ingresarán los datos fila a fila
en la columna staff.
DELIMITER $$
CREATE TRIGGER staff_actualizar BEFORE UPDATE ON sakila.store FOR EACH ROW
# Inicio - Bloque de implementacion
BEGIN
#SET @var_num_emp_prev = 0;
SELECT s.staff_id
INTO @id_staff_eliminar
FROM sakila.staff s
WHERE s.store_id = NEW.store_id
#AND s.staff_id <> NEW.manager_staff_id
AND NOT EXISTS (SELECT 1 FROM sakila.store WHERE
manager_staff_id = s.staff_id)
LIMIT 1;
Explicación
Se crea un disparador de tipo UPDATE, y similar al disparador anterior se realiza
una actualización a las filas según dos casos:
- Si es mayor a la cantidad de datos que tiene actualmente para el número de
empleados, se realiza la inserción de datos de la misma forma que en el
disparador de inserción.
- Si la cantidad de empleados es menor se realiza una consulta para retornar
el id de un empleado aleatorio y realizado esto, eliminarlo. Si por error la
cantidad de empleados es menor a 1, el disparador no elimina nada, ya que,
como mínimo, una tienda debe contar con un empleado, que en este caso
sería el manager de la tienda.
DELIMITER $$
CREATE TRIGGER staff_actualizar_v2 BEFORE UPDATE ON sakila.store FOR EACH
ROW
# Inicio - Bloque de implementacion
BEGIN
IF NEW.num_empleados <> OLD.num_empleados AND NEW.num_empleados >= 1
THEN # El administrador no sera eliminado
# Eliminar staff
IF NEW.num_empleados < OLD.num_empleados THEN
SET @i = 0;
DELETE s FROM sakila.staff s
INNER JOIN (
SELECT staff_id
FROM (
SELECT (@i:=@i+1) num,
staff_id
FROM sakila.staff
WHERE store_id = NEW.store_id
AND staff_id NOT IN (SELECT manager_staff_id FROM
sakila.store)
) num_staff
WHERE num_staff.num <= (OLD.num_empleados-
NEW.num_empleados)
) filtro
ON (filtro.staff_id = s.staff_id);
ELSE
# Insertar staff
SET @nombre_array =
JSON_ARRAY('Raul','Gabriel','Maria','Natalia','Sara');
SET @apellido_array =
JSON_ARRAY('Garcia','Bustamante','Hernandez','Cruz','Santonilli');
SET @password_array =
JSON_ARRAY('12435','54321','11111','22222','33333');
SET @i = OLD.num_empleados;
insertar: LOOP
SET @i = @i + 1;
SET @temp_nombre = JSON_EXTRACT(@nombre_array, CONCAT('$
[',FLOOR(RAND()*(JSON_LENGTH(@nombre_array)-1+1)),']'));
Explicación
En esta tercera opción se mantiene la lógica del disparador de actualización
previamente descrito, pero, a diferencia del anterior, en vez de realizar un proceso
de eliminación seleccionando id por id se realiza una consulta y se eliminan los
datos de la tabla staff en base al resultado de esta.
Resultado
Para las pruebas se debe tener en cuenta el estado inicial de la tabla store y staff,
por ende, se debe consultar las tablas antes de la modificación.
Posterior a la actualización, los resultados para las tablas store y staff son
respectivamente: