WITH CHECK OPTION

WITH CHECK OPTION es una cláusula que se añade a las vistas actualizables para prevenir que un INSERT o UPDATE produzca filas que no cumplan la condición WHERE de la vista. Sin ella, podrías insertar o actualizar datos a través de una vista que luego "desaparecerían" de la misma.

Sintaxis

CREATE VIEW nombre_vista AS
SELECT columnas
FROM tabla
WHERE condicion
WITH CHECK OPTION;
 
-- Con nivel explícito
WITH LOCAL CHECK OPTION;   -- Solo verifica esta vista
WITH CASCADED CHECK OPTION;  -- Verifica esta vista y las vistas subyacentes (por defecto)

El problema sin CHECK OPTION

-- Vista de productos con stock disponible
CREATE VIEW v_productos_disponibles AS
SELECT id, nombre, precio, stock
FROM productos
WHERE stock > 0;
 
-- Actualizar stock a 0 a través de la vista
UPDATE v_productos_disponibles SET stock = 0 WHERE id = 7;
 
-- El producto "desaparece" de la vista
SELECT * FROM v_productos_disponibles WHERE id = 7;
-- (sin resultados)
 
-- Pero sigue en la tabla real
SELECT nombre, stock FROM productos WHERE id = 7;
nombrestock
ASUS ROG Zephyrus0
-- Restaurar
UPDATE productos SET stock = 12 WHERE id = 7;
DROP VIEW v_productos_disponibles;

La solución: WITH CHECK OPTION

-- Misma vista pero con CHECK OPTION
CREATE VIEW v_productos_disponibles AS
SELECT id, nombre, precio, stock
FROM productos
WHERE stock > 0
WITH CHECK OPTION;
 
-- Ahora este UPDATE falla
-- UPDATE v_productos_disponibles SET stock = 0 WHERE id = 7;
-- Error: CHECK OPTION failed 'tienda_mysql.v_productos_disponibles'

MySQL rechaza la operación porque el resultado violaría la condición stock > 0 de la vista.

-- Esto sí funciona: stock sigue siendo > 0
UPDATE v_productos_disponibles SET stock = 10 WHERE id = 7;
 
SELECT nombre, stock FROM v_productos_disponibles WHERE id = 7;
nombrestock
ASUS ROG Zephyrus10
-- Restaurar
UPDATE productos SET stock = 12 WHERE id = 7;

CHECK OPTION con INSERT

CREATE VIEW v_productos_activos_electronicos AS
SELECT id, nombre, precio, stock, activo
FROM productos
WHERE activo = TRUE AND categoria_id = 6
WITH CHECK OPTION;
 
-- Esto falla: activo = FALSE viola la condición
-- INSERT INTO v_productos_activos_electronicos (nombre, precio, stock, activo)
-- VALUES ('Test Phone', 99.99, 10, FALSE);
-- Error: CHECK OPTION failed

LOCAL vs CASCADED

La diferencia importa cuando tienes vistas basadas en otras vistas:

CASCADED (por defecto)

CREATE VIEW v_base AS
SELECT id, nombre, precio, stock
FROM productos
WHERE precio > 100;
 
CREATE VIEW v_derivada AS
SELECT id, nombre, precio, stock
FROM v_base
WHERE stock > 10
WITH CASCADED CHECK OPTION;
 
-- CASCADED verifica AMBAS condiciones:
-- 1. stock > 10 (condición de v_derivada)
-- 2. precio > 100 (condición de v_base)
 
-- Esto falla: precio = 50 viola la condición de v_base
-- UPDATE v_derivada SET precio = 50 WHERE id = 1;
-- Error: CHECK OPTION failed

LOCAL

DROP VIEW v_derivada;
 
CREATE VIEW v_derivada_local AS
SELECT id, nombre, precio, stock
FROM v_base
WHERE stock > 10
WITH LOCAL CHECK OPTION;
 
-- LOCAL solo verifica la condición de v_derivada_local:
-- Solo verifica stock > 10
-- NO verifica precio > 100 de v_base
 
-- Esto podría funcionar con LOCAL
-- UPDATE v_derivada_local SET precio = 50 WHERE id = 1;
TipoVerifica condición propiaVerifica vistas subyacentes
CASCADED
LOCALNo

Cuándo usar WITH CHECK OPTION

Caso de usoRecomendación
Vista de productos activosSí, evita desactivar accidentalmente
Vista por departamentoSí, evita mover datos entre departamentos
Vista de solo lecturaNo necesario
Vista con agregacionesNo aplica, ya no es actualizable

Limpieza

DROP VIEW IF EXISTS v_productos_disponibles;
DROP VIEW IF EXISTS v_productos_activos_electronicos;
DROP VIEW IF EXISTS v_derivada;
DROP VIEW IF EXISTS v_derivada_local;
DROP VIEW IF EXISTS v_base;

En el siguiente artículo veremos cómo modificar una vista existente con ALTER VIEW.

Escrito por Eduardo Lázaro