CodeGym /Cursos /SQL SELF /Modelando relaciones entre tablas para la normalización

Modelando relaciones entre tablas para la normalización

SQL SELF
Nivel 26 , Lección 0
Disponible

Hoy vamos a profundizar en un tema súper importante: cómo modelar relaciones entre tablas. La normalización no es solo sobre datos atómicos y eliminar redundancias, sino también sobre crear relaciones correctas entre tablas.

Si una base de datos es un sistema organizado para guardar información, entonces las relaciones entre tablas son como puentes lógicos que muestran cómo los datos interactúan entre sí. Imagínate una biblioteca donde la info sobre los libros se guarda aparte de la info sobre los autores, pero cada libro "conoce" a su autor a través de una relación especial. O piensa en una tienda online: los datos de los productos existen independientemente de la info de los clientes, pero cuando alguien hace un pedido, el sistema conecta a un cliente concreto con productos concretos a través de la tabla de pedidos.

En una clínica médica, los pacientes están conectados con sus historiales médicos, los médicos con el horario de citas, y los medicamentos con las prescripciones. Estas relaciones ayudan al sistema a entender qué info pertenece a qué, sin duplicar datos innecesariamente.

Los tipos principales de estas relaciones funcionan como relaciones en la vida real: un pasaporte pertenece solo a una persona (uno a uno), un profe puede dar varias asignaturas (uno a muchos), y los estudiantes pueden apuntarse a diferentes materias, mientras que cada materia la cursan diferentes estudiantes (muchos a muchos).

Uno a uno (1:1)

Esta es una relación donde un registro en la tabla "A" corresponde exactamente a un registro en la tabla "B". Por ejemplo, tenemos las tablas "Empleados" y "Datos de pasaporte". Un empleado solo puede tener un pasaporte, y cada pasaporte pertenece a un solo empleado.

Ejemplo:

Empleados

id nombre puesto
1 Otto Lin manager

Datos de pasaporte

id empleado_id número de pasaporte
1 1 123456789

Aquí la relación se hace a través de la clave foránea empleado_id, que apunta al id en la tabla "Empleados".

Uno a muchos (1:N)

Este es el tipo de relación más común. Aquí cada registro de la tabla "A" puede estar relacionado con varios registros en la tabla "B", pero cada registro de la tabla "B" solo está relacionado con un registro de la tabla "A". Por ejemplo, tenemos las tablas "Profesores" y "Cursos". Un profe puede dar varios cursos.

Ejemplo:

Profesores

id nombre
1 Anna Song
2 Aleks Min

Cursos

id nombre del curso profesor_id
1 Fundamentos de SQL 1
2 Administración de BD 1
3 Programación en Python 2

La relación se crea a través de la clave foránea profesor_id en la tabla "Cursos".

Muchos a muchos (M:N)

Cuando tienes un montón de todo, mola pero es complicado. Aquí cada registro en la tabla "A" puede estar relacionado con varios registros de la tabla "B", y viceversa. Por ejemplo, los estudiantes pueden apuntarse a varios cursos, y cada curso puede tener varios estudiantes.

Ejemplo:

Estudiantes

id nombre
1 Otto Lin
2 Maria Chi

Cursos

id nombre del curso
1 Fundamentos de SQL
2 Administración de BD

Para conectar todo esto necesitamos una tabla intermedia que guarde las relaciones entre estudiantes y cursos:

Inscripciones

id estudiante_id curso_id
1 1 1
2 1 2
3 2 1

Modelando relaciones con claves foráneas

Una clave foránea es una columna (o conjunto de columnas) que apunta a la columna clave primaria en otra tabla. Es la base para construir relaciones entre tablas.

Ejemplo de clave foránea:

CREATE TABLE Cursos (
    id SERIAL PRIMARY KEY,
    nombre VARCHAR(255)
);

CREATE TABLE Inscripciones (
    id SERIAL PRIMARY KEY,
    estudiante_id INT,
    curso_id INT,
    FOREIGN KEY (curso_id) REFERENCES Cursos(id)
);

¿Cómo evitar errores al diseñar claves foráneas? Lo primero es comprobar que los tipos de datos entre las columnas de la clave foránea y la clave primaria coincidan — si no, la base de datos no te dejará crear la relación. Y también es importante pensar de antemano qué debe pasar cuando se borren registros. Por ejemplo, si borras una fila de la tabla padre, ¿qué pasa con los registros hijos? Una opción muy usada es poner ON DELETE CASCADE, para que los datos relacionados se borren automáticamente junto con el registro principal. Así mantienes el orden y evitas referencias "colgantes".

Implementando la relación "Muchos a muchos"

Pongamos un ejemplo: tenemos estudiantes y cursos. Un estudiante puede estar inscrito en varios cursos, y un curso puede tener varios estudiantes inscritos. Para la relación M:N creamos tres tablas: Estudiantes, Cursos e Inscripciones.

CREATE TABLE Estudiantes (
    id SERIAL PRIMARY KEY,
    nombre VARCHAR(255)
);

CREATE TABLE Cursos (
    id SERIAL PRIMARY KEY,
    nombre VARCHAR(255)
);

CREATE TABLE Inscripciones (
    id SERIAL PRIMARY KEY,
    estudiante_id INT,
    curso_id INT,
    FOREIGN KEY (estudiante_id) REFERENCES Estudiantes(id),
    FOREIGN KEY (curso_id) REFERENCES Cursos(id)
);

Ahora podemos añadir registros a la tabla Inscripciones para conectar estudiantes y cursos.

Ejercicio práctico

Crea la estructura de base de datos para un sistema de gestión de cursos. Debes tener las tablas Estudiantes, Cursos e Inscripciones. Implementa todas las relaciones entre las tablas. Luego mete algunos datos de ejemplo de estudiantes, cursos y sus inscripciones. Vamos a ver cómo se hace.

  1. Creamos las tablas:
CREATE TABLE Estudiantes (
    id SERIAL PRIMARY KEY,
    nombre VARCHAR(255)
);

CREATE TABLE Cursos (
    id SERIAL PRIMARY KEY,
    nombre VARCHAR(255)
);

CREATE TABLE Inscripciones (
    id SERIAL PRIMARY KEY,
    estudiante_id INT,
    curso_id INT,
    FOREIGN KEY (estudiante_id) REFERENCES Estudiantes(id),
    FOREIGN KEY (curso_id) REFERENCES Cursos(id)
);
  1. Insertamos datos:
INSERT INTO Estudiantes (nombre) VALUES ('Otto Lin'), ('Maria Chi');
INSERT INTO Cursos (nombre) VALUES ('Fundamentos de SQL'), ('Administración de BD');
INSERT INTO Inscripciones (estudiante_id, curso_id) VALUES (1, 1), (1, 2), (2, 1);
  1. Comprobamos los datos:
SELECT
    Estudiantes.nombre AS estudiante, 
    Cursos.nombre AS curso
FROM Inscripciones
JOIN Estudiantes ON Inscripciones.estudiante_id = Estudiantes.id
JOIN Cursos ON Inscripciones.curso_id = Cursos.id;

Resultado:

estudiante curso
Otto Lin Fundamentos de SQL
Otto Lin Administración de BD
Maria Chi Fundamentos de SQL

Dificultades y particularidades al modelar relaciones

Cuando modelas relaciones entre tablas, pueden surgir problemas como:

  • Errores al borrar datos (por ejemplo, tienes registros en la tabla hija que dependen de un registro en la tabla padre).
  • Rendimiento de las consultas cuando hay muchos datos. Las relaciones M:N son especialmente "tragonas", porque requieren joins extra.

Para solucionar estos problemas ayudan:

  • Usar índices en las claves foráneas
  • Una estructura de base de datos bien pensada.
  • Equilibrio entre normalización y rendimiento.

Hemos visto cómo modelar relaciones entre tablas a un nivel muy básico y lo hemos puesto en práctica creando la estructura de una base de datos para un sistema de gestión de cursos. Me gustaría, claro, ver un ejemplo grande, pero no se me ocurre cómo hacerlo. Un ejemplo grande se vuelve complicado y aburrido. Y no sirve de mucho. Intentaré volver a este tema cerca del final del curso.

2
Tarea
SQL SELF, nivel 26, lección 0
Bloqueada
Creación de una relación "muchos a muchos"
Creación de una relación "muchos a muchos"
Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION