Ejemplos Prácticos de SQL Avanzado: Procedimientos, Triggers, Eventos y Manejo de Errores

Clasificado en Informática

Escrito el en español con un tamaño de 7,74 KB

Contar Empleados con Procedimiento Almacenado

Crear un procedimiento almacenado que cuente los empleados registrados en la tabla PERSONAL y muestre el total en pantalla.


CREATE PROCEDURE contarPersonal()
BEGIN
    DECLARE n INT DEFAULT 0;
    DECLARE done INT DEFAULT 0;
    DECLARE dni_empleado INT; -- Renombrado para claridad
    DECLARE cursor1 CURSOR FOR SELECT DNI FROM PERSONAL;
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;

    OPEN cursor1;

    read_loop: REPEAT
        FETCH cursor1 INTO dni_empleado;
        IF done = 0 THEN
            SET n = n + 1;
        END IF;
    UNTIL done END REPEAT read_loop;

    CLOSE cursor1;

    SELECT n AS 'Nº de empleados';
END;

Actualizar Fechas y Crear Vista de Cuentas

Modificar la fecha de apertura de las cuentas creadas en 2011 para que sea 1 de enero de 2014. Posteriormente, crear una vista que muestre las cuentas abiertas durante el año 2014.


-- Actualizar fechas de 2011 a 2014
UPDATE cuentas 
SET fecha_creacion = '2014-01-01'
WHERE fecha_creacion BETWEEN '2011-01-01' AND '2011-12-31';

-- Crear vista para cuentas de 2014
CREATE VIEW vista_cuentas_2014 AS
SELECT cod_cuenta, fecha_creacion -- Añadido cod_cuenta para más utilidad
FROM cuentas
WHERE fecha_creacion BETWEEN '2014-01-01' AND '2014-12-31';

Identificar Mes y Año con Mejor Saldo Total (Evento y Procedimiento)

Implementar una solución para determinar el mes y año con el mejor saldo total acumulado en la base de datos ebanca, utilizando un evento para registrar saldos mensuales y un procedimiento para consultar el máximo.


-- Evento para registrar saldo total mensual
CREATE EVENT registrar_saldo_mensual
ON SCHEDULE EVERY 1 MONTH
STARTS CURRENT_TIMESTAMP -- O una fecha de inicio específica
DO
BEGIN
    DECLARE nsaldo DECIMAL(15, 2); -- Ajustar precisión si es necesario
    DECLARE nmes INT;
    DECLARE nanio INT;

    SELECT SUM(saldo), MONTH(NOW()), YEAR(NOW())
    FROM cuentas
    INTO nsaldo, nmes, nanio;

    -- Asumiendo que existe la tabla saldo_mes(saldototal DECIMAL, mes INT, anio INT)
    INSERT INTO saldo_mes (saldototal, mes, anio) 
    VALUES (nsaldo, nmes, nanio);
END;

-- Procedimiento para obtener el mes/año con máximo saldo registrado
CREATE PROCEDURE obtener_mejor_saldo_mes()
BEGIN
    SELECT saldototal, mes, anio 
    FROM saldo_mes
    WHERE saldototal = (SELECT MAX(saldototal) FROM saldo_mes);
END;

Auditar Modificaciones en Tabla Movimientos con Trigger

Crear un trigger para auditar quién y cuándo modifica la tabla movimientos en la base de datos ebanca. El trigger debe registrar los datos antiguos y nuevos de cada fila actualizada en una tabla de auditoría (auditoria_mov).


CREATE TRIGGER auditar_movimientos_update
AFTER UPDATE ON movimientos
FOR EACH ROW
BEGIN
    -- Asumiendo tabla auditoria_mov con columnas adecuadas
    INSERT INTO auditoria_mov (
        cod_cuenta_ant, fecha_ant, cantidad_ant, 
        cod_cuenta_n, fecha_n, cantidad_n, 
        usuario, fecha_mod
    )
    VALUES (
        OLD.cod_cuenta, OLD.fecha, OLD.cantidad, 
        NEW.cod_cuenta, NEW.fecha, NEW.cantidad, 
        CURRENT_USER(), NOW()
    );
END;

Programar Bonificación con Evento

Crear un evento en la base de datos ebanca que se ejecute una vez, un mes a partir de ahora, y otorgue una bonificación de 100€ a las cuentas que fueron creadas hoy.


CREATE EVENT bonificacion_nuevas_cuentas
ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 MONTH
DO
    UPDATE ebanca.cuentas -- Asegúrate que la tabla es 'cuentas'
    SET saldo = saldo + 100 
    WHERE DATE(fecha_creacion) = DATE(CURRENT_DATE() - INTERVAL 1 MONTH); -- Bonifica cuentas creadas hace exactamente un mes respecto a la ejecución del evento.
    -- Si la intención era bonificar las creadas el día que se crea el evento:
    -- WHERE DATE(fecha_creacion) = DATE(CURRENT_DATE()); 

Registrar Ingresos Mensuales con Función y Trigger

Crear una tabla idia para almacenar la cantidad total de ingresos por mes. Desarrollar una función existe que verifique si ya existe un registro para un mes específico en idia. Implementar un trigger que, tras cada inserción en movimientos, actualice o inserte el total de ingresos del mes correspondiente en la tabla idia.

Tabla de Registro Mensual


CREATE TABLE idia (
    mes VARCHAR(20), -- Almacena el nombre del mes (e.g., 'January')
    cantidad DOUBLE, -- Almacena el total de ingresos del mes
    PRIMARY KEY (mes) -- Clave primaria para evitar duplicados
) ENGINE=InnoDB;

Función para Verificar Existencia del Mes


CREATE FUNCTION existe (pas_mes VARCHAR(20))
RETURNS INT
DETERMINISTIC -- Añadido ya que depende solo de la entrada y estado de la tabla
BEGIN
    DECLARE v_return INT DEFAULT 0;
    DECLARE v_mes VARCHAR(20) DEFAULT NULL;

    SELECT mes INTO v_mes 
    FROM idia 
    WHERE mes = pas_mes;

    IF v_mes IS NOT NULL THEN
        SET v_return = 1;
    END IF;
    
    RETURN v_return;
END;

Trigger para Actualizar/Insertar Ingresos Mensuales


CREATE TRIGGER registrar_ingreso_mensual
AFTER INSERT ON movimientos
FOR EACH ROW
BEGIN
    DECLARE nombre_mes VARCHAR(20);
    SET nombre_mes = MONTHNAME(NEW.fecha);

    IF existe(nombre_mes) = 0 THEN
        -- Si no existe registro para el mes, lo inserta
        INSERT INTO idia (mes, cantidad) 
        VALUES (nombre_mes, NEW.cantidad);
    ELSE
        -- Si ya existe, actualiza la cantidad sumando el nuevo ingreso
        UPDATE idia 
        SET cantidad = cantidad + NEW.cantidad 
        WHERE mes = nombre_mes;
    END IF;
END;

Auditoría Detallada de Actualizaciones en Movimientos (Trigger)

Implementar un trigger para registrar detalladamente quién y cuándo modifica la tabla movimientos en la base de datos ebanca. Se deben almacenar los valores antiguos y nuevos de cada columna modificada en la tabla auditoria_mov.


-- Nota: Este es un ejemplo similar al anterior, asegurando la correcta sintaxis.
CREATE TRIGGER auditar_movimientos_update_detalle -- Nombre ligeramente diferente si coexiste
AFTER UPDATE ON movimientos
FOR EACH ROW
BEGIN
    INSERT INTO auditoria_mov (
        cod_cuenta_ant, fecha_ant, cantidad_ant, 
        cod_cuenta_n, fecha_n, cantidad_n, 
        usuario, fecha_mod
    )
    VALUES (
        OLD.cod_cuenta, OLD.fecha, OLD.cantidad, 
        NEW.cod_cuenta, NEW.fecha, NEW.cantidad, 
        CURRENT_USER(), NOW()
    );
END;

Manejo de Errores de Integridad Referencial con Handler

Ejemplo de control de errores de integridad referencial (clave ajena, error 1452) durante una inserción en una tabla (t3), utilizando un HANDLER para registrar el error en una tabla error_log.


CREATE PROCEDURE procedimientoConHandler (parametro1 INT)
BEGIN
    -- Handler para el error específico de violación de clave ajena (1452)
    DECLARE EXIT HANDLER FOR 1452
    BEGIN
        -- Asumiendo que error_log tiene una columna 'mensaje' de tipo TEXT o VARCHAR
        INSERT INTO error_log (mensaje) 
        VALUES (CONCAT('Time: ', CURRENT_TIMESTAMP, '. Error de clave ajena (1452) al intentar insertar valor: ', parametro1));
    END;

    -- Intento de inserción que podría fallar por la clave ajena
    -- Asumiendo que t3 tiene una columna 'columna_fk' que es clave ajena
    INSERT INTO t3 (columna_fk) VALUES (parametro1);
    
    -- Si la inserción fue exitosa, se puede añadir lógica adicional aquí.
END;

Entradas relacionadas: