En esta píldora aprenderás los conceptos fundamentales de triggers y cómo aplicarlos en bases de datos.
Un Trigger es un procedimiento almacenado en una base de datos que se ejecuta automáticamente cuando ocurre un evento en una tabla (INSERT, UPDATE, DELETE).
Vamos a crear un trigger en la base de datos gestion_hospitalaria que registrará automáticamente los cambios en los nombres de los pacientes en una tabla de historial.
CREATE TABLE historial_pacientes (
id_historial INT AUTO_INCREMENT PRIMARY KEY,
id_paciente INT,
nombre_anterior VARCHAR(100),
nombre_nuevo VARCHAR(100),
fecha_cambio TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
TIMESTAMP DEFAULT CURRENT_TIMESTAMPEsta columna se usa para registrar automáticamente la fecha y hora de cada inserción en la tabla sin necesidad de introducirla manualmente.
fecha_cambio TIMESTAMP DEFAULT CURRENT_TIMESTAMP
TIMESTAMP: Tipo de dato que almacena fecha y hora (YYYY-MM-DD HH:MI:SS).DEFAULT CURRENT_TIMESTAMP: MySQL asigna la fecha y hora actual al insertar un nuevo registro.Si insertamos un nuevo registro SIN especificar la fecha:
INSERT INTO historial_pacientes (id_paciente, nombre_anterior, nombre_nuevo)
VALUES (1, 'Juan Pérez', 'Juan Gómez');
✅ **Salida esperada:** La columna fecha_cambio se llena automáticamente:
SELECT * FROM historial_pacientes;
| id_historial | id_paciente | nombre_anterior | nombre_nuevo | fecha_cambio |
|---|---|---|---|---|
| 1 | 1 | Juan Pérez | Juan Gómez | 2025-02-20 14:35:20 |
UPDATE?fecha_cambio TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
✅ Esto permite que la fecha se actualice automáticamente cada vez que se edite el registro.
TIMESTAMP DEFAULT CURRENT_TIMESTAMP permite automatizar el registro de fechas en bases de datos.DELIMITER //
CREATE TRIGGER before_update_paciente
BEFORE UPDATE ON pacientes
FOR EACH ROW
BEGIN
INSERT INTO historial_pacientes (id_paciente, nombre_anterior, nombre_nuevo)
VALUES (OLD.id_paciente, OLD.nombre, NEW.nombre);
END //
DELIMITER ;
El Trigger before_update_paciente se activa antes de actualizar un registro en la tabla pacientes, permitiendo guardar un historial de los cambios en los nombres de los pacientes.
DELIMITER //
🔹 Cambia el delimitador de MySQL de ; a // para que el motor no interprete erróneamente los ; dentro del trigger.
CREATE TRIGGER before_update_paciente
🔹 Crea un nuevo trigger llamado before_update_paciente.
BEFORE UPDATE ON pacientes
🔹 Se ejecuta antes de que ocurra un UPDATE en la tabla pacientes.
FOR EACH ROW
🔹 Se activa para cada fila que se actualice en la consulta.
FOR EACH ROWINSERT, UPDATE, DELETE).Si actualizamos múltiples filas, el trigger se ejecutará una vez por cada fila afectada:
UPDATE pacientes SET ciudad = 'Barcelona' WHERE ciudad = 'Madrid';
✅ Si hay 5 pacientes en Madrid, el trigger se ejecutará 5 veces, registrando cada cambio.
DELETEEvitar la eliminación de pacientes si tienen consultas registradas:
DELIMITER //
CREATE TRIGGER before_delete_paciente
BEFORE DELETE ON pacientes
FOR EACH ROW
BEGIN
IF (SELECT COUNT(*) FROM consultas WHERE id_paciente = OLD.id_paciente) > 0 THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'No se puede eliminar un paciente con consultas registradas';
END IF;
END //
DELIMITER ;
✅ Evita la eliminación de pacientes con consultas activas.
Reducir automáticamente el stock de productos después de una venta:
DELIMITER //
CREATE TRIGGER after_insert_ventas
AFTER INSERT ON ventas
FOR EACH ROW
BEGIN
UPDATE productos
SET stock = stock - NEW.cantidad
WHERE id_producto = NEW.id_producto;
END //
DELIMITER ;
✅ Actualiza el stock de productos automáticamente después de cada venta.
FOR EACH ROW NO es un bucle explícito, pero actúa fila por fila en cada evento INSERT, UPDATE o DELETE.
BEGIN
🔹 Inicio del bloque de código del trigger.
INSERT INTO historial_pacientes (id_paciente, nombre_anterior, nombre_nuevo)
VALUES (OLD.id_paciente, OLD.nombre, NEW.nombre);
INSERT INTO historial_pacientes: Guarda los datos en la tabla historial_pacientes.OLD.id_paciente: Obtiene el ID del paciente antes de la actualización.OLD.nombre: Guarda el nombre del paciente antes del cambio.NEW.nombre: Guarda el nuevo nombre después del cambio.END //
🔹 Indica el final del bloque del trigger.
DELIMITER ;
🔹 Restaura el delimitador predeterminado ; en MySQL.
Si un paciente tenía registrado su nombre como Juan Pérez y lo actualizamos a Juan Gómez:
UPDATE pacientes
SET nombre = 'Juan Gómez'
WHERE id_paciente = 1;
✅ Se almacenará automáticamente en historial_pacientes:
SELECT * FROM historial_pacientes;
| id_historial | id_paciente | nombre_anterior | nombre_nuevo | fecha_cambio |
|---|---|---|---|---|
| 1 | 1 | Juan Pérez | Juan Gómez | 2025-02-20 14:35:20 |
BEFORE UPDATE permite registrar cambios antes de la actualización.FOR EACH ROW garantiza que el trigger se ejecuta por cada paciente afectado.
Estos ejercicios te ayudarán a reforzar el uso de triggers en bases de datos con distintos escenarios prácticos.
📍 Objetivo: Registrar cada vez que la edad de un paciente se actualiza.
🔹 Pasos a seguir:
historial_edades para almacenar los cambios de edad.pacientes que registre la edad antes de la actualización.UPDATE para cambiar la edad de un paciente y verifica el historial.📍 Objetivo: No permitir que se elimine un doctor si todavía tiene consultas asignadas.
🔹 Pasos a seguir:
doctores para evitar eliminaciones si el doctor tiene consultas registradas.📍 Objetivo: Cada vez que se registre un nuevo paciente, guardar un historial con la fecha de ingreso.
🔹 Pasos a seguir:
historial_altas para registrar las altas de pacientes.pacientes para registrar cada nuevo ingreso.INSERT en pacientes y revisa el historial.