CodeGym /Cursos /SQL SELF /Errores típicos al trabajar con claves foráneas

Errores típicos al trabajar con claves foráneas

SQL SELF
Nivel 20 , Lección 4
Disponible

Todos somos humanos y todos nos equivocamos. Especialmente cuando se trata de los detalles de trabajar con claves foráneas en bases de datos. En esta clase te voy a ayudar a evitar los errores y trampas más comunes. Una buena base de datos es como un puente sólido: si te equivocas en algún sitio, toda la estructura puede venirse abajo. Vamos a ver cómo mantener tus "puentes de datos" en orden.

Error 1: Falta de índice en la clave foránea

Cuando añades una clave foránea, le dices a la base de datos: "Conecta estas tablas entre sí". Pero si no creas un índice explícitamente en esa clave foránea, cuando ejecutes consultas complejas sobre tablas relacionadas, el rendimiento puede caer en picado.

Ejemplo del problema:

CREATE TABLE customers (
    customer_id SERIAL PRIMARY KEY,
    name TEXT NOT NULL
);

CREATE TABLE orders (
    order_id SERIAL PRIMARY KEY,
    customer_id INT REFERENCES customers(customer_id)
);

Parece que todo está bien: las tablas están creadas y la clave foránea existe. Pero si ejecutas una consulta como:

SELECT * 
FROM orders 
JOIN customers ON orders.customer_id = customers.customer_id;

para grandes volúmenes de datos, esa consulta puede ir lentísima porque PostgreSQL no encontrará un índice adecuado para optimizar el join.

Cómo evitarlo:

Crea siempre un índice para la columna a la que apunta la clave foránea. A veces PostgreSQL lo hace automáticamente, pero mejor asegurarse.

CREATE INDEX idx_customer_id ON orders(customer_id);

Error 2: Secuencia incorrecta al crear tablas

Imagina que estás creando tablas pero intentas añadir una clave foránea antes de que exista la tabla a la que apuntas. PostgreSQL se va a quejar y te va a lanzar errores porque no encuentra la tabla de destino.

Ejemplo del problema:

CREATE TABLE orders (
    order_id SERIAL PRIMARY KEY,
    customer_id INT REFERENCES customers(customer_id)
);

-- Uy, ¿dónde está la tabla customers?..
CREATE TABLE customers (
    customer_id SERIAL PRIMARY KEY,
    name TEXT NOT NULL
);

Resultado: PostgreSQL lanza un error porque la tabla customers aún no existe.

Cómo evitarlo:

Crea primero las tablas a las que vas a referenciar y luego añade las claves foráneas. El orden importa. Así es como se hace bien:

CREATE TABLE customers (
    customer_id SERIAL PRIMARY KEY,
    name TEXT NOT NULL
);

CREATE TABLE orders (
    order_id SERIAL PRIMARY KEY,
    customer_id INT REFERENCES customers(customer_id)
);

Error 3: Errores de sintaxis en operaciones en cascada

Las claves foráneas suelen ir acompañadas de opciones como ON DELETE CASCADE o ON UPDATE RESTRICT. Pero si te olvidas de escribir bien estas reglas, tu base de datos puede comportarse de forma inesperada. Por ejemplo, borrar datos en una tabla no afectará a las tablas dependientes.

Ejemplo del problema:

CREATE TABLE orders (
    order_id SERIAL PRIMARY KEY,
    customer_id INT REFERENCES customers(customer_id) ON DELETE CASCADEE
);

El ojo atento verá el error de tipeo — la palabra CASCADEE está mal escrita. PostgreSQL no te va a dejar pasar ese error.

Cómo evitarlo:

Escribir bien es media batalla ganada. Si tienes dudas, consulta siempre la documentación oficial de PostgreSQL.

Error 4: Violación de la integridad de los datos

La integridad de los datos es sagrada en cualquier base de datos, y las claves foráneas ayudan a mantenerla. Pero a veces se dan casos en los que te olvidas de poner la clave foránea y todo se desmadra.

Ejemplo del problema:

CREATE TABLE customers (
    customer_id SERIAL PRIMARY KEY,
    name TEXT NOT NULL
);

CREATE TABLE orders (
    order_id SERIAL PRIMARY KEY,
    customer_id INT
);

-- Insertamos datos
INSERT INTO orders (customer_id) VALUES (999);

Aquí hemos añadido un pedido para un cliente que no existe. Eso rompe la integridad de los datos y ese pedido queda "colgado".

Cómo evitarlo:

Usa siempre claves foráneas para evitar que una tabla apunte a registros inexistentes. Así está bien hecho:

CREATE TABLE orders (
    order_id SERIAL PRIMARY KEY,
    customer_id INT REFERENCES customers(customer_id)
);

Ahora, si intentas meter un registro "colgado", te dará error.

Error 5: Suprimir errores de claves foráneas

A veces los desarrolladores intentan meter datos incompatibles a la fuerza usando INSERT ... ON CONFLICT. Parece buena idea, pero con claves foráneas puede tener consecuencias raras.

Ejemplo del problema:

INSERT INTO orders (order_id, customer_id)
VALUES (1, 999)
ON CONFLICT DO NOTHING;

Resultado: los datos no se insertan, pero la base de datos no te dice por qué. Pierdes el control de la situación.

Cómo evitarlo:

Si usas ON CONFLICT, revisa los datos antes. Por ejemplo:

INSERT INTO orders (order_id, customer_id)
SELECT 1, 999
WHERE EXISTS (
    SELECT 1 FROM customers WHERE customer_id = 999
);

Error 6: Borrar registros dependientes sin ON DELETE

Si borras un registro de una tabla referenciada por una clave foránea pero no usas ON DELETE CASCADE, los registros dependientes se quedan en la base, rompiendo el sentido de las relaciones.

Ejemplo del problema:

DELETE FROM customers WHERE customer_id = 1;
-- Los registros en orders con customer_id = 1 siguen ahí.

Cómo evitarlo:

Añade la directiva ON DELETE CASCADE para que los registros relacionados se borren automáticamente:

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

Ahora, cuando borres un cliente, sus pedidos también desaparecerán.

Error 7: Problemas con relaciones MANY-TO-MANY

Al trabajar con relaciones MANY-TO-MANY a veces se olvidan de añadir una clave primaria compuesta o un índice en la tabla intermedia.

Ejemplo del problema:

CREATE TABLE enrollments (
    student_id INT REFERENCES students(student_id),
    course_id INT REFERENCES courses(course_id)
);

-- ¡Uy! Nos olvidamos del PRIMARY KEY.

Cómo evitarlo:

Añade una clave primaria compuesta o un índice único:

CREATE TABLE enrollments (
    student_id INT REFERENCES students(student_id),
    course_id INT REFERENCES courses(course_id),
    PRIMARY KEY (student_id, course_id)
);

Error 8: Referencias cíclicas

Las referencias cíclicas aparecen cuando dos tablas se referencian mutuamente como claves foráneas. Esto crea un círculo vicioso y da problemas al insertar datos.

Ejemplo del problema:

CREATE TABLE table_a (
    id SERIAL PRIMARY KEY,
    table_b_id INT REFERENCES table_b(id)
);

CREATE TABLE table_b (
    id SERIAL PRIMARY KEY,
    table_a_id INT REFERENCES table_a(id)
);

Cómo evitarlo:

Usa DEFERRABLE INITIALLY DEFERRED para que PostgreSQL pueda comprobar la integridad de los datos al final de la transacción:

CREATE TABLE table_a (
    id SERIAL PRIMARY KEY,
    table_b_id INT REFERENCES table_b(id) DEFERRABLE INITIALLY DEFERRED
);

Los errores con claves foráneas no solo ralentizan el desarrollo, sino que pueden causar problemas serios con los datos. Usa esta lista como chuleta para evitar los típicos "tropiezos". Recuerda: la clave foránea es tu aliada, no tu enemiga. Lo importante es usarla bien, y así tu base de datos será la base sólida de un proyecto a largo plazo.

1
Cuestionario/control
Comprobación de integridad de datos, nivel 20, lección 4
No disponible
Comprobación de integridad de datos
Comprobación de integridad de datos
Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION