Vamos a ponernos un poco técnicos. Vamos a repasar paso a paso cómo crear la estructura MANY-TO-MANY. ¿Listo?
La relación MANY-TO-MANY entre estudiantes y cursos no se puede representar directamente en una sola tabla. Un estudiante puede estar inscrito en varios cursos, y un curso puede tener varios estudiantes a la vez.
Para solucionar esto, creamos una tabla intermedia enrollments, que va a guardar la info de las inscripciones, o sea, qué pareja estudiante-curso existe. Esto no solo nos ayuda a mantener la integridad de los datos, sino que también nos permite ampliar la funcionalidad fácilmente, por ejemplo, añadiendo la fecha de inscripción.
¿Cómo se ve la tabla enrollments?
Ya sabes que la tabla enrollments será el nodo central entre las tablas students y courses. Así es su estructura:
CREATE TABLE enrollments (
enrollment_id SERIAL PRIMARY KEY, -- ID único del registro
student_id INT REFERENCES students(student_id), -- Clave foránea a la tabla students
course_id INT REFERENCES courses(course_id), -- Clave foránea a la tabla courses
enrollment_date DATE DEFAULT CURRENT_DATE -- Cuándo el estudiante fue inscrito al curso
);
Vamos a ver cada línea:
enrollment_id: Es el identificador único de cada registro. Cada estudiante inscrito en un curso debe tener su propio ID.student_id: Indica qué estudiante está inscrito. Es una clave foránea que apunta a la tablastudents(columnastudent_id).course_id: Indica a qué curso está inscrito el estudiante. Esta columna está relacionada con la tablacourses(columnacourse_id).enrollment_date: Un extra útil que muestra la fecha de inscripción. UsamosDEFAULT CURRENT_DATEpara que se ponga la fecha actual automáticamente al crear el registro.
Creando las tablas students y courses
Antes de seguir, asegúrate de que ya tienes las tablas students y courses:
CREATE TABLE students (
student_id SERIAL PRIMARY KEY, -- Identificador único del estudiante
name TEXT NOT NULL, -- Nombre del estudiante
email TEXT NOT NULL UNIQUE -- Email del estudiante, para evitar duplicados
);
CREATE TABLE courses (
course_id SERIAL PRIMARY KEY, -- Identificador único del curso
title TEXT NOT NULL, -- Nombre del curso
description TEXT, -- Descripción del curso
start_date DATE -- Fecha de inicio del curso
);
Fíjate que aquí hemos añadido detalles útiles, como emails únicos para los estudiantes y una descripción del curso en la tabla courses.
Conectando todo junto
Ahora que tenemos las tablas listas, vamos a crear la tabla enrollments:
CREATE TABLE enrollments (
enrollment_id SERIAL PRIMARY KEY, -- ID único de inscripción
student_id INT NOT NULL REFERENCES students(student_id), -- Clave foránea
course_id INT NOT NULL REFERENCES courses(course_id), -- Clave foránea
enrollment_date DATE DEFAULT CURRENT_DATE -- Fecha de inscripción
);
Insertando datos en las tablas
Vale, las tablas ya están, pero están aburridas sin datos. Vamos a meter algunos estudiantes, cursos y sus inscripciones:
Insertando estudiantes:
INSERT INTO students (name, email)
VALUES
('Alex Lin', 'alex.lin@example.com'),
('Maria Chi', 'maria.chi@example.com'),
('Otto Song', 'otto.song@example.com');
Insertando cursos:
INSERT INTO courses (title, description, start_date)
VALUES
('Fundamentos de programación', 'Curso para programadores principiantes.', '2023-11-01'),
('Bases de datos', 'Aprendemos SQL y bases de datos relacionales.', '2023-11-15'),
('Desarrollo web', 'Creación de sitios y aplicaciones web.', '2023-12-01');
Insertando registros de inscripciones:
INSERT INTO enrollments (student_id, course_id)
VALUES
(1, 1), -- Alex Lin en "Fundamentos de programación"
(1, 2), -- Alex Lin en "Bases de datos"
(2, 2), -- Maria Chi en "Bases de datos"
(3, 3); -- Otto Song en "Desarrollo web"
Aquí student_id y course_id coinciden con los identificadores en las tablas correspondientes.
Comprobando las relaciones con consultas
Obteniendo todas las inscripciones:
SELECT e.enrollment_id, s.name AS student_name, c.title AS course_title, e.enrollment_date
FROM enrollments e
JOIN students s ON e.student_id = s.student_id
JOIN courses c ON e.course_id = c.course_id;
Resultado:
| enrollment_id | student_name | course_title | enrollment_date |
|---|---|---|---|
| 1 | Alex Lin | Fundamentos de programación | 2023-11-01 |
| 2 | Alex Lin | Bases de datos | 2023-11-01 |
| 3 | Maria Chi | Bases de datos | 2023-11-01 |
| 4 | Otto Song | Desarrollo web | 2023-11-01 |
Ejercicio para practicar por tu cuenta
Intenta añadir más estudiantes y cursos, y luego inscríbelos en la tabla enrollments. Por ejemplo, añade el curso "Aprendizaje automático" y apunta ahí a 1-2 estudiantes. Usa la consulta de arriba para comprobar el resultado.
Errores típicos que pueden pasar
Al trabajar con claves foráneas y tablas intermedias hay varias trampas en las que es fácil caer:
Falta de registro en la tabla padre: Si intentas añadir un registro en
enrollmentscon unstudent_idocourse_idque no existen en las tablasstudentsocourses, te va a saltar un error. La clave foránea lo controla a tope.Violación de integridad al borrar: Si borras un estudiante o curso que ya está usado en la tabla
enrollments, y no tienesON DELETE CASCADEconfigurado, te va a dar error.Duplicar registros: Asegúrate de no meter a un estudiante en el mismo curso más de una vez, a menos que tu lógica de negocio lo permita.
Ahora ya tienes un modelo funcional para representar la relación MANY-TO-MANY entre estudiantes y cursos en PostgreSQL. Esta estructura se usa un montón en apps reales, como sistemas de gestión de aprendizaje, CRM y muchos más. ¡Vamos a por la siguiente lección!
GO TO FULL VERSION