Una relación muchos a muchos resulta más fácil de modelar cuando cada asociación tiene su propio registro. Un estudiante puede inscribirse en varios cursos y cada curso puede tener varios estudiantes. Una tabla de inscripciones registra cada vínculo por separado, en lugar de guardar una lista de identificadores de cursos en la fila del estudiante.

Utiliza el espacio de diagramación de Boardmix para definir esa relación antes de implementarla en la base de datos. Este ejemplo parte de estudiantes y cursos, incorpora una tabla intermedia y resuelve un detalle que suele pasarse por alto: un mismo curso puede impartirse más de una vez.

Los registros de estudiantes y cursos se conectan mediante una tabla de inscripciones, en lugar de un vínculo directo muchos a muchos.
El registro de inscripción da un lugar propio a cada asociación entre estudiante y curso.

Define qué representa una fila de inscripción

Supongamos que un centro ofrece los cursos Fundamentos de datos y Planificación visual. El estudiante S01 cursa ambos y el estudiante S02 cursa Fundamentos de datos. La relación conceptual es muchos a muchos: cada estudiante puede estar vinculado a varios cursos y cada curso, a varios estudiantes.

En un diseño relacional, una tabla intermedia representa esas asociaciones. La documentación de Microsoft sobre relaciones muchos a muchos explica este patrón: cada fila de la tabla de unión contiene claves foráneas que apuntan a los registros de ambos extremos. Los vínculos entre las tablas resultantes son uno a muchos, aunque la relación de negocio siga siendo muchos a muchos.

student_idcourse_idSignificado
S01C10El estudiante S01 está inscrito en Fundamentos de datos.
S01C20El mismo estudiante también está inscrito en Planificación visual.
S02C10Otro estudiante está inscrito en Fundamentos de datos.

Estas tres filas no duplican los registros de los estudiantes. Sus datos permanecen en Student, los del curso en Course y la asociación en Enrollment. Corregir una errata en el nombre de un estudiante no debería exigir modificar todas sus inscripciones.

Coloca Enrollment entre Student y Course. Para este primer modelo simplificado, define las relaciones así:

  • Un estudiante puede tener cero o muchas filas de inscripción.
  • Cada inscripción corresponde a un único estudiante.
  • Un curso puede tener cero o muchas filas de inscripción.
  • Cada inscripción corresponde a un único curso.

El cero es importante. Puede existir un estudiante nuevo que aún no se haya inscrito, o un curso recién creado sin participantes. En cambio, una inscripción necesita ambos extremos: en este modelo sus dos claves foráneas son obligatorias.

No conserves otro conector directo entre Student y Course en un diagrama de tablas físicas, salvo que tenga un significado distinto y explícito. De lo contrario, parecerá que el diseño exige tanto la tabla intermedia como una implementación directa adicional. La vista conceptual puede mostrar la asociación muchos a muchos; la vista de tablas explica cómo se representa.

Guarda en Enrollment los datos propios de la asociación

Pregúntate si un valor describe al estudiante, al curso o la participación de ese estudiante en ese curso. La respuesta ayuda a decidir dónde debe estar cada campo.

CampoTablaMotivo
student_nameStudentEl nombre no cambia con cada inscripción.
course_titleCourseEl título describe el curso, no a un participante.
enrolled_atEnrollmentRegistra cuándo comenzó la asociación.
enrollment_statusEnrollmentUn estudiante puede darse de baja de un curso y seguir inscrito en otro.
completion_resultEnrollmentEl resultado corresponde a esa participación, no a todas las personas del curso.

Una tabla intermedia puede contener más que dos identificadores. Aquí Enrollment, «inscripción», es un nombre útil porque la asociación tiene estado e historial. También podría llamarse StudentCourse, pero el nombre no debería ocultar qué representa el registro.

Define qué ocurre a lo largo de su ciclo de vida. Cuando alguien se da de baja, decide si se actualiza el estado o se registran eventos por separado. Borrar la fila eliminaría el historial de la asociación. La conservación de datos depende de la aplicación; el diagrama debe expresar el modelo acordado, no dar por hecho que cada baja implica borrar un registro.

Decide por separado la clave y la regla de unicidad

Si el modelo permite una sola inscripción por pareja estudiante–curso, (student_id, course_id) puede ser la clave primaria compuesta. Es la combinación la que identifica la fila: ninguna de las dos columnas tiene que ser única por sí sola.

Otra opción es una clave primaria independiente, enrollment_id, junto con una restricción de unicidad sobre la pareja estudiante–curso. El identificador adicional no impide por sí mismo insertar dos veces a S01 en C10. Si esas asociaciones duplicadas no son válidas, expresa la regla.

La documentación de restricciones de PostgreSQL diferencia claves primarias, restricciones de unicidad y claves foráneas. En este ejemplo, las claves foráneas exigen que existan el estudiante y el curso referenciados; la unicidad evita repetir la asociación; la clave primaria identifica una fila. Son responsabilidades relacionadas, no etiquetas intercambiables.

El diagrama documenta las reglas y la base de datos debe aplicarlas. Una línea marcada con «1» o una nota que diga «único» no impide escrituras inválidas si la implementación no incorpora esa restricción.

Resuelve el caso de un curso que vuelve a impartirse

La pareja inicial limita el modelo cuando Fundamentos de datos se imparte en primavera y en otoño. Si S01 puede repetir el curso, (student_id, course_id) ya no expresa la unicidad deseada. Eliminar la restricción por completo permitiría también inscripciones duplicadas por error en la misma edición.

Introduce CourseOffering: una edición programada de un curso. El curso C10 puede tener la edición O101 en primavera y O102 en otoño. Cada edición pertenece a un curso y un curso puede tener varias ediciones. Ahora Enrollment conecta Student con CourseOffering.

La pareja pasa a ser (student_id, offering_id). S01–O101 y S01–O102 son inscripciones distintas y ambas pueden ser válidas. Una segunda S01–O101 sigue siendo un duplicado si la regla permite una sola inscripción por estudiante y edición.

Guarda los datos propios de cada edición, como la fecha de inicio, en CourseOffering y no en Course. El título describe el curso reutilizable; la edición describe cuándo se imparte. Si el servicio permite varios intentos en una misma edición, modela ese concepto adicional en lugar de debilitar continuamente la clave de inscripción.

Revisa el modelo en Boardmix con registros concretos

Dibuja en Boardmix cuatro entidades: Student, Enrollment, CourseOffering y Course. Coloca la inscripción entre el estudiante y la edición, y conecta la edición con el curso. Marca las claves primarias y foráneas junto a los campos y añade una nota independiente sobre la pareja única estudiante–edición.

Debajo, coloca tres tarjetas de ejemplo: S01–O101, S01–O102 y otra S01–O101. Señala las dos primeras como asociaciones distintas y la pareja repetida como duplicado según la regla elegida. Así resulta más fácil discutir el comportamiento del modelo que mirando solo una lista de campos.

Un modelo ER en Boardmix conecta Student, Enrollment, CourseOffering y Course, con una nota sobre la unicidad de la pareja estudiante–edición.
CourseOffering permite repetir el curso sin admitir inscripciones duplicadas en una misma edición.

Abre una pizarra de Boardmix y comprueba la relación con varios registros de tu propio caso. ¿Puede existir un registro principal sin asociaciones? ¿Puede repetirse la misma pareja? ¿Dónde se guardan los valores propios de la asociación?

Las respuestas pueden cambiar el diagrama. Para este centro de formación, el hallazgo importante no es solo que haga falta otra tabla: cada inscripción une a una persona con una edición concreta, no con el curso abstracto para siempre.