0% encontró este documento útil (0 votos)
74 vistas34 páginas

#1 - Programas MySQL

El documento aborda el uso de programas almacenados en MySQL para el desarrollo de aplicaciones web, destacando tipos como procedimientos, funciones y triggers, así como sus ventajas en términos de seguridad y rendimiento. Se presentan fundamentos de programación en MySQL, incluyendo la declaración de variables, control de flujo y manejo de errores, junto con ejemplos prácticos. Además, se incluyen ejercicios propuestos para reforzar el aprendizaje sobre la gestión de bases de datos mediante estos programas almacenados.

Cargado por

cristina53moreno
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
74 vistas34 páginas

#1 - Programas MySQL

El documento aborda el uso de programas almacenados en MySQL para el desarrollo de aplicaciones web, destacando tipos como procedimientos, funciones y triggers, así como sus ventajas en términos de seguridad y rendimiento. Se presentan fundamentos de programación en MySQL, incluyendo la declaración de variables, control de flujo y manejo de errores, junto con ejemplos prácticos. Además, se incluyen ejercicios propuestos para reforzar el aprendizaje sobre la gestión de bases de datos mediante estos programas almacenados.

Cargado por

cristina53moreno
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd

Programas Almacenados en MySQL para Desarrollo de

Aplicaciones Web (DAW)

1. Introducción​ 3
1.1. Tipos de Programas Almacenados​ 3
1.2. Ventajas de su Uso​ 3
1.3. Edición de Programas Almacenados​ 3
1.4. Ejemplos de uso​ 3
2. Fundamentos de la programación en MySQL​ 4
2.1. Declaración de Variables​ 5
2.2. Variables de Usuario​ 5
2.3. Comentarios en MySQL​ 5
2.4. Expresiones y Funciones Incorporadas​ 6
2.5. Operadores en MySQL​ 6

t
2.6. Bloques de Instrucciones y Control de Flujo​ 7

yo Instrucción IF:​
Instrucción CASE:​
2.6 Bucles en MySQL​
LOOP + LEAVE:​
WHILE:​
REPEAT…UNTIL:​
2.7. Uso del DELIMITER y estructura general​
10
10
11
11
12
12
13
lu
2.8. Ejemplo completo:​ 13
3. Procedimientos almacenados​ 14
3.1. Estructura básica de un procedimiento almacenado​ 14
3.2. Llamada a un procedimiento almacenado​ 14
3.3. Delimitadores​ 14
PL

3.4. Variables y Tipos de Datos​ 14


Declaración de Variables​ 15
Variables de Usuario​ 15
Ejemplo de uso de una variable de usuario en un procedimiento​ 15
Ejercicios Prácticos I​ 15
3.5. Parámetros en Procedimientos Almacenados​ 16
Ejemplo de parámetros en un procedimiento​ 16
Ejemplo de parámetros en un procedimiento​ 16
Aclaración con ejemplo (Paquetes con direcciones)​ 17
Ejercicios Prácticos II​ 18
Ejercicio propuesto de repaso​ 20
3.6. Modificación de procedimientos​ 21
3.7. Borrado de procedimientos​ 21
4. Funciones​ 21
4.1. ¿Qué es una función?​ 21
4.2. Sintaxis básica​ 22

P.Lluyot-25​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ 1
4.3. Ejemplo básico​ 22
4.4. Parámetros en funciones​ 23
4.5. Variables locales en funciones​ 23
4.6. Llamada a funciones​ 23
4.7. Restricciones y Diferencias Clave con Procedimientos​ 24
4.8. Ejemplos prácticos adicionales​ 25
4.9. Modificación y Borrado de Funciones​ 25
4.10. Aplicaciones comunes​ 25
Ejercicios Prácticos III​ 26
Ejercicio propuestos​ 26
5. Triggers (Disparadores)​ 26
5.1. ¿Qué es un trigger?​ 26
5.2. Sintaxis básica​ 27
5.3. Tipos de triggers​ 27
5.4. Ejemplo: Auditoría​ 27

t
5.5. Buenas prácticas​ 27
6. Tratamiento de errores​ 27

yo
6.1. Manejo de errores en MySQL​
6.2. Sintaxis básica​
6.3. Ejemplo típico​
6.4. Generación de Errores (SIGNAL)​
7. Ejercicios complejos propuestos:​
7.1. Gestión de puntos y premios en una tienda de fidelización​
27
27
28
29
30
30
lu
7.2. Gestión de Stock Simple​ 32
PL

P.Lluyot-25​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ 2
1.​ Introducción
Los programas almacenados en MySQL permiten encapsular lógica de negocio dentro del
servidor de bases de datos. Esto mejora el rendimiento y la seguridad al reducir el tráfico entre
la aplicación y la base de datos.

t
yo
1.1.​ Tipos de Programas Almacenados
●​ Procedimientos almacenados: Resuelven problemas al ser llamados, pueden aceptar y
devolver múltiples parámetros.
●​ Funciones almacenadas: Similares a los procedimientos, pero devuelven un único valor
lu
y pueden usarse dentro de instrucciones SQL.
●​ Triggers (disparadores): Se activan automáticamente ante eventos en la base de datos.

1.2.​ Ventajas de su Uso


●​ Mayor seguridad y robustez al limitar el acceso directo a las tablas.
●​ Mejor mantenimiento al centralizar la lógica de acceso y actualización de datos.
PL

●​ Mayor portabilidad de las aplicaciones al implementar la lógica en la base de datos.


●​ Integración con SQL sin necesidad de conectores externos.
●​ Reducción del tráfico de red al ejecutar la lógica en el servidor.

1.3.​ Edición de Programas Almacenados


Los programas almacenados pueden crearse y editarse con herramientas como:

●​ MySQL Workbench: Interfaz gráfica que facilita la gestión de bases de datos.


●​ CLI (Command Line Interface): Uso de la terminal para ejecutar comandos SQL.

1.4.​ Ejemplos de uso

Procedimiento almacenado: registro de un nuevo pedido

Imagina una tienda online. Cada vez que un cliente realiza un pedido, es necesario guardar el
pedido, los productos seleccionados, calcular el total y aplicar posibles descuentos. Todo esto

P.Lluyot-25​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ 3
puede hacerse con un procedimiento almacenado que reciba los datos del pedido y realice
todas estas acciones de forma centralizada, segura y automática.

Ventaja: Se encapsula toda la lógica del proceso en un solo lugar, evitando errores
y repitiendo el mismo flujo cada vez que se registra un pedido.

Función: cálculo de la edad de un usuario

En una base de datos de empleados, es común querer saber la edad actual de una persona a
partir de su fecha de nacimiento. Para eso, se puede usar una función almacenada que reciba la
fecha y devuelva la edad exacta. Esta función se puede reutilizar en informes, filtros,
validaciones, etc.

Ventaja: Aporta reutilización y claridad: cualquier parte del sistema puede


obtener la edad simplemente llamando a la función, sin reescribir el cálculo cada
vez.

t
Trigger (disparador): control automático de auditoría

yo
Cuando se modifica información sensible en una tabla (como los datos personales de un
cliente), es fundamental saber quién hizo el cambio y cuándo. Un trigger puede activarse
automáticamente en cada UPDATE y guardar un registro en una tabla de auditoría sin
intervención del programador.

Ventaja: Se garantiza el control y trazabilidad de los cambios, sin depender del


código de la aplicación externa.
lu
PL

2.​ Fundamentos de la programación en MySQL


Esta sección recoge los elementos básicos necesarios para construir procedimientos, funciones
o disparadores. Incluye el uso de variables, expresiones, bloques de instrucciones, funciones
integradas y bucles. Dominar esta sintaxis es fundamental antes de crear programas
almacenados complejos.

P.Lluyot-25​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ 4
2.1.​ Declaración de Variables

Dentro de un bloque de programa se pueden declarar variables locales utilizando DECLARE.


Estas variables solo existen dentro del bloque donde se declaran y permiten almacenar valores
intermedios, realizar operaciones o controlar el flujo del programa.

Sintaxis: ​
DECLARE nombre_variable1 [,nombre_variable2...] tipo [DEFAULT valor];

Ejemplo:
Tipo de Dato Descripción Ejemplo

INT Entero (±2 mil millones DECLARE num INT DEFAULT 0;


aprox.)

DECIMAL(M,D) / Número decimal con DECLARE precio DECIMAL(8,2);


NUMERIC(M,D) precisión

t
FLOAT, DOUBLE Números reales aproximados DECLARE promedio FLOAT;

yo
CHAR(N)

VARCHAR(N)

DATE

DATETIME
Cadena de longitud fija

Cadena de longitud
variable

Fecha (YYYY-MM-DD)

Fecha y hora
DECLARE letra CHAR(1) DEFAULT ‘A’;

DECLARE nombre VARCHAR(50);

DECLARE fechaNacimiento DATE;

DECLARE fechaRegistro DATETIME;


lu
BOOLEAN / Booleano (0 o 1) DECLARE activo BOOLEAN DEFAULT TRUE;
TINYINT

2.2.​ Variables de Usuario

Las variables de usuario comienzan con @ y tienen alcance a nivel de sesión. No requieren
PL

declaración previa y pueden usarse fuera de procedimientos. No obstante, no son


recomendables dentro de procedimientos almacenados, ya que no están aisladas del resto de
la sesión.

SET @contador = 10;


SELECT @contador;

2.3.​ Comentarios en MySQL

Existen tres formas de incluir comentarios en el código SQL:

-- Comentario de una línea


# También válido como comentario de una línea
/* Comentario
de varias líneas */​
Los comentarios son útiles para documentar el código, explicar partes específicas del
procedimiento o desactivar temporalmente instrucciones.

P.Lluyot-25​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ 5
2.4.​ Expresiones y Funciones Incorporadas

MySQL dispone de funciones nativas para trabajar con texto, fechas, números y otros tipos de
datos. Estas funciones pueden usarse dentro de procedimientos o consultas para realizar
operaciones comunes.

SELECT UPPER('texto en mayúsculas');


SELECT NOW(); -- Devuelve la fecha y hora actual
SELECT LENGTH('cadena'); -- Devuelve 6

2.5.​ Operadores en MySQL

Los operadores permiten realizar cálculos, comparar valores y construir condiciones lógicas.
Son fundamentales en la construcción de expresiones, condiciones IF, filtros WHERE, y más.

A continuación, se clasifican los operadores más comunes usados en MySQL:

t
Operadores Aritméticos
Sirven para realizar operaciones matemáticas básicas.

*
yo
Operador

Suma
Descripción

Resta

Multiplicación
Ejemplo

SET total = precio + iva;

SET diferencia = a - b;

SET subtotal = precio * cantidad;


lu
/ División SET promedio = suma / cantidad;

% Módulo (resto) SET resto = a % 2; (par/impar)


PL

Operadores de Comparación
Se utilizan para comparar valores. El resultado siempre es TRUE o FALSE.

Operador Descripción Ejemplo

= Igual IF edad = 18 THEN ...

<> o != Distinto IF nombre <> 'Juan' THEN ...

< Menor que IF salario < 1000 THEN ...

<= Menor o igual IF nota <= 5 THEN ...

> Mayor que IF edad > 65 THEN ...

>= Mayor o igual IF puntos >= 50 THEN ...

P.Lluyot-25​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ 6
Operadores Lógicos
Permiten combinar múltiples condiciones lógicas.

Operador Descripción Ejemplo

AND Verdadero si ambas condiciones IF edad > 18 AND activo = TRUE


lo son THEN ...

OR Verdadero si alguna condición lo IF rol = 'admin' OR rol =


es 'editor' THEN ...

NOT Niega una condición IF NOT activo THEN ...

Operadores Especiales
Estos operadores permiten crear condiciones más complejas o específicas.

t
Operador Descripción Ejemplo

yo
BETWEEN

IN(...)
Comprueba si un valor está entre
dos valores

Comprueba si un valor pertenece a


una lista
IF nota BETWEEN 5 AND 10 THEN
...

IF pais IN ('España', 'México')


THEN ...
lu
IS NULL Comprueba si un valor es nulo IF email IS NULL THEN ...

LIKE Comparación de patrones de texto IF nombre LIKE 'A%' THEN ...


(empieza por A)
PL

2.6.​ Bloques de Instrucciones y Control de Flujo

Los bloques BEGIN ... END son esenciales en la programación en MySQL: agrupan un
conjunto de instrucciones que se ejecutan como una unidad. Dentro de un bloque se pueden

P.Lluyot-25​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ 7
declarar variables locales, usar estructuras condicionales (IF, CASE), realizar operaciones y
controlar el flujo con bucles (WHILE, REPEAT, LOOP).

Es obligatorio utilizar un bloque BEGIN ... END en procedimientos, funciones o triggers


cuando se quieren incluir múltiples instrucciones o lógica interna.

¿Qué puede incluir un bloque BEGIN ... END?

●​ Declaración de variables (DECLARE)


●​ Declaración de cursores
●​ Asignación de valores (SET)
●​ Estructuras de control (IF, CASE)
●​ Bucles (WHILE, LOOP, REPEAT)
●​ Sentencias SQL como SELECT, INSERT, etc.
●​ Manejo de errores

CREATE {PROCEDURE | FUNCTION |TRIGGER} nombre_del_programa

t
BEGIN
Instrucciones
END;
yo
lu
PL

Ejemplo simple de bloque:


DELIMITER //

CREATE PROCEDURE verificar_edad(IN edad INT)


BEGIN
-- declaración de variables
DECLARE mensaje VARCHAR(50);

-- Evaluamos la edad con un IF


IF edad >= 18 THEN
SET mensaje = 'Es mayor de edad';
ELSE
SET mensaje = 'Es menor de edad';

P.Lluyot-25​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ 8
END IF;

-- Mostramos el mensaje
SELECT mensaje AS Resultado;
END //

DELIMITER ;

-- Llamada al procedimiento con diferentes valores


CALL verificar_edad(20);
CALL verificar_edad(15);

Los bloques también pueden anidarse, permitiendo estructuras más complejas dentro de
procedimientos.

delimiter %%
drop procedure if exists ejemplo_anidado;

t
create procedure ejemplo_anidado()

yo
-- Comenzamos un bloque exterior
BEGIN
-- Declaramos una variable en el bloque exterior
DECLARE edad INT DEFAULT 20;
-- Mostramos el valor de la variable 'edad' del bloque exterior
SELECT 'Valor de edad dentro del bloque exterior:', edad; -- muestra 20
-- Modificamos la variable 'edad' dentro del bloque exterior
SET edad = 25;
lu
-- Mostramos el valor de la variable 'edad' después de la modificación
en el bloque exterior
SELECT 'Valor de edad después de modificación dentro del bloque
exterior:', edad; -- Muestra 25
-- Comenzamos un bloque interior anidado sin declarar 'edad' en el
interior
PL

BEGIN
​ ​ -- declare edad int default 1; #####DESCOMENTAR ESTA LÍNEA####
​ ​ -- leemos en el bloque interior el valor de edad:
SELECT 'Valor de edad dentro del bloque interior:', edad; --
Muestra 25
-- No declaramos 'edad' dentro del bloque interior, por lo que
usamos la del bloque exterior
SET edad = 30; -- Modifica la variable 'edad' del bloque exterior
-- Mostramos el valor de la variable 'edad' dentro del bloque
interior
SELECT 'Valor de edad dentro del bloque interior (modificada):',
edad; -- Muestra 30
END;
-- Después de salir del bloque interior, mostramos el valor de la
variable 'edad' del bloque exterior
SELECT 'Valor de edad después de salir del bloque interior (bloque
exterior):', edad; -- Muestra 30*/
END %%

P.Lluyot-25​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ 9
delimiter ;
call ejemplo_anidado();

En el ejemplo anterior ejecuta el código y verifica como cambia el valor de la variable edad en
función de su modificación en el bloque interior o exterior.
Si descomentamos la línea marcada, comprobar el comportamiento de la variable dentro y
fuera del bloque
(clase 1 - hasta aquí)

Instrucción IF:
El comando IF se utiliza para ejecutar instrucciones condicionalmente. Si la expresión
condicional es verdadera, se ejecutan las instrucciones correspondientes.
IF condición THEN
instrucciones;
[ELSEIF condición2 THEN

t
instrucciones;]
[ELSE

yo
instrucciones;]
END IF;

Por ejemplo:
DECLARE
DECLARE
IF edad
edad INT DEFAULT 25;
mensaje VARCHAR(50);
>= 18 THEN
lu
SET mensaje = 'Mayor de edad';
ELSE
SET mensaje = 'Menor de edad';
END IF;

SELECT mensaje;
PL

Ejercicio propuesto:
Crear un procedimiento, donde definimos una variable llamada nota con un valor comprendido
entre 0 y el 10 (admite dos decimales). Emplear la estructura de IF…ELSEIF…ELSE…ENDIF para
mostrar un mensaje al usuario en función de la nota:
-​ [9,10] → sobresaliente
-​ [7,9) -> notable
-​ [6-7) -> bien
-​ [5-6) -> suficiente
-​ [0-5) -> suspenso.

Instrucción CASE:
El comando CASE permite manejar múltiples condiciones y elegir cuál ejecutar. Es más
adecuado cuando tienes varias condiciones a evaluar.
CASE
WHEN condición1 THEN instrucciones;
WHEN condición2 THEN instrucciones;

P.Lluyot-25​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ 10
ELSE instrucciones;
END CASE;

otra forma de usar la sentencia CASE:


CASE expresión
WHEN valor1 THEN instrucciones;
WHEN valor2 THEN instrucciones;
ELSE instrucciones;
END CASE;

Ejemplo:
DECLARE edad INT DEFAULT 25;
DECLARE mensaje VARCHAR(50);
SET mensaje = CASE
WHEN edad >= 18 THEN 'Mayor de edad'
WHEN edad < 18 THEN 'Menor de edad'
ELSE 'Edad no válida'

t
END;

SELECT mensaje;

yo
Ejemplo2:
DECLARE edad INT DEFAULT 25;
DECLARE mensaje VARCHAR(50);

SET mensaje = CASE edad


lu
WHEN 18 THEN 'Justo mayor de edad'
WHEN 17 THEN 'Casi mayor de edad'
WHEN 25 THEN 'Edad típica de un joven adulto'
ELSE 'Edad no clasificada'
END;

SELECT mensaje;
PL

Ejercicio propuesto:
Usa la instrucción case para poner en texto castellano el día de la semana. Por ejemplo, el día 1
corresponde al Lunes, etc..

2.6 Bucles en MySQL

Los bucles permiten repetir instrucciones mientras se cumpla una condición. Son útiles para
iterar cálculos, mostrar listados o recorrer valores.

LOOP + LEAVE:
El comando LOOP permite ejecutar un conjunto de instrucciones repetidamente hasta que se
encuentre una instrucción LEAVE que termine el bucle.
[etiqueta:] LOOP
instrucciones;
END LOOP [etiqueta];

P.Lluyot-25​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ 11
Ejemplo: contar del 1 al 10
LOOP_label: LOOP
SET contador = contador + 1;
IF contador >= 10 THEN
LEAVE LOOP_label;
END IF;
END LOOP;

Ejemplo: Contar del 1 al 5 pero saltar el 3


cuenta: LOOP
SET i = i + 1;
-- Saltar el número 3
IF i = 3 THEN
ITERATE cuenta;
END IF;

t
-- Mostrar el número
SELECT CONCAT('Número: ', i) AS mensaje;
-- Salir del bucle al llegar a 5

yo
IF i >= 5 THEN
LEAVE cuenta;
END IF;
END LOOP cuenta;

Ejercicio propuesto:
Mostrar por pantalla los 10 primeros múltiplos de 3 (usando LOOP). Almacena los valores en
lu
una tabla temporal y mostrarlos.

WHILE:
El comando WHILE ejecuta un conjunto de instrucciones mientras la expresión booleana sea
verdadera
PL

[etiqueta:] WHILE expresión DO


instrucciones;
END WHILE [etiqueta];

Ejemplo:
WHILE contador < 10 DO
SET contador = contador + 1;
END WHILE;

Ejercicio propuesto:
Usar un bucle WHILE para mostrar los cuadrados de los primeros 10 números enteros.

REPEAT…UNTIL:
El comando REPEAT...UNTIL ejecuta un bloque de instrucciones hasta que la expresión
booleana se evalúe como verdadera. A diferencia de WHILE, la condición se evalúa después de
la ejecución, por lo que al menos una iteración siempre se realiza.

P.Lluyot-25​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ 12
[etiqueta:] REPEAT
instrucciones;
UNTIL expresión
END REPEAT [etiqueta];

Ejemplo:
DECLARE i INT DEFAULT 1;
REPEAT
SELECT i;
SET i = i + 1;
UNTIL i > 5
END REPEAT;

Ejercicio propuesto:
Queremos generar números de la secuencia de Fibonacci (donde cada número es la suma de los
dos anteriores: 0, 1, 1, 2, 3, 5, 8...) y detenernos justo después de generar el primer número que
sea mayor que 100. Mostraremos la secuencia del número generado mediante una SELECT

t
(usar la función CONCAT para concatenar la secuencia de números)

yo
2.7.​ Uso del DELIMITER y estructura general

Al definir procedimientos o funciones con varios comandos, es necesario cambiar el


delimitador (;) por otro temporal como // o $$, para evitar errores de interpretación.
lu
DELIMITER //
CREATE PROCEDURE ejemplo()
BEGIN
SELECT 'Hola mundo';
END //
DELIMITER ;
PL

2.8.​ Ejemplo completo:

Este ejemplo integra variables, bloques de control y una salida sencilla:

DELIMITER //
-- Comienza el primer bloque
CREATE PROCEDURE ejemplo_edad()
BEGIN
-- Declaración de variables
DECLARE edad INT DEFAULT 25;
DECLARE mensaje VARCHAR(50);
-- Estructura condicional (IF)
IF edad >= 18 THEN
SET mensaje = 'Mayor de edad';
ELSE
SET mensaje = 'Menor de edad';
END IF;
-- Muestra el valor de la variable 'mensaje'

P.Lluyot-25​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ 13
SELECT mensaje;
END//
DELIMITER ;

3.​ Procedimientos almacenados


3.1.​ Estructura básica de un procedimiento almacenado

Un procedimiento almacenado es un bloque de código SQL que se guarda en el servidor y se


puede ejecutar varias veces mediante una llamada. Su estructura básica incluye la definición
del delimitador, el nombre del procedimiento, y el cuerpo que contiene las instrucciones SQL.

DELIMITER $$
CREATE PROCEDURE ejemplo_basico()
BEGIN

t
SELECT 'Esto es un procedimiento almacenado';
END $$

yo
DELIMITER ;

3.2.​ Llamada a un procedimiento almacenado

Una vez creado un procedimiento, puede ejecutarse con la instrucción CALL. Esta llamada
ejecuta todas las instrucciones que contiene el procedimiento y, si tiene parámetros, permite
enviar valores de entrada o recibir resultados.
lu
CALL ejemplo_basico();

3.3.​ Delimitadores

Los delimitadores se utilizan para evitar conflictos con el punto y coma (;) que se usa en SQL.
Para definir un procedimiento almacenado correctamente, se usa DELIMITER:
PL

DELIMITER $$
CREATE PROCEDURE test()
BEGIN
SELECT 'Prueba de delimitador';
END $$
DELIMITER ;

3.4.​ Variables y Tipos de Datos

En los procedimientos almacenados, se pueden declarar variables internas con DECLARE.


Estas variables sirven para almacenar valores temporales, realizar cálculos o controlar el
flujo del programa. Cada variable debe tener un tipo de dato y puede tener un valor por
defecto.

Declaración de Variables
DELIMITER $$

P.Lluyot-25​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ 14
CREATE PROCEDURE ejemplo_variables()
BEGIN
DECLARE mi_variable INT DEFAULT 1;
DECLARE texto VARCHAR(50) DEFAULT 'Ejemplo';
SET mi_variable = mi_variable + 5;
SET texto = CONCAT(texto, ' actualizado');
SELECT mi_variable, texto;
END $$
DELIMITER ;

Variables de Usuario
Las variables de usuario comienzan con @ y tienen un alcance a nivel de sesión. Se pueden usar
dentro o fuera de procedimientos almacenados y no requieren declaración previa. Son útiles
para almacenar valores temporales entre consultas o para probar procedimientos.

SET @mi_variable = 10;


SELECT @mi_variable;

t
Ejemplo de uso de una variable de usuario en un procedimiento

yo
DELIMITER $$
CREATE PROCEDURE ejemplo_variable_usuario()
BEGIN
SET @contador = 5;
WHILE @contador > 0 DO
SELECT CONCAT('Cuenta regresiva: ', @contador);
SET @contador = @contador - 1;
END WHILE;
lu
END $$
DELIMITER ;

Nota sobre las variables de usuario


PL

Aunque las variables de usuario (@variable) pueden utilizarse dentro de un programa SQL, no
son recomendables porque:

No están aisladas dentro del procedimiento: su valor persiste durante toda la


sesión y puede verse afectado por otras operaciones o consultas anteriores. Esto
puede provocar errores inesperados o resultados inconsistentes si varios
procedimientos o usuarios modifican la misma variable.

Por eso, siempre que sea posible, se recomienda usar variables locales declaradas con
DECLARE, que son seguras, privadas y solo existen dentro del procedimiento donde se definen.

Ejercicios Prácticos I
1.​ Crea un procedimiento (ejemplo1_sp.sql) que muestre por pantalla el texto "esto es un
ejemplo de procedimiento" (donde la cabecera de la columna sea mensaje).
2.​ Crea un procedimiento (ejemplo2_sp.sql) donde se declaran tres variables internas:
○​ Una de tipo entero con valor de 1.

P.Lluyot-25​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ 15
○​ Otra de tipo VARCHAR(10) con valor NULL por defecto.
○​ Otra de tipo DECIMAL(4,2).
Dentro del procedimiento, modifica los valores de estas variables, realiza operaciones
matemáticas y muestra los resultados con SELECT.
3.​ Crea un procedimiento (ejemplo3_sp.sql) donde se declaran dos variables internas:
○​ Una de tipo CHAR(1).
○​ Otra de tipo ENUM('bajo', 'medio', 'alto').
○​ Modifica los valores de las variables y muestra el resultado. Luego, provoca errores
asignando valores no permitidos.
4.​ Crea un procedimiento (ejemplo4_sp.sql) donde se declaran variables internas de tipo
entero y de tipo fecha, con la fecha actual por defecto.
○​ Modifica los valores y muestra los resultados.
○​ Provoca errores asignando valores incorrectos a las variables.
5.​ Asignar cualquier valor a una variable definida por el usuario de distintas formas (mediante
una select y mediante la clausula SET)​
Crear un procedimiento (ejemplo5_sp.sql) que modifique dicha variable, muestre el valor
de dicha variable tanto dentro del procedimiento, como fuera de él.

t
3.5.​ Parámetros en Procedimientos Almacenados
yo
Los procedimientos almacenados en MySQL pueden aceptar parámetros para trabajar con
datos dinámicos. Esto permite reutilizar la lógica con diferentes valores de entrada y obtener
distintos resultados sin tener que modificar el código.

MySQL permite definir tres tipos de parámetros, según cómo se comportan durante la
ejecución:
lu
●​ IN: Se utiliza para enviar un valor al procedimiento.
●​ OUT: Se utiliza para devolver un valor desde el procedimiento.
●​ INOUT: Se utiliza tanto para enviar como para recibir un valor.

Ejemplo de parámetros en un procedimiento


PL

DELIMITER //
CREATE PROCEDURE ejemplo_parametro(IN nombre_usuario VARCHAR(50))
BEGIN
SELECT * FROM usuarios WHERE nombre = nombre_usuario;
END //
DELIMITER ;

Llamada al procedimiento con parámetros:

CALL ejemplo_parametros('Juan');

Ejemplo de parámetros en un procedimiento


DELIMITER $$
CREATE PROCEDURE ejemplo_parametros(IN nombre VARCHAR(50), OUT mensaje
VARCHAR(100))
BEGIN

P.Lluyot-25​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ 16
SET mensaje = CONCAT('Hola, ', nombre, '!');
END $$
DELIMITER ;

Llamada al procedimiento con parámetros:

CALL ejemplo_parametros('Juan', @saludo);


SELECT @saludo;

Aclaración con ejemplo (Paquetes con direcciones)

Imagina que un procedimiento es como una oficina de mensajería. Según el tipo de parámetro,
el comportamiento del "paquete" (el valor) cambia:
●​ IN ⇒ : Solo entra a la oficina (se usa pero no se modifica fuera).

t
●​ OUT ⇐ : Solo sale desde la oficina (se genera dentro).
🔁
●​ INOUT : Entra, se modifica dentro y sale actualizado.

yo
IN ⇒ : solo entra
DELIMITER //
CREATE PROCEDURE saludar(IN nombre_usuario VARCHAR(50))
BEGIN
SELECT CONCAT('Hola, ', nombre_usuario) AS saludo;
END //
lu
DELIMITER ;

Llamada al procedimiento con parámetros:


CALL saludar('Pepe');

Explicación:
●​ Se le da un valor ('Pepe') al entrar.
PL

●​ Solo se usa para hacer cosas dentro del procedimiento.


●​ Fuera del procedimiento ese valor no cambia.

OUT ⇐ : solo sale (y empieza null)


DELIMITER //
CREATE PROCEDURE contar_usuarios(OUT total INT)
BEGIN
SELECT COUNT(*) INTO total FROM usuarios;
END //
DELIMITER ;

Llamada al procedimiento con parámetros:

-- Aunque pongamos un valor inicial, se sobrescribirá:


SET @total = 999;

P.Lluyot-25​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ 17
CALL contar_usuarios(@total); -- @total se convierte en NULL al entrar, y luego se
rellena con el valor real.
SELECT @total;

Explicación:
●​ La oficina no espera nada como entrada.
●​ Dentro se rellena el paquete (total) con un valor.
●​ IMPORTANTE: Si usas una variable de usuario como @total, al entrar al procedimiento
se inicializa automáticamente como NULL. No importa qué valor tuviera antes.
●​ Es como enviar un paquete de salida desde la oficina.

INOUT 🔁: entra y sale modificado


DELIMITER //
CREATE PROCEDURE duplicar(INOUT numero INT)
BEGIN
SET numero = numero * 2;

t
END //
DELIMITER ;

yo
Llamada al procedimiento con parámetros:
SET @valor = 10;
CALL duplicar(@valor);
SELECT @valor; -- Muestra 20

Explicación:
●​ La variable llega con un valor, como un paquete.
lu
●​ Se modifica dentro (duplicar).
●​ Sale de nuevo con el nuevo valor.
●​ Es entrada + salida al mismo tiempo.

Se proponen ejercicios de procedimientos usando tablas


PL

Ejercicios Prácticos II
6.​ Crear una tabla llamada usuarios, que almacene varios usuarios y sus passwords.​
Crear un procedimiento (ejemplo6_sp.sql) que reciba dos parámetros de entrada (un
usuario y un password) y que inserte un nuevo usuario con esos datos. Comprobar que si
modificamos una de las variables de entrada dentro del procedimiento, fuera de él la
variable no cambia (los parámetros de entrada son una copia de los parámetros
originales).
Crea la tabla usuario con los campos usuario, password, e inserta algunos registros
CREATE TABLE usuarios (
​ usuario varchar(15) primary key,
password varchar(15) NOT NULL
);
INSERT INTO usuarios values
( 'pepe', '1234'), ( 'juan', '1234') , ('ana', '1111');

○​ crea el procedimiento con dos parámetros de entrada (usuario y password).


inserta los datos en la tabla de usuarios
Trata de modificar el valor del parámetro de entrada usuario

P.Lluyot-25​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ 18
○​ Llama al procedimiento inicializando dos variables definidas por el usuario (@)
○​ Una vez llamado al procedimiento muestra el valor de las variables definidas por el usuario
para ver si han cambiado
7.​ Crear un procedimiento (ejemplo7_sp.sql) con un parámetro de de salida (paso de
parámetros por variable o referencia) y comprueba que por defecto su valor es Nulo.
Modifica su valor y muestralo tanto dentro del procedimiento como fuera de él.
○​ puedes contar el número de usuarios de la tabla de usuarios creada en el apartado anterior y
almacenarla en la variable de salida
○​ Llama al procedimiento con una variable definida por el usuario (@) con un valor asignado y
comprueba que en el procedimiento su valor por defecto es null
8.​ Crea un procedimiento (ejemplo8_sp.sql) con un parámetro de entrada-salida. El
procedimiento debe cambiar el valor de la variable. Realizar una prueba mostrando el valor
de la variable antes y después de llamar al procedimiento.
○​ Inicializa una variable de usuario (@)
○​ Llama al procedimiento pasandole dicha variable como parámetro de entrada-salida
○​ Muestra su valor dentro del procedimiento,
○​ Modifica su valor dentro del procedimiento y muestra el valor por pantalla
○​ Muestra el valor una vez finalizada la llamada al procedimiento

t
○​ forzar algunos errores con los tipos de variables.
9.​ Crea un procedimiento (ejemplo9_sp.sql) que compruebe si un usuario existe o no en la

yo base de datos. Mostrar un mensaje en forma de select.


○​ Es preferible mantener el password encriptado por lo que podemos insertar los password
usando el algoritmo SHA2:​
​ DROP TABLE IF EXISTS usuarios;
CREATE TABLE IF NOT EXISTS usuarios (

);
usuario VARCHAR(50) NOT NULL UNIQUE PRIMARY KEY,
password VARCHAR(64) NOT NULL -- para SHA2 256
lu
INSERT INTO usuarios (usuario, password)
VALUES ('pepe', SHA2('1234', 256)),
('ana', SHA2('hola123', 256));
○​ Si el usuario existe (no es necesario comprobar su password), mostrar un mensaje
afirmandolo, de lo contrario mostrar un mensaje indicando su inexistencia,
○​ Realizar el ejercicio empleando un SELECT COUNT
○​ Realizar el mismo ejercicio empleando SELECT usuario … y asignarlo a una variable..
PL

10.​ Crea un procedimiento (ejemplo10_sp.sql) con dos parámetros de entrada (usuario y


contraseña) y uno de salida (mensaje) Hacer uso de IF, ELSE para comprobar si un usuario
pasado por parámetros existe en la base de datos con esa contraseña. Devolvemos en la
variable de salida estos tres posibles valores: usuario no existe, password incorrecto o
usuario correcto.
○​ Emplear la tabla de usuario con el password encriptado.
○​ el password se pasa como parámetros sin encriptar, y es dentro del procedimiento donde
usamos la función SHA2(p_password,256) para obtener el password encriptado y poderlo
compar con el de la base de datos.
11.​ Crea una nueva tabla datos_personales con los campos: usuario, edad, ultimo_login,
num_accesos, (donde usuario es clave foránea de la tabla creada anteriormente).​
Insertar algunos datos de ejemplos.
create table datos_personales (
usuario varchar(10) NOT NULL PRIMARY KEY,
fecha_nacimiento date NULL,
ultimo_login timestamp NULL,
num_accesos INT NULL default 0,
foreign key (usuario) references usuarios (usuario) ON DELETE CASCADE

P.Lluyot-25​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ 19
);
Inserta algún registro en esta tabla para hacer pruebas usando diferentes fechas de nacimiento.​
Crea un procedimiento (ejemplo11_sp.sql) Hacer uso de case...when.. para comprobar si
un usuario pasado por parámetros es mayor de edad o no.
12.​ Crea un procedimiento (ejemplo12_sp.sql) que borre si existe la tabla artículos. Si no
existe debe crearla e insertar 10 artículos haciendo uso de un bucle WHILE...DO
○​ Asegúrate que has insertado 10 artículos y no 9 o 11.
13.​ Hacer un procedimiento (ejemplo13_sp.sql) de forma que cuando un usuario se
autentifique (comprobar que el usuario existe en la BD), actualice la tabla datos_personales
(aumente el número de acceso y almacene la fecha actual). Si por casualidad no existen
datos en la tabla datos_personales para ese usuario, hay que añadirlos. ​
Mostrar los datos de la tabla datos personales para ese usuario.
14.​ Crea un procedimiento (ejemplo14_sp.sql) que pasándole un número muestre una select
para cada número comprendido entre el número y 1. Si el número es 0 o negativo no
mostrará nada. Hacer uso de LOOP para implementar dicho procedimiento.
15.​ Crear un procedimiento (​ejemplo15_sp.sql​) que pasándole un número, inserte en la tabla
de artículos el artículo con clave el número p, controlar los errores de clave duplicada y

t
error al insertar null como clave. (CONTROL DE ERRORES→hacer más adelante)

yo
Ejercicio propuesto de repaso
Aplicar sanciones por impago de facturas​
(más complejo usando procedimiento y sin emplear control de errores)
Tenemos una tabla de clientes y otra de facturas. Queremos sancionar a los clientes que tienen
varias facturas impagadas.
CREATE TABLE clientes (
lu
id INT AUTO_INCREMENT PRIMARY KEY,
nombre VARCHAR(100),
bloqueado BOOLEAN DEFAULT FALSE,
nivel_riesgo ENUM ('Alto','Medio','Bajo') DEFAULT 'Bajo'
);
PL

CREATE TABLE facturas (


id INT AUTO_INCREMENT PRIMARY KEY,
cliente_id INT,
importe DECIMAL(10,2),
pagada BOOLEAN DEFAULT FALSE,
fecha DATE,
FOREIGN KEY (cliente_id) REFERENCES clientes(id)
);
INSERT INTO clientes(nombre) VALUES ('Carlos'), ('Laura'), ('Pedro'), ('Manuel');

INSERT INTO facturas(cliente_id, importe, pagada, fecha) VALUES


(1, 100.00, FALSE, '2024-12-01'),
(1, 80.00, FALSE, '2025-01-01'),
(1, 120.00, FALSE, '2025-02-01'),
(1, 90.00, FALSE, '2025-03-01'),
(2, 60.00, TRUE, '2025-03-01'),

P.Lluyot-25​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ 20
(3, 30.00, FALSE, '2025-02-11'),
(4, 55.00, TRUE, '2025-03-01'),
(4, 28.00, FALSE, '2025-03-04'),
(4, 36.00, FALSE, '2025-03-05');
Enunciado:
Crear un procedimiento llamado revisar_clientes_morosidad que:
●​ Revise cuántas facturas impagadas tiene un cliente dado.
●​ Si tiene más de 3 impagadas, lo marca como bloqueado y aumenta su nivel de riesgo a
"Alto".
●​ Si tiene entre 2 y 3 impagadas, se establece su riesgo como "Medio".
●​ Si tiene 1 o ninguna, su riesgo baja a "Bajo" y se asegura de que no esté bloqueado.
●​ El procedimiento recibe el ID del cliente y devuelve el número de facturas impagadas
y el nuevo estado de riesgo.

3.6.​ Modificación de procedimientos

t
ALTER PROCEDURE nombre_procedimiento;

yo
Se debe poseer el privilegio de ALTER ROUTINE para poder modificar
procedimientos y funciones. El uso de las distintas opciones se ha expuesto en el
apartado de creación.

3.7.​ Borrado de procedimientos


lu
DROP PROCEDURE [IF EXISTS] nombre_procedimiento
Al igual que para la modificación, se debe poseer el privilegio de ALTER ROUTINE
para poder borrar procedimientos y funciones

4.​ Funciones
PL

4.1.​ ¿Qué es una función?

Una función es un bloque de código SQL que realiza una tarea específica y devuelve un único
valor. A diferencia de los procedimientos, las funciones están diseñadas para ser utilizadas
directamente dentro de expresiones en sentencias SQL (como SELECT, WHERE, SET), lo que
las hace ideales para encapsular lógica reutilizable como cálculos, validaciones o conversiones
de datos.

Además, las funciones no pueden modificar datos, pero sí permiten encapsular lógica
reutilizable, como cálculos, validaciones o conversiones. (No podemos usar sentencias INSERT,
UPDATE, CREATE TABLE, etc…, sólo podemos devolver un valor)

Las funciones aumentan la claridad del código y la reutilización de operaciones comunes.

4.2.​ Sintaxis básica

P.Lluyot-25​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ 21
DELIMITER //
CREATE FUNCTION nombre_funcion(
param1 TIPO1,
param2 TIPO2,
...
)
RETURNS tipo_retorno
[CHARACTERISTICS ...] -- Opcional: DETERMINISTIC, NOT DETERMINISTIC,
SQL SECURITY, etc.
BEGIN
DECLARE variable_local TIPO;
-- Lógica de la función (puede incluir IF, CASE, bucles, etc.)
-- Debe haber al menos una sentencia RETURN
RETURN valor_a_devolver;
END //
DELIMITER ;

Características adicionales:

t
●​ DETERMINISTIC: Indica que la función siempre devuelve el mismo resultado
para los mismos parámetros de entrada. Es importante para la optimización y la

yo replicación. MySQL requiere especificar esto si la función no accede a datos de


tablas.
●​ NOT DETERMINISTIC: Indica que la función puede devolver resultados
diferentes para los mismos parámetros (p. ej., si usa `NOW()` o lee datos de
tablas). Es el valor por defecto si no se especifica.
●​ READS SQL DATA: Indica a MySQL que no modifica datos.
●​ NO SQL: Indica a MySQL que la función no usa sentencias SQL,
lu
4.3.​ Ejemplo básico

Por ejemplo:
DELIMITER $$
PL

DROP FUNCTION IF EXISTS cuadrado $$

CREATE FUNCTION cuadrado(n INT) RETURNS INT


DETERMINISTIC –no es necesario indicarlo
BEGIN
RETURN n * n;
END $$

DELIMITER ;

Llamada a la función​
SELECT cuadrado(3);

4.4.​ Parámetros en funciones

P.Lluyot-25​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ 22
A diferencia de los procedimientos las funciones sólo admiten parámetros de entrada (IN). No
pueden tener parámetros OUT o INOUT. Los parámetros se pasan por valor y se utilizan dentro
de la función para realizar los cálculos o la lógica necesaria.

Ejemplo:
DELIMITER //
DROP FUNCTION IF EXISTS calcular_iva //
CREATE FUNCTION calcular_iva(precio DECIMAL(10,2), tasa_iva DECIMAL(4,2))
RETURNS DECIMAL(10,2)
DETERMINISTIC -- Siempre devuelve lo mismo para los mismos inputs
BEGIN
DECLARE iva_calculado DECIMAL(10,2);
SET iva_calculado = precio * tasa_iva;
RETURN iva_calculado;
END //
DELIMITER ;

t
Llamada a la función
SELECT calcular_iva(100.00, 0.21); -- Devuelve 21.00

yo
4.5.​ Variables locales en funciones
Al igual que en los procedimientos, se pueden declarar variables locales dentro del bloque
BEGIN ... END de una función utilizando DECLARE. Estas variables tienen alcance limitado a la
función y son útiles para almacenar resultados intermedios.
lu
Ejemplo:
DELIMITER //
CREATE FUNCTION evaluar_nota(nota DECIMAL(4,2))
RETURNS VARCHAR(20)
DETERMINISTIC
BEGIN
PL

DECLARE calificacion VARCHAR(20);


IF nota >= 9 THEN SET calificacion = 'Sobresaliente';
ELSEIF nota >= 7 THEN SET calificacion = 'Notable';
ELSEIF nota >= 5 THEN SET calificacion = 'Aprobado';
ELSE SET calificacion = 'Suspenso';
END IF;
RETURN calificacion;
END //
DELIMITER ;

Llamada a la función
SELECT evaluar_nota(8.5); -- Devuelve ‘Notable’

4.6.​ Llamada a funciones


Las funciones se llaman directamente como parte de una expresión SQL, no con CALL. Pueden
usarse en:

P.Lluyot-25​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ 23
●​ Cláusulas SELECT: ​
SELECT nombre, calcular_iva(precio, 0.21) AS iva FROM productos;
●​ Cláusulas WHERE: ​
SELECT nombre FROM alumnos WHERE evaluar_nota(nota_final) = 'Aprobado';
●​ Sentencias SET:​
SET @edad_calculada = calcular_edad('1990-05-15');
●​ Valores por defecto en CREATE TABLE o ALTER TABLE (con ciertas limitaciones).

4.7.​ Restricciones y Diferencias Clave con Procedimientos


●​ Valor de Retorno:
○​ Las funciones deben devolver un único valor escalar usando RETURN.
○​ Los procedimientos pueden devolver valores a través de parámetros OUT o
INOUT y también pueden devolver conjuntos de resultados (SELECT).
○​ No se permite modificar tablas (sin INSERT, UPDATE, DELETE)

t
●​ Modificación de Datos:
○​ Por defecto y por diseño, las funciones no deben realizar operaciones DML

yo (INSERT, UPDATE, DELETE) sobre tablas.


○​ Si intentan hacerlo, MySQL puede generar un error, especialmente si no se
declaran adecuadamente o si afectan a la tabla que está siendo consultada. Los
procedimientos sí pueden realizar estas operaciones libremente.
●​ Transacciones:
○​ Las funciones no pueden iniciar ni finalizar transacciones (START
TRANSACTION, COMMIT, ROLLBACK).
lu
●​ Llamada:
○​ Las funciones se integran en expresiones SQL. Los procedimientos se llaman
explícitamente con CALL.
●​ Uso:
○​ Las funciones son para cálculos, transformaciones y lógica que devuelve un
PL

valor para ser usado.


○​ Los procedimientos son para encapsular procesos o conjuntos de operaciones.

IMPORTANTE:

Por norma general el servidor no permite generar funciones a usuarios no administradores. Es


necesario en función de la configuración otorgar permisos de administrador para poder
elaborar las funciones. Ejemplo:

SET GLOBAL log_bin_trust_function_creators = 1; — esto permite crear


funciones a los usuarios

GRANT CREATE ROUTINE ON BD06.* TO 'programacion'@'%'; – otorga


permisos a un usuario.

4.8.​ Ejemplos prácticos adicionales


Ejemplo cálculo de edad:

P.Lluyot-25​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ 24
DELIMITER //
CREATE FUNCTION calcular_edad(fecha_nacimiento DATE)
RETURNS INT
DETERMINISTIC
BEGIN
RETURN TIMESTAMPDIFF(YEAR, fecha_nacimiento, CURDATE());
END //
DELIMITER ;

Llamada a la función
SELECT nombre, calcular_edad(fecha_nac) FROM empleados;

Ejemplo Obtención de nombre completo:


DELIMITER //
CREATE FUNCTION nombre_completo(nombre VARCHAR(50), apellido1 VARCHAR(50),
apellido2 VARCHAR(50))
RETURNS VARCHAR(160)

t
DETERMINISTIC
BEGIN

yo RETURN CONCAT_WS(' ', nombre, apellido1, IFNULL(apellido2, '')); --


Concatena con espacios, maneja apellido2 nulo
END //
DELIMITER ;

Llamada a la función
SELECT nombre_completo(nom, ape1, ape2) AS empleado FROM personal;
lu
4.9.​ Modificación y Borrado de Funciones
Modificación
Al igual que los procedimientos, las funciones pueden modificarse o eliminarse. Se requieren
los mismos privilegios (`ALTER ROUTINE`).
PL

ALTER FUNCTION nombre_funcion [CHARACTERISTICS ...]

Borrado
DROP FUNCTION [IF EXISTS] nombre_funcion;

ALTER FUNCTION` tiene limitaciones. A menudo es más práctico usar `DROP FUNCTION` y
`CREATE FUNCTION` de nuevo

4.10.​ Aplicaciones comunes


●​ Cálculo de edades a partir de fechas
●​ Transformación de formatos de texto o fechas
●​ Obtención de valores derivados (descuentos, totales, impuestos)
●​ Validación de rangos o condiciones

P.Lluyot-25​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ 25
Ejercicios Prácticos III
16.​ Crear una función (​ejemplo16_fun.sql​) de manera que reciba una cantidad de euros y
devuelva el valor expresado en pesetas. Llamar a dicha función en el interior de una select.
17.​ Crea una función (​ejemplo17_fun.sql​) de forma que pasándole un usuario nos devuelva su
edad actual (debe comprobar su fecha de nacimiento en el caso de existir y calcular su
edad actual).

Ejercicio propuestos
Validar nombre
Crea una función llamada es_nombre_valido que reciba un usuario (campo usuario). La función
deberá devolver TRUE o FALSE si el nombre cumple las siguientes condiciones:
●​ Tiene al menos 4 caracteres
●​ No contiene espacios
●​ No empieza por número

t
(Usar la tabla usuarios creada anteriormente)

yo
Número de acceso de usuarios a partir de una fecha
Crea una función accesos_desde_fecha(fecha DATE) que devuelva el total de accesos
(num_accesos) de los usuarios cuyo ultimo_login sea posterior a esa fecha.
(Usar la tabla datos_personales creada anteriormente)
lu
Porcentaje de usuarios activos
Crea una función porcentaje_usuarios_activos() que devuelva el porcentaje de usuarios que
han iniciado sesión en los últimos 15 días (ultimo_login) respecto al total de usuarios
existentes.​
PL

5.​ Triggers (Disparadores)


5.1.​ ¿Qué es un trigger?

Ejecuta automáticamente una acción cuando ocurre un evento (INSERT, UPDATE, DELETE).

Los triggers permiten reaccionar automáticamente ante cambios en los datos sin intervención
del usuario o del código externo. Son ideales para:

●​ Auditar cambios
●​ Validar condiciones antes de insertar o modificar registros
●​ Mantener datos sincronizados entre tablas
●​ Registrar automáticamente fechas de actualización

Añaden control y seguridad a las operaciones en la base de datos.

P.Lluyot-25​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ 26
5.2.​ Sintaxis básica

DELIMITER //
CREATE TRIGGER nombre_trigger
AFTER INSERT ON tabla
FOR EACH ROW
BEGIN
-- Acción
END //
DELIMITER ;

5.3.​ Tipos de triggers


BEFORE INSERT / UPDATE / DELETE
AFTER INSERT / UPDATE / DELETE​

t
5.4.​ Ejemplo: Auditoría
CREATE TRIGGER auditoria_insert

END;
yo
AFTER INSERT ON usuarios
FOR EACH ROW
BEGIN
INSERT INTO auditoria(tabla, accion, fecha)
VALUES ('usuarios', 'INSERT', NOW());

5.5.​ Buenas prácticas


lu
●​ Evita operaciones complejas que afecten al rendimiento.
●​ Asegúrate de que no entren en conflicto con otras lógicas (como procedimientos).
●​ No abuses de ellos: úsalos cuando la lógica realmente debe ejecutarse
automáticamente.
6.​ Tratamiento de errores
PL

6.1.​ Manejo de errores en MySQL

En los programas almacenados se pueden manejar errores mediante el uso de manejadores


(handlers). Estos permiten definir qué hacer cuando ocurre una condición específica, como un
error, una excepción o el final de una tabla.

6.2.​ Sintaxis básica


DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
BEGIN
-- Código a ejecutar si ocurre un error SQL
END;

Tipos de manejadores:
●​ CONTINUE: continúa tras el error.
●​ EXIT: sale del bloque actual.

P.Lluyot-25​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ 27
Condiciones que pueden capturarse:

●​ NOT FOUND: cuando no se encuentran más filas.


●​ SQLEXCEPTION: para cualquier error no capturado.
●​ SQLWARNING: para advertencias.

También se pueden usar códigos MySQL o SQLSTATE:

DECLARE CONTINUE HANDLER FOR 1062 -- Clave duplicada


SET @error = 'Clave duplicada';

DECLARE CONTINUE HANDLER FOR SQLSTATE '23000'


SET @error = 'Clave duplicada';

DECLARE EXIT HANDLER FOR SQLEXCEPTION
SET @error = 'Error genérico';

6.3.​ Ejemplo típico

t
Este procedimiento intenta insertar un alumno, pero si falla (por ejemplo, por clave duplicada),

yo
captura el error y muestra un mensaje personalizado.

CREATE PROCEDURE insertar_alumno(IN id INT, IN nombre VARCHAR(50))


BEGIN
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
BEGIN
SELECT 'Error al insertar alumno';
lu
END;
INSERT INTO alumnos VALUES(id, nombre);
END;

CREATE PROCEDURE insertar_usuario(


PL

IN p_id INT,
IN p_nombre VARCHAR(50)
)
BEGIN
DECLARE mensaje VARCHAR(100);

-- Manejador para clave duplicada (error 1062)


DECLARE CONTINUE HANDLER FOR 1062


BEGIN
SET mensaje = ' Error: ID duplicado, no se puede insertar.';
SELECT mensaje AS resultado;
END;

-- Manejador para cualquier otro error SQL


DECLARE CONTINUE HANDLER FOR SQLEXCEPTION

⚠️
BEGIN
SET mensaje = ' Error general al insertar usuario.';
SELECT mensaje AS resultado;
END;

P.Lluyot-25​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ 28
-- Intentamos insertar
INSERT INTO usuarios(id, nombre) VALUES(p_id, p_nombre);


-- Si no hay error, mensaje de éxito
SET mensaje = ' Usuario insertado correctamente.';
SELECT mensaje AS resultado;
END $$

DELIMITER ;

6.4.​ Generación de Errores (SIGNAL)

Además de manejar errores que ocurren automáticamente (como claves duplicadas o


divisiones por cero), a menudo necesitamos que nuestros propios programas almacenados
generen un error para indicar una situación no deseada o una validación fallida. Aquí es donde
entra la instrucción SIGNAL.

t
SIGNAL interrumpe la ejecución normal del programa almacenado y devuelve información de
error al cliente (o al manejador de errores que lo haya llamado).

yo
El código SQLSTATE '45000' está reservado en MySQL para excepciones definidas por el
usuario. Es la forma estándar de indicar un error que no es un error de base de datos
predefinido, sino un problema lógico de nuestro programa (ej: un parámetro no válido, una
condición de negocio que no se cumple, etc.).

SIGNAL SQLSTATE '45000'


lu
SET MESSAGE_TEXT = 'Mensaje de error personalizado aquí',

ejemplo:

-- Borramos el procedimiento si ya existe para poder crearlo de nuevo


PL

DROP PROCEDURE IF EXISTS validar_numero_rango //

-- Creamos el procedimiento
CREATE PROCEDURE validar_numero_rango (
IN p_numero INT,
IN p_limite_inferior INT,
IN p_limite_superior INT,
OUT mensaje_validacion VARCHAR(100)
)
BEGIN
-- Validamos si el número está fuera del rango permitido
IF p_numero < p_limite_inferior OR p_numero > p_limite_superior THEN
-- Si está fuera del rango, generamos un error personalizado
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = CONCAT('Error: El número ', p_numero, ' está
fuera del rango permitido [', p_limite_inferior, ', ', p_limite_superior,
'].');
-- NOTA: Cuando SIGNAL se ejecuta, el procedimiento termina
inmediatamente.

P.Lluyot-25​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ 29
-- La línea SET mensaje_validacion de abajo NO se ejecutará en caso
de error.
ELSE
-- Si el número está dentro del rango, asignamos un mensaje de éxito
SET mensaje_validacion = CONCAT('El número ', p_numero, ' es
válido.');
END IF;

END //

DELIMITER ;

7.​ Ejercicios complejos propuestos:


7.1.​ Gestión de puntos y premios en una tienda de fidelización

t
Una tienda tiene un sistema de fidelización de clientes. Cada vez que un cliente realiza una

yo
compra, se le asignan puntos. Cuando alcanza cierto umbral, puede canjear los puntos por un
premio. Además, si un cliente no realiza compras en más de 6 meses, pierde todos sus puntos.

-- Tabla de clientes
CREATE TABLE clientes (
id_cliente INT AUTO_INCREMENT PRIMARY KEY,
nombre VARCHAR(100),
lu
fecha_ultima_compra DATE,
puntos_acumulados INT DEFAULT 0
);

-- Tabla de compras
CREATE TABLE compras (
PL

id_compra INT AUTO_INCREMENT PRIMARY KEY,


id_cliente INT,
fecha_compra DATE,
importe DECIMAL(10,2),
FOREIGN KEY (id_cliente) REFERENCES clientes(id_cliente)
);

-- Tabla de premios
CREATE TABLE premios (
id_premio INT AUTO_INCREMENT PRIMARY KEY,
descripcion VARCHAR(100),
puntos_necesarios INT
);

-- Tabla de premios entregados


CREATE TABLE premios_entregados (
id_entrega INT AUTO_INCREMENT PRIMARY KEY,

P.Lluyot-25​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ 30
id_cliente INT,
id_premio INT,
fecha_entrega DATE,
FOREIGN KEY (id_cliente) REFERENCES clientes(id_cliente),
FOREIGN KEY (id_premio) REFERENCES premios(id_premio)
);

-- Datos de prueba
INSERT INTO clientes (nombre, fecha_ultima_compra,
puntos_acumulados) VALUES
('Ana García', '2024-10-01', 20),
('Luis Pérez', '2023-06-01', 45),
('Marta López', '2025-03-01', 10);

INSERT INTO premios (descripcion, puntos_necesarios) VALUES


('Taza de café', 15),
('Camiseta', 30),

t
('Mochila', 50);

yo
Enunciado:​
Diseña un procedimiento almacenado llamado procesar_compra que gestione el sistema de
fidelización de una tienda. Este procedimiento debe:

●​ Recibir el ID del cliente, el importe de la compra y un indicador booleano sobre si el


cliente quiere canjear un premio.
●​ En primer lugar, obtener del cliente la fecha de su última compra y sus puntos actuales.
lu
●​ Si el cliente lleva más de 6 meses sin comprar, debe reiniciarse su contador de puntos a
cero.
●​ Por cada 10€ gastados, se añade 1 punto.
●​ La compra debe registrarse en la tabla correspondiente.
●​ Si el cliente solicita canjear un premio, se le entregará automáticamente el premio más
PL

barato disponible según sus puntos acumulados.


●​ Si se entrega un premio, se insertará un registro en la tabla premios_entregados y se
descontarán los puntos necesarios.
●​ Finalmente, deben actualizarse los puntos acumulados y la fecha de última compra del
cliente en la tabla clientes.

Este procedimiento debe utilizar condiciones, control de errores y consultas para extraer y
actualizar la información necesaria en varias tablas relacionadas.

Ejemplo de llamada al procedimiento:

CALL revisar_clientes_morosidad(1, @impagadas, @riesgo);

P.Lluyot-25​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ 31
7.2.​ Gestión de Stock Simple

Procedimiento: Este procedimiento permitirá añadir stock a un producto existente. Validará


que el producto exista y la cantidad sea positiva. Usará un HANDLER para capturar cualquier
error SQL inesperado durante la actualización.

-- Usar una base de datos existente o crear una nueva


DROP DATABASE IF EXISTS gestion_stock;
CREATE DATABASE gestion_stock;
USE gestion_stock;

-- Eliminamos la tabla si existe


DROP TABLE IF EXISTS productos;

-- Creamos la tabla de productos

t
CREATE TABLE productos (
id_producto INT AUTO_INCREMENT PRIMARY KEY,

);
yo
nombre_producto VARCHAR(100) NOT NULL UNIQUE, -- Nombre único
para cada producto
stock INT NOT NULL DEFAULT 0 CHECK (stock >= 0) -- Stock no
puede ser negativo

-- Insertamos algunos datos de prueba


lu
INSERT INTO productos (nombre_producto, stock) VALUES
('Ordenador Portátil', 50),
('Ratón Inalámbrico', 150),
('Monitor 24"', 30);
PL

Función:
Crea una función que devuelva el valor actual del stock de un producto, y en el caso de error
devolver el valor -1.
por ejemplo:​
SELECT nombre_producto , obtener_stock(id_producto) from productos;

Procedimiento:
Crear un procedimiento llamado anadir_stock que reciba el identificador del producto, la
cantidad a sumar en stock y devuelva un mensaje con el resultado

Realiza las siguientes acciones:


●​ valida que el producto exista, de lo contrario generar un mensaje de salida con el error
●​ valida que la cantidad a sumar sea positiva, de lo contrario generar un mensaje de salida
con el error
●​ Capturar cualquier posible excepción, generando un mensaje de salida.
●​ Haz uso de la función anterior dentro del procedimiento

P.Lluyot-25​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ 32
●​ Si las validaciones son correctas actualizar el stock y devolver un mensaje de éxito.

t
yo
lu
PL

P.Lluyot-25​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ 33
t
yo
lu
PL

P.Lluyot-25​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ 34

También podría gustarte