CodeGym /Cursos /SQL SELF /Comprobación de integridad de datos

Comprobación de integridad de datos

SQL SELF
Nivel 20 , Lección 2
Disponible

Hoy vamos a empezar a ver cómo las claves foráneas nos ayudan a vigilar la integridad de los datos y a evitar problemas típicos relacionados con datos inconsistentes o incorrectos.

Primero, vamos a aclarar qué queremos decir con "integridad de datos". Imagina que tienes una tabla de pedidos (orders) y una tabla de clientes (customers). Si un pedido tiene un cliente que no existe en la tabla de clientes, eso es una violación de la integridad. Es importante que todos los datos en tablas relacionadas estén en coherencia lógica.

La integridad de datos significa:

  • Nada de referencias "vacías": si hacemos referencia a algo en otra tabla, ese "algo" siempre existe.
  • Resistencia a errores de modificación: si borramos de una tabla un valor al que hacen referencia otros registros, la base de datos debe avisarnos o manejar la situación correctamente.

Justo para esto se usan las claves foráneas en PostgreSQL.

¿Cómo aseguran las claves foráneas la integridad de los datos?

Cuando creas una clave foránea en una tabla, PostgreSQL automáticamente comprueba:

  1. Existencia de datos en la tabla padre. Antes de insertar o actualizar un registro, PostgreSQL comprueba si la clave foránea indicada existe en la tabla relacionada.
  2. Eliminación o modificación de datos. Antes de borrar o actualizar un registro en la tabla padre, PostgreSQL comprueba si hay registros en la tabla hija que hagan referencia a él.

Las claves foráneas son como un "guardián". No dejan pasar datos incorrectos y garantizan que las tablas interactúen según las reglas establecidas.

Ejemplo: integridad de datos en tablas de estudiantes y cursos

Supón que tenemos dos tablas — students y courses. Cada estudiante puede apuntarse a varios cursos. Para reflejar esta relación usamos la tabla enrollments. Veamos qué pasa si alguien intenta inscribir a un estudiante en un curso que no existe.

Paso 1. Creamos tres tablas relacionadas:

CREATE TABLE students (
    student_id SERIAL PRIMARY KEY,
    name TEXT NOT NULL
);

CREATE TABLE courses (
    course_id SERIAL PRIMARY KEY,
    title TEXT NOT NULL
);

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

Aquí:

  • En la tabla enrollments hemos especificado explícitamente las claves foráneas student_id y course_id, que hacen referencia a las claves primarias de las tablas students y courses.

Comprobaciones típicas de integridad de datos

  1. Comprobación al insertar datos

Si intentamos insertar en la tabla enrollments un registro con student_id o course_id que no existen, saldrá un error.

Ejemplo:

INSERT INTO enrollments (student_id, course_id)
VALUES (999, 1); -- ¡Error! El estudiante con ID 999 no existe.

Mensaje de error:

ERROR:  insert or update on table "enrollments" violates foreign key constraint "enrollments_student_id_fkey"
DETAIL:  Key (student_id)=(999) is not present in table "students".
  1. Comprobación al eliminar datos

Vamos a intentar borrar un registro de la tabla padre al que se hace referencia.

Ejemplo:

INSERT INTO students (name) VALUES ('Alicia');
INSERT INTO courses (title) VALUES ('Matemáticas');

INSERT INTO enrollments (student_id, course_id)
VALUES (1, 1); -- Inserción exitosa

DELETE FROM students WHERE student_id = 1; -- ¡Error, porque el estudiante sigue inscrito en un curso!

Mensaje de error:

ERROR:  update or delete on table "students" violates foreign key constraint "enrollments_student_id_fkey" on table "enrollments"
DETAIL:  Key (student_id)=(1) is still referenced from table "enrollments".

Para eliminar registros correctamente en estos casos usamos estrategias como CASCADE, SET NULL o RESTRICT, que ya comentamos antes.

Ejemplos de uso de claves foráneas para comprobar la integridad

Ejemplo 1: Protección automática contra datos incorrectos

Con claves foráneas, PostgreSQL automáticamente impide insertar datos "inexistentes":

-- Intentamos añadir estudiantes inexistentes a un curso:
INSERT INTO enrollments (student_id, course_id)
VALUES (42, 1); -- ¡Error! El estudiante con ID 42 no existe.

Esto garantiza que un estudiante no podrá apuntarse a un curso si no existe en la tabla students.

Ejemplo 2: Eliminación de datos con ON DELETE CASCADE

Si la clave foránea está configurada con borrado en cascada ON DELETE CASCADE, al eliminar un registro en la tabla padre los datos relacionados en la tabla hija también se borrarán.

ALTER TABLE enrollments DROP CONSTRAINT enrollments_student_id_fkey; -- Quitamos la clave foránea antigua

ALTER TABLE enrollments
ADD CONSTRAINT enrollments_student_id_fkey FOREIGN KEY (student_id)
REFERENCES students(student_id) ON DELETE CASCADE;

DELETE FROM students WHERE student_id = 1; -- Ahora también se borran los registros de enrollments

Ejemplo 3: Manejo de cambios con ON UPDATE

Si la clave foránea está configurada con ON UPDATE CASCADE, al cambiar el valor en la tabla padre PostgreSQL actualizará automáticamente los datos en la tabla hija.

-- Configuramos la clave foránea para que los cambios en la clave padre se apliquen automáticamente en la tabla hija:
ALTER TABLE enrollments DROP CONSTRAINT enrollments_student_id_fkey;

ALTER TABLE enrollments
ADD CONSTRAINT enrollments_student_id_fkey FOREIGN KEY (student_id)
REFERENCES students(student_id) ON UPDATE CASCADE;

-- Cambiamos el identificador del estudiante:
UPDATE students SET student_id = 10 WHERE student_id = 1;

-- Ahora en la tabla enrollments student_id también se actualiza a 10.

Testeo de la integridad de datos

Siempre es útil probar cómo se comportan las claves foráneas en diferentes escenarios:

  1. Intenta insertar datos con student_id o course_id incorrectos.
  2. Borra datos de students y comprueba qué pasa en la tabla enrollments.
  3. Cambia datos en la tabla students y asegúrate de que los registros relacionados se actualizan.

Detalles a tener en cuenta al trabajar con claves foráneas

A veces hay situaciones que pueden despistar:

  • Falta de índice. Si la tabla padre (students, por ejemplo) no tiene el campo referenciado indexado, PostgreSQL puede "intentar" funcionar más lento. Por eso es importante que la clave primaria en la tabla padre siempre sea un índice.
  • Referencias cíclicas. Si dos tablas se referencian entre sí, puede ser complicado insertar datos. En estos casos hay que diseñar con más cuidado.
  • Eliminación de todos los registros. Si necesitas borrar todos los registros con borrado en cascada, hay que tener en cuenta la naturaleza de los datos en la tabla hija para evitar comportamientos inesperados.

Para evitar estos problemas, es importante diseñar bien las tablas y probar las reglas de relación antes de usarlas en una base de datos real.

Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION