Codemaker SQL

SQL Tema 6

Tablas relacionadas

En el mundo real, la información no está en una sola tabla gigante. Está repartida en varias tablas que se «conectan» entre sí. Esto evita repetir datos y mantiene la base de datos organizada.

El concepto de clave foránea (Foreign Key)#

Para conectar dos tablas usamos una clave foránea (Foreign Key, FK): una columna de una tabla que guarda el ID (la clave primaria, PK) de una fila de otra tabla.

TablaPapelClave primaria (PK)Clave foránea (FK)
alumnosTabla padre: existe por sí solaid_alumno—
tutoresTabla hija: cada tutor apunta a un alumnoid_tutorid_alumno, que apunta a alumnos

Importante

SQLite tiene desactivadas por defecto las claves foráneas. En cada sesión (cada vez que abras DBeaver u otro programa) debes ejecutar este comando para activarlas:

PRAGMA foreign_keys = ON;

Creación de tablas con relaciones#

Al crear la tabla hija, debemos avisar a SQL de que una de sus columnas está conectada a otra tabla. La tabla alumnos ya la tenemos del tema de creación de tablas; ahora creamos la de tutores:

CREATE TABLE tutores (
    id_tutor INTEGER PRIMARY KEY AUTOINCREMENT,
    nombre TEXT NOT NULL,
    pago TEXT NOT NULL CHECK (pago IN ('Efectivo', 'Bizum')),
    id_alumno INTEGER,
    FOREIGN KEY (id_alumno) REFERENCES alumnos(id_alumno)
);

La última línea se lee así: «la columna id_alumno de esta tabla tiene que coincidir con algún id_alumno de la tabla alumnos».

Inserción de datos con relaciones#

¡Importante! No puedes asignar un tutor a un alumno que no existe. Por eso, primero se insertan los alumnos (ya los tenemos) y después los tutores, indicando el id_alumno de cada uno:

SQL
INSERT INTO tutores (nombre, pago, id_alumno) VALUES
('Juana', 'Efectivo', 1),
('Paco', 'Bizum', 2),
('Pepe', 'Bizum', 3),
('Marta', 'Efectivo', 4);

Si intentas INSERT INTO tutores (nombre, pago, id_alumno) VALUES ('Luis', 'Bizum', 99);, SQLite dará un error, porque no hay ningún alumno con id_alumno 99. Esa es justo la protección que da la clave foránea.

Consultas con relaciones (INNER JOIN)#

Cuando queremos ver a la vez el nombre del alumno y el de su tutor, usamos el superpoder del JOIN. Es como decirle a SQL: «junta estas dos tablas usando el ID que tienen en común».

SQL
SELECT alumnos.nombre AS alumno, tutores.nombre AS tutor, tutores.pago
FROM alumnos INNER JOIN tutores ON tutores.id_alumno = alumnos.id_alumno;

El resultado:

alumnotutorpago
AntonioJuanaEfectivo
MaríaPacoBizum
JuanPepeBizum
ElenaMartaEfectivo

¿Qué está pasando aquí?

ParteQué hace
SELECTEliges qué columnas quieres ver de cada tabla, con tabla.columna
ASLe pone otro nombre a la columna en el resultado (las dos se llamaban nombre)
FROMEliges la tabla principal
INNER JOINEliges la tabla que quieres «pegar»
ONExplicas cuál es el conector: dónde el ID de una coincide con el ID de la otra

Errores frecuentes#

Mensaje o síntomaQué significaCómo se arregla
FOREIGN KEY constraint failedEl id_alumno del tutor no existe en alumnos, o intentas borrar un alumno que todavía tiene tutoresInserta primero el alumno; para borrarlo, borra antes sus tutores
ambiguous column name: nombreLas dos tablas tienen una columna nombre y SQL no sabe cuál quieresIndica la tabla: alumnos.nombre o tutores.nombre
La clave foránea no protege nada: se pueden meter IDs que no existenEn SQLite no se ha ejecutado PRAGMA foreign_keys = ON; en esta sesiónEjecútalo cada vez que abras DBeaver
El JOIN devuelve muchísimas filas repetidasFalta el ON, o el ON compara columnas que no sonUne por la clave: ON tutores.id_alumno = alumnos.id_alumno