CodeGym /Cursos /SQL SELF /Modelando la relación ONE-TO-MANY entre tab...

Modelando la relación ONE-TO-MANY entre tablas

SQL SELF
Nivel 19 , Lección 3
Disponible

Ahora ha llegado el momento de mejorar nuestras skills y crear una de las relaciones más frecuentes en bases de datos relacionales — la relación ONE-TO-MANY.

Imagina una pequeña empresa. Un empleado solo puede trabajar en un departamento, pero en un departamento pueden currar decenas de empleados así. Tenemos dos objetos del mundo real: empleados y departamentos. La relación entre ellos se puede describir como "un departamento puede incluir a muchos empleados", o formalmente "uno a muchos" (ONE-TO-MANY).

Igualito, las relaciones ONE-TO-MANY están por todas partes:

  • un cliente puede hacer muchos pedidos;
  • un autor puede escribir un montón de libros;
  • un profe puede enseñar a varios estudiantes.

En una base de datos relacional, la relación ONE-TO-MANY se implementa usando una clave foránea (FOREIGN KEY). Una de las columnas de la tabla "muchos" (MANY) apunta a la clave primaria de la tabla "uno" (ONE).

Cómo crear una relación ONE-TO-MANY

Vamos a ver el ejemplo clásico: la relación entre clientes y pedidos. Un cliente puede hacer muchos pedidos, pero cada pedido está vinculado solo a un cliente. Vamos a crear dos tablas: customers (clientes) y orders (pedidos).

Tabla customers

Esta es nuestra tabla "uno". Aquí vamos a guardar info sobre los clientes.

CREATE TABLE customers (
    customer_id SERIAL PRIMARY KEY, -- Identificador único del cliente
    name TEXT NOT NULL              -- Nombre del cliente
);

Tabla orders

Esta es la tabla "muchos". Aquí se guardan los pedidos, donde cada pedido tiene una clave foránea customer_id que apunta al customer_id de la tabla customers.

CREATE TABLE orders (
    order_id SERIAL PRIMARY KEY,           -- Identificador único del pedido
    order_date DATE NOT NULL,              -- Fecha del pedido
    customer_id INT REFERENCES customers(customer_id) -- Clave foránea
);

Uso práctico

Insertando datos

Ahora vamos a meter algunos datos en nuestras tablas para comprobar que la relación funciona.

Agregamos clientes a la tabla customers:

INSERT INTO customers (name)
VALUES
    ('Ada Lovelace'),
    ('Grace Hopper'),
    ('Linus Torvalds');

Resultado:

customer_id name
1 Ada Lovelace
2 Grace Hopper
3 Linus Torvalds

Agregamos pedidos a la tabla orders:

INSERT INTO orders (order_date, customer_id)
VALUES
    ('2023-10-01', 1),  -- Pedido de Ada
    ('2023-10-02', 2),  -- Pedido de Grace
    ('2023-10-03', 1);  -- Otro pedido de Ada

Tabla orders:

order_id order_date customer_id
1 2023-10-01 1
2 2023-10-02 2
3 2023-10-03 1

Ojo: cuando añades un pedido tienes que poner sí o sí un customer_id que exista. Si intentas poner un ID que no existe, la base de datos te va a tirar un error. Así se protege la integridad de los datos.

Comprobando la relación

Ahora vamos a ver cómo están conectadas nuestras tablas. Por ejemplo, ¿qué pedidos hizo Ada Lovelace?

SELECT orders.order_id, orders.order_date, customers.name
FROM orders
JOIN customers ON orders.customer_id = customers.customer_id
WHERE customers.name = 'Ada Lovelace';

Resultado:

order_id order_date name
1 2023-10-01 Ada Lovelace
3 2023-10-03 Ada Lovelace

Aquí usamos el comando JOIN para juntar las dos tablas usando la clave foránea. Cómodo, limpio — ¡y sin datos duplicados!

¿Para qué sirve esto?

La relación ONE-TO-MANY es súper común y útil en la vida real. Imagina una tienda online con miles de clientes y millones de pedidos. En vez de duplicar la info del cliente en cada pedido, guardamos los clientes únicos en una tabla y los pedidos en otra. Así ahorramos espacio y la base queda mucho más ordenada.

Además, poder conectar datos te permite hacer consultas potentes para análisis. Por ejemplo, puedes preguntar: "¿Cuántos pedidos hizo cada cliente?" o "¿Qué clientes hicieron pedidos el último mes?".

Dificultades y trampas típicas

Esto es donde la peña que empieza suele tropezar:

Falta de clave foránea. Si te olvidas de poner la clave foránea en la tabla "muchos", la relación solo existe en tu cabeza, pero la base de datos no puede aplicarla de verdad. Eso significa que te arriesgas a tener una base "rota", donde hay pedidos que apuntan a clientes que no existen.

Intentar borrar un registro de la tabla "uno". Por ejemplo, si borras un cliente de customers, sus pedidos en orders se quedan "colgados". Para evitarlo, puedes usar ON DELETE CASCADE, así cuando borres un cliente, se borran automáticamente sus pedidos.

CREATE TABLE orders (
    order_id SERIAL PRIMARY KEY,
    order_date DATE NOT NULL,
    customer_id INT REFERENCES customers(customer_id) ON DELETE CASCADE
);

Ahora, si borras un cliente:

DELETE FROM customers WHERE customer_id = 1;

Todos sus pedidos también se borran. La base queda limpia, como una taza de café recién hecha.

Errores al insertar datos. Si intentas meter un pedido con un customer_id que no existe, te saldrá un error como:

ERROR:  insert or update on table "orders" violates foreign key constraint
Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION