Contenido de esta guía
Respuesta rápida
ON DELETE CASCADE hace que, al borrar una fila de la tabla referenciada por una FOREIGN KEY, se borren automáticamente las filas dependientes de la tabla que contiene esa clave foránea.
CREATE TABLE detalle_pedido (
id INTEGER PRIMARY KEY,
pedido_id INTEGER NOT NULL
REFERENCES pedidos(id) ON DELETE CASCADE
);Úsalo cuando la fila hija sea realmente una parte del objeto padre y no tenga sentido conservarla por separado. No lo actives como una forma genérica de «hacer que los borrados funcionen».
Tabla padre, tabla hija y dirección del borrado
Una clave foránea conecta una tabla hija con una tabla padre. En un pedido, pedidos puede ser la tabla padre y detalle_pedido la tabla hija: cada línea pertenece a un pedido concreto.
| Elemento | Ejemplo | Papel |
|---|---|---|
| Tabla padre | pedidos | Su id es referenciado |
| Tabla hija | detalle_pedido | Guarda pedido_id |
| Acción | ON DELETE CASCADE | El borrado del padre se propaga hacia sus filas hijas |
La dirección importa: borrar una línea de detalle_pedido no borra el pedido. La cascada se activa cuando desaparece la fila referenciada del padre.
Ejemplo completo: pedido y líneas
SQLite exige que la comprobación de claves foráneas esté habilitada en la conexión para aplicar estas acciones. El ejemplo la activa explícitamente y utiliza dos pedidos para comprobar que la cascada solo afecta al padre eliminado.
PRAGMA foreign_keys = ON;
CREATE TEMP TABLE pedidos_cascade (
id INTEGER PRIMARY KEY,
cliente TEXT NOT NULL
);
CREATE TEMP TABLE detalle_cascade (
id INTEGER PRIMARY KEY,
pedido_id INTEGER NOT NULL
REFERENCES pedidos_cascade(id) ON DELETE CASCADE,
producto TEXT NOT NULL
);
INSERT INTO pedidos_cascade VALUES
(1, 'Ana'),
(2, 'Luis');
INSERT INTO detalle_cascade VALUES
(101, 1, 'Teclado'),
(102, 1, 'Ratón'),
(103, 2, 'Monitor');
DELETE FROM pedidos_cascade
WHERE id = 1;
SELECT id, pedido_id, producto
FROM detalle_cascade
ORDER BY id;| id | pedido_id | producto |
|---|---|---|
| 103 | 2 | Monitor |
Las filas 101 y 102 desaparecen porque dependían del pedido 1. La fila 103 permanece porque pertenece al pedido 2. Esa selectividad es la consecuencia directa de la clave foránea.
Cuándo CASCADE representa bien la regla de negocio
CASCADE encaja cuando la existencia de la fila hija depende conceptualmente de la fila padre. Las líneas de un pedido son un ejemplo claro: una línea sin pedido dejaría de representar el mismo objeto de negocio.
| Situación | Acción a evaluar | Idea |
|---|---|---|
| El hijo no tiene sentido sin el padre | CASCADE | Eliminar ambos mantiene el modelo coherente |
| Padre e hijo son entidades independientes | RESTRICT / NO ACTION | Obliga a resolver la relación de forma explícita |
| La relación es opcional y el hijo puede sobrevivir | SET NULL | Conserva la fila hija y elimina el vínculo, si la columna acepta NULL |
PostgreSQL recomienda elegir la acción según la relación semántica entre los objetos. CASCADE es cómodo, pero una regla automática solo es correcta si expresa la política real del dominio.
No confundas ON DELETE CASCADE con DROP ... CASCADE
Ambos contienen la palabra CASCADE, pero resuelven problemas distintos. ON DELETE CASCADE pertenece a una FOREIGN KEY y actúa sobre filas relacionadas. En cambio, opciones como DROP ... CASCADE afectan objetos dependientes del esquema, por ejemplo constraints o vistas según el motor y la sentencia.
Cómo comprobar un borrado en cascada antes de ejecutarlo
Un borrado en cascada puede afectar muchas filas. Antes de borrar el padre, consulta primero las filas hijas que dependen de él:
SELECT id, pedido_id, producto
FROM detalle_pedido
WHERE pedido_id = 42;En operaciones sensibles, combina esta comprobación con una transacción: ejecuta el cambio, revisa el resultado y decide entre COMMIT y ROLLBACK cuando tu motor y flujo de trabajo lo permitan.
Índices en la columna hija
Al borrar una fila padre, el motor necesita localizar las filas hijas que la referencian. PostgreSQL señala que suele ser buena idea indexar las columnas de referencia de la tabla hija, aunque declarar una clave foránea no crea necesariamente ese índice de forma automática.
CREATE INDEX idx_detalle_pedido_pedido_id
ON detalle_pedido (pedido_id);No crees índices por reflejo: confirma el volumen, las consultas y el motor. La idea importante es que integridad referencial y estrategia de índices son decisiones relacionadas, pero no idénticas.
Errores frecuentes
Añadir CASCADE para evitar un error de FOREIGN KEY
Si la base bloquea un borrado, primero decide qué debería ocurrir con las filas hijas. Cambiar la restricción para que borre automáticamente datos no es una corrección neutra.
Creer que CASCADE borra «hacia arriba»
La acción configurada en la clave foránea se dispara cuando se elimina la fila referenciada. Borrar una fila hija no elimina automáticamente su padre.
Probar SQLite sin habilitar foreign_keys
Si la conexión no aplica la integridad referencial, una prueba puede dar la impresión de que la cascada no funciona. Activa y comprueba la configuración apropiada de la conexión antes de sacar conclusiones.
Práctica guiada
Haz que las líneas dependan de su pedido
Define pedidos_practica y lineas_practica. La columna pedido_id debe referenciar pedidos_practica(id) con ON DELETE CASCADE. Inserta un pedido 10 con dos líneas, bórralo y comprueba cuántas líneas quedan.
Criterio de éxito: después del DELETE, el recuento de líneas es 0.
PRAGMA foreign_keys = ON si practicas en SQLite.ON DELETE CASCADE en la referencia de pedido_id.pedidos_practica, no las líneas manualmente.Solución razonada
PRAGMA foreign_keys = ON;
CREATE TEMP TABLE pedidos_practica (
id INTEGER PRIMARY KEY
);
CREATE TEMP TABLE lineas_practica (
id INTEGER PRIMARY KEY,
pedido_id INTEGER NOT NULL
REFERENCES pedidos_practica(id) ON DELETE CASCADE
);
INSERT INTO pedidos_practica VALUES (10);
INSERT INTO lineas_practica VALUES
(1, 10),
(2, 10);
DELETE FROM pedidos_practica
WHERE id = 10;
SELECT COUNT(*) AS lineas_restantes
FROM lineas_practica;| lineas_restantes |
|---|
| 0 |
La clave foránea identifica las dos filas dependientes y la acción CASCADE las elimina como consecuencia del borrado del pedido.
Compatibilidad entre motores
PostgreSQL y SQLite documentan acciones referenciales como CASCADE, RESTRICT, SET NULL y otras variantes. MySQL también documenta acciones ON DELETE para claves foráneas. Los detalles de comprobación, restricciones diferibles y configuración varían por motor.
En SQLite, la aplicación de claves foráneas depende de la configuración de la conexión, por eso los ejemplos de esta página activan PRAGMA foreign_keys = ON de forma explícita.
Qué debes recordar
ON DELETE CASCADEborra filas hijas cuando se borra la fila padre referenciada.- Solo es apropiado cuando esa dependencia representa la regla real del modelo.
- No borra el padre cuando eliminas una fila hija.
- Haz un preflight de las filas dependientes antes de un borrado sensible.
- En SQLite, comprueba que la integridad de claves foráneas esté habilitada en la conexión.