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;| nombre | stock |
|---|---|
| ASUS ROG Zephyrus | 0 |
-- 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;| nombre | stock |
|---|---|
| ASUS ROG Zephyrus | 10 |
-- 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 failedLOCAL 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 failedLOCAL
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;| Tipo | Verifica condición propia | Verifica vistas subyacentes |
|---|---|---|
| CASCADED | Sí | Sí |
| LOCAL | Sí | No |
Cuándo usar WITH CHECK OPTION
| Caso de uso | Recomendación |
|---|---|
| Vista de productos activos | Sí, evita desactivar accidentalmente |
| Vista por departamento | Sí, evita mover datos entre departamentos |
| Vista de solo lectura | No necesario |
| Vista con agregaciones | No 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
