Pregunta 1Escribiste REFERENCES category(cat_id) en una columna, y aun así entró una fila que apuntaba a una category inexistente. ¿Cuál es la causa más probable?
Restricciones de clave foránea y acciones referenciales (ON DELETE / ON UPDATE)
Con un montaje padre/hijo category–item, aprende REFERENCES para la integridad referencial, por qué se requiere PRAGMA foreign_keys=ON para activar las comprobaciones, y cómo ON DELETE CASCADE / SET NULL / RESTRICT propagan los borrados del padre — todo práctico.
Los datos que vamos a usar — category e item
Una restricción de clave foránea (la restricción que garantiza que el valor de una columna existe siempre como clave primaria en otra tabla) es el mecanismo que protege la integridad referencial entre tablas (el estado en el que cada fila referenciada existe realmente).
Bloquea contradicciones como "un item apunta a una category inexistente" o "eliminar una category deja a sus items colgando", en la capa de base de datos.
La comprobación de claves foráneas se activa con PRAGMA foreign_keys=ON
Las restricciones de clave foránea se declaran escribiendo REFERENCES tabla_padre(col_padre) en la definición de columna de la tabla hija.
item.cat_id lleva REFERENCES category(cat_id), que codifica la regla: cada valor de item.cat_id debe existir en category.
Sin embargo, en la consola de este curso la comprobación de claves foráneas está por defecto desactivada (PRAGMA foreign_keys es 0).
Mientras está desactivada, `REFERENCES` no se aplica realmente y se pueden insertar filas que apuntan a una category inexistente.
Para aplicar realmente la restricción, ejecuta PRAGMA foreign_keys=ON; una vez por conexión.
-- Activa la comprobación de claves foráneas
PRAGMA foreign_keys=ON;
-- Confirma el estado (1 significa activada)
PRAGMA foreign_keys;
-- Intenta insertar una fila que apunta a cat_id=99 (no está en category)
-- Con foreign_keys=ON, esto se rechaza con FOREIGN KEY constraint failed
INSERT INTO item VALUES (5,'Mouse',99);
ON DELETE — qué hacer con las filas hijas cuando se elimina una fila padre
Cuando se elimina una fila padre (category), ¿qué debe pasar con las filas hijas (item) que apuntaban a ella? Lo decides escribiendo una acción referencial en la cláusula REFERENCES.
Hay tres acciones referenciales habituales.
ON DELETE CASCADE significa que eliminar el padre también elimina a los hijos (borrado en cascada), ON DELETE SET NULL significa que la columna de referencia del hijo se pone a NULL y la fila se conserva, y ON DELETE RESTRICT significa que se rechaza el propio borrado del padre mientras los hijos aún lo referencian.
Si no especificas ninguna acción, el valor por defecto también es similar a RESTRICT (un padre referenciado no puede eliminarse).
Qué comportamiento es apropiado depende del requisito de negocio.
En el siguiente ejercicio configurarás SET NULL y RESTRICT lado a lado en una sola consola para compararlos.
| Acción referencial | Cuando se elimina el padre category | Qué pasa con el item hijo |
|---|---|---|
| ON DELETE CASCADE | Eliminado | Los hijos se eliminan en cascada junto con él |
| ON DELETE SET NULL | Eliminado | Los hijos permanecen, cat_id pasa a NULL |
| ON DELETE RESTRICT | No se puede eliminar — da error | Se rechaza el borrado del padre mientras existan hijos (intactos) |
-- Ejemplo de declaración con ON DELETE SET NULL
CREATE TABLE cat_demo(cat_id INTEGER PRIMARY KEY, cat_name TEXT NOT NULL);
CREATE TABLE item_demo(
item_id INTEGER PRIMARY KEY,
item_name TEXT NOT NULL,
cat_id INTEGER REFERENCES cat_demo(cat_id) ON DELETE SET NULL
);
INSERT INTO cat_demo VALUES (1,'Stationery'),(2,'Electronics');
INSERT INTO item_demo VALUES (1,'Pen',1),(2,'Phone',2),(3,'Cable',2);
-- Eliminar el padre cat_id=2 pone a NULL el cat_id de Phone / Cable
DELETE FROM cat_demo WHERE cat_id=2;
SELECT item_id, item_name, cat_id FROM item_demo ORDER BY item_id;
SET NULL y RESTRICT — elige entre conservar y rechazar
ON DELETE SET NULL conserva la fila hija cuando se elimina el padre, simplemente reemplazando la columna de referencia con NULL.
Úsalo cuando no quieras eliminar el registro hijo en sí, como "conserva el item como 'sin categoría'".
Si la columna de referencia del hijo es NOT NULL, no se puede escribir NULL, así que las columnas usadas con SET NULL deben permitir NULL.
ON DELETE RESTRICT rechaza el propio borrado del padre mientras los hijos aún lo referencian.
Úsalo cuando quieras fallar de forma segura (no tirar accidentalmente una fila maestra que aún está referenciada).
Una vez que has eliminado o reasignado todos los hijos para que no queden referencias, el padre puede eliminarse.
En el siguiente ejercicio configurarás SET NULL y RESTRICT lado a lado en una sola consola para compararlos.
-- Ejemplo de RESTRICT: un padre con hijos no puede eliminarse
CREATE TABLE cat_r(cat_id INTEGER PRIMARY KEY, cat_name TEXT NOT NULL);
CREATE TABLE item_r(
item_id INTEGER PRIMARY KEY,
item_name TEXT NOT NULL,
cat_id INTEGER REFERENCES cat_r(cat_id) ON DELETE RESTRICT
);
INSERT INTO cat_r VALUES (1,'Stationery'),(2,'Electronics');
INSERT INTO item_r VALUES (1,'Pen',1);
-- cat_id=1 está referenciado por item_r, así que se rechaza el borrado
DELETE FROM cat_r WHERE cat_id=1;
-- cat_id=2 no tiene referencias, así que se puede eliminar
DELETE FROM cat_r WHERE cat_id=2;
SELECT * FROM cat_r ORDER BY cat_id;
Verificación de conocimientos
Responde cada pregunta una a una.
Pregunta 2¿Qué acción referencial hace que una fila hija se elimine automáticamente cuando se elimina su fila padre?
Pregunta 3¿Qué condición debe cumplir la columna de referencia de la tabla hija para usar ON DELETE SET NULL?