Sentencia CASE
La sentencia CASE proporciona una forma limpia de manejar múltiples condiciones. Hay dos formas: el CASE simple que compara un valor con opciones, y el CASE buscado que evalúa condiciones booleanas.
CASE simple
Compara una expresión con valores concretos:
CASE expresion
WHEN valor1 THEN sentencias;
WHEN valor2 THEN sentencias;
...
ELSE sentencias;
END CASE;DELIMITER //
CREATE PROCEDURE estado_pedido(IN ped_id INT)
BEGIN
DECLARE v_estado VARCHAR(20);
DECLARE v_descripcion VARCHAR(100);
SELECT estado INTO v_estado FROM pedidos WHERE id = ped_id;
CASE v_estado
WHEN 'pendiente' THEN
SET v_descripcion = 'El pedido está esperando ser procesado';
WHEN 'enviado' THEN
SET v_descripcion = 'El pedido está en camino';
WHEN 'entregado' THEN
SET v_descripcion = 'El pedido ha sido entregado';
WHEN 'cancelado' THEN
SET v_descripcion = 'El pedido fue cancelado';
ELSE
SET v_descripcion = 'Estado desconocido';
END CASE;
SELECT ped_id AS pedido, v_estado AS estado, v_descripcion AS descripcion;
END //
DELIMITER ;CALL estado_pedido(1);| pedido | estado | descripcion |
|---|---|---|
| 1 | entregado | El pedido ha sido entregado |
CALL estado_pedido(23);| pedido | estado | descripcion |
|---|---|---|
| 23 | pendiente | El pedido está esperando ser procesado |
CASE buscado
Evalúa condiciones booleanas independientes:
CASE
WHEN condicion1 THEN sentencias;
WHEN condicion2 THEN sentencias;
...
ELSE sentencias;
END CASE;DELIMITER //
CREATE PROCEDURE clasificar_cliente(IN cli_id INT)
BEGIN
DECLARE v_nombre VARCHAR(100);
DECLARE v_total_pedidos INT;
DECLARE v_total_gastado DECIMAL(10,2);
DECLARE v_clasificacion VARCHAR(20);
SELECT nombre INTO v_nombre FROM clientes WHERE id = cli_id;
SELECT COUNT(*), COALESCE(SUM(total), 0)
INTO v_total_pedidos, v_total_gastado
FROM pedidos WHERE cliente_id = cli_id;
CASE
WHEN v_total_gastado > 5000 THEN
SET v_clasificacion = 'VIP';
WHEN v_total_gastado > 2000 THEN
SET v_clasificacion = 'Premium';
WHEN v_total_gastado > 500 THEN
SET v_clasificacion = 'Regular';
WHEN v_total_pedidos > 0 THEN
SET v_clasificacion = 'Nuevo';
ELSE
SET v_clasificacion = 'Sin compras';
END CASE;
SELECT v_nombre AS cliente,
v_total_pedidos AS pedidos,
v_total_gastado AS total_gastado,
v_clasificacion AS clasificacion;
END //
DELIMITER ;CALL clasificar_cliente(1);| cliente | pedidos | total_gastado | clasificacion |
|---|---|---|---|
| María | 3 | 3899.97 | Premium |
CASE con múltiples sentencias
Cada rama WHEN puede contener múltiples sentencias:
DELIMITER //
CREATE PROCEDURE procesar_devolucion(IN ped_id INT)
BEGIN
DECLARE v_estado VARCHAR(20);
DECLARE v_mensaje VARCHAR(200);
SELECT estado INTO v_estado FROM pedidos WHERE id = ped_id;
CASE v_estado
WHEN 'entregado' THEN
UPDATE pedidos SET estado = 'cancelado' WHERE id = ped_id;
SET v_mensaje = 'Devolución procesada correctamente';
WHEN 'enviado' THEN
UPDATE pedidos SET estado = 'cancelado' WHERE id = ped_id;
SET v_mensaje = 'Envío interceptado y cancelado';
WHEN 'pendiente' THEN
UPDATE pedidos SET estado = 'cancelado' WHERE id = ped_id;
SET v_mensaje = 'Pedido cancelado antes del envío';
WHEN 'cancelado' THEN
SET v_mensaje = 'El pedido ya estaba cancelado';
ELSE
SET v_mensaje = 'No se puede procesar la devolución';
END CASE;
SELECT v_mensaje AS resultado;
END //
DELIMITER ;CASE simple vs CASE buscado
| Característica | CASE simple | CASE buscado |
|---|---|---|
| Compara | Un valor con opciones | Condiciones booleanas |
| Flexibilidad | Menor, solo igualdad | Mayor, cualquier condición |
| Legibilidad | Más limpio para valores discretos | Mejor para rangos |
| Rendimiento | Similar | Similar |
CASE vs IF
| Escenario | Recomendación |
|---|---|
| Valor con múltiples opciones | CASE simple |
| Rangos numéricos | CASE buscado o IF |
| Dos opciones | IF...ELSE |
| Lógica compleja con anidamiento | IF |
Importante: ELSE en CASE
Si ninguna condición WHEN coincide y no hay ELSE, MySQL genera un error:
-- Esto genera error si v_estado no coincide con ningún WHEN
CASE v_estado
WHEN 'activo' THEN SET x = 1;
WHEN 'inactivo' THEN SET x = 0;
-- Sin ELSE: Error 1339 - Case not found for CASE statement
END CASE;Siempre incluye una cláusula ELSE para evitar este error.
Limpieza
DROP PROCEDURE IF EXISTS estado_pedido;
DROP PROCEDURE IF EXISTS clasificar_cliente;
DROP PROCEDURE IF EXISTS procesar_devolucion;En el siguiente artículo veremos el bucle LOOP para repetir sentencias dentro de un procedimiento.
Escrito por Eduardo Lázaro
