Volver a MySQL Básico

Procedimientos Almacenados y Triggers en MySQL

Procedimientos Almacenados

DELIMITER // CREATE PROCEDURE crear_pedido( IN p_cliente_id INT, IN p_total DECIMAL(10,2), OUT p_pedido_id INT ) BEGIN DECLARE EXIT HANDLER FOR SQLEXCEPTION BEGIN ROLLBACK; RESIGNAL; END; START TRANSACTION; INSERT INTO pedidos(cliente_id, total, estado) VALUES (p_cliente_id, p_total, 'pendiente'); SET p_pedido_id = LAST_INSERT_ID(); UPDATE clientes SET total_pedidos = total_pedidos + p_total WHERE id = p_cliente_id; COMMIT; END // DELIMITER ; -- Llamar al procedimiento CALL crear_pedido(1, 299.99, @nuevo_id); SELECT @nuevo_id;

Variables y Lógica de Control

DELIMITER // CREATE PROCEDURE calcular_descuento(IN precio DECIMAL(10,2)) BEGIN DECLARE descuento DECIMAL(10,2); DECLARE precio_final DECIMAL(10,2); IF precio >= 1000 THEN SET descuento = precio * 0.20; ELSEIF precio >= 500 THEN SET descuento = precio * 0.10; ELSE SET descuento = precio * 0.05; END IF; SET precio_final = precio - descuento; SELECT precio, descuento, precio_final; END // DELIMITER ;

Cursores

DELIMITER // CREATE PROCEDURE procesar_pedidos_pendientes() BEGIN DECLARE terminado INT DEFAULT 0; DECLARE v_id INT; DECLARE v_total DECIMAL(10,2); DECLARE cur CURSOR FOR SELECT id, total FROM pedidos WHERE estado = 'pendiente'; DECLARE CONTINUE HANDLER FOR NOT FOUND SET terminado = 1; OPEN cur; bucle: LOOP FETCH cur INTO v_id, v_total; IF terminado = 1 THEN LEAVE bucle; END IF; UPDATE pedidos SET estado = 'procesando' WHERE id = v_id; -- lógica de negocio aquí... END LOOP; CLOSE cur; END // DELIMITER ;

Funciones Almacenadas

DELIMITER // CREATE FUNCTION precio_formateado(precio DECIMAL(10,2)) RETURNS VARCHAR(20) DETERMINISTIC BEGIN RETURN CONCAT('$', FORMAT(precio, 2)); END // DELIMITER ; -- Usar como función SQL normal SELECT nombre, precio_formateado(precio) AS precio_fmt FROM productos;

Triggers

-- Trigger BEFORE INSERT para validación DELIMITER // CREATE TRIGGER validar_precio BEFORE INSERT ON productos FOR EACH ROW BEGIN IF NEW.precio <= 0 THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'El precio debe ser mayor que 0'; END IF; SET NEW.actualizado_en = NOW(); END // DELIMITER ; -- Trigger AFTER UPDATE para auditoría DELIMITER // CREATE TRIGGER auditar_precio AFTER UPDATE ON productos FOR EACH ROW BEGIN IF OLD.precio != NEW.precio THEN INSERT INTO auditoria_precios(producto_id, precio_anterior, precio_nuevo, cambiado_en) VALUES (NEW.id, OLD.precio, NEW.precio, NOW()); END IF; END // DELIMITER ;

Eventos Programados

-- Habilitar el planificador de eventos SET GLOBAL event_scheduler = ON; -- Evento para limpiar datos viejos diariamente DELIMITER // CREATE EVENT limpiar_sesiones_viejas ON SCHEDULE EVERY 1 DAY STARTS CURRENT_TIMESTAMP DO BEGIN DELETE FROM sesiones WHERE creado_en < DATE_SUB(NOW(), INTERVAL 30 DAY); END // DELIMITER ;