Relaciones · integridad referencial

ON DELETE CASCADE con FOREIGN KEY

Entiende cuándo un borrado debe propagarse de una fila padre a sus filas hijas y cómo evitar cascadas que no representen la regla real del negocio.

Lectura: 10–12 minEjemplos comprobadosPráctica con pistas
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.

Patrón
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.

Dirección de la relación
ElementoEjemploPapel
Tabla padrepedidosSu id es referenciado
Tabla hijadetalle_pedidoGuarda pedido_id
AcciónON DELETE CASCADEEl 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.

SQL comprobado en SQLite
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;
Detalle que permanece después de borrar el pedido 1
idpedido_idproducto
1032Monitor

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.

Elegir una acción ON DELETE
SituaciónAcción a evaluarIdea
El hijo no tiene sentido sin el padreCASCADEEliminar ambos mantiene el modelo coherente
Padre e hijo son entidades independientesRESTRICT / NO ACTIONObliga a resolver la relación de forma explícita
La relación es opcional y el hijo puede sobrevivirSET NULLConserva 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:

Preflight
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.

Índice habitual
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

Intermedia · FOREIGN KEY

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.

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 CASCADE borra 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.

Conceptos relacionados

Fuentes técnicas consultadas