BEFORE UPDATE
Un trigger BEFORE UPDATE se ejecuta antes de que una fila existente sea modificada. Tiene acceso a OLD con los valores actuales y NEW con los valores que se van a guardar. Puede modificar NEW o cancelar la operación.
Sintaxis
DELIMITER //
CREATE TRIGGER nombre_trigger
BEFORE UPDATE ON nombre_tabla
FOR EACH ROW
BEGIN
-- OLD.columna = valor actual
-- NEW.columna = valor nuevo (modificable)
END //
DELIMITER ;Validar cambios
DELIMITER //
CREATE TRIGGER tr_productos_before_update
BEFORE UPDATE ON productos
FOR EACH ROW
BEGIN
-- No permitir precio negativo
IF NEW.precio < 0 THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'El precio no puede ser negativo';
END IF;
-- No permitir reducción de precio mayor al 50%
IF NEW.precio < OLD.precio * 0.5 THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'No se puede reducir el precio más del 50%';
END IF;
-- No permitir stock negativo
IF NEW.stock < 0 THEN
SET NEW.stock = 0;
END IF;
END //
DELIMITER ;-- Esto funciona: reducción del 10%
UPDATE productos SET precio = 1169.99 WHERE id = 1;
-- Esto falla: reducción mayor al 50%
-- UPDATE productos SET precio = 100 WHERE id = 1;
-- Error: No se puede reducir el precio más del 50%-- Restaurar
UPDATE productos SET precio = 1299.99 WHERE id = 1;Prevenir cambios en campos protegidos
DELIMITER //
CREATE TRIGGER tr_pedidos_before_update
BEFORE UPDATE ON pedidos
FOR EACH ROW
BEGIN
-- No permitir cambiar el cliente de un pedido
IF OLD.cliente_id != NEW.cliente_id THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'No se puede cambiar el cliente de un pedido existente';
END IF;
-- No permitir reactivar pedidos cancelados
IF OLD.estado = 'cancelado' AND NEW.estado != 'cancelado' THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'No se puede reactivar un pedido cancelado';
END IF;
-- Validar transiciones de estado
IF OLD.estado = 'entregado' AND NEW.estado = 'pendiente' THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'No se puede volver a estado pendiente un pedido entregado';
END IF;
END //
DELIMITER ;Ejemplo con OLD y NEW
DELIMITER //
CREATE TRIGGER tr_resenas_before_update
BEFORE UPDATE ON resenas
FOR EACH ROW
BEGIN
-- Validar que la puntuación esté en rango
IF NEW.puntuacion < 1 OR NEW.puntuacion > 5 THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'La puntuación debe estar entre 1 y 5';
END IF;
END //
DELIMITER ;Limpieza
DROP TRIGGER IF EXISTS tr_productos_before_update;
DROP TRIGGER IF EXISTS tr_pedidos_before_update;
DROP TRIGGER IF EXISTS tr_resenas_before_update;En el siguiente artículo veremos los triggers AFTER UPDATE.
Escrito por Eduardo Lázaro
