Bienvenida
En el módulo anterior aprendiste a crear una tabla, insertar registros y consultar sus columnas. Esa primera tabla permitió organizar información, pero los sistemas reales rara vez pueden representarse correctamente con una sola tabla.
Una clínica necesita pacientes, médicos, especialidades, consultorios y citas. Si toda esa información se guarda en una tabla enorme, los nombres y teléfonos se repetirán, aparecerán contradicciones y cada corrección será más difícil.
En este módulo aprenderás a pensar antes de crear las tablas. Analizarás necesidades, identificarás entidades, definirás relaciones y establecerás reglas que la propia base de datos deberá proteger.
Principio del módulo: una buena base de datos no depende de que todas las personas recuerden las reglas. La estructura debe impedir que los datos lleguen a estados inválidos.
Objetivos de aprendizaje
Al completar el módulo serás capaz de:
- Convertir una situación real en requisitos de información.
- Distinguir entidades, atributos y reglas de negocio.
- Elegir claves primarias adecuadas.
- Diferenciar claves naturales, sustitutas, simples y compuestas.
- Crear claves foráneas que protejan relaciones entre tablas.
- Identificar relaciones uno a uno, uno a muchos y muchos a muchos.
- Representar cardinalidad y opcionalidad en un diagrama entidad-relación.
- Resolver relaciones muchos a muchos mediante tablas intermedias.
- Aplicar
PRIMARY KEY,FOREIGN KEY,NOT NULL,UNIQUE,CHECKyDEFAULT. - Activar y comprobar la integridad referencial de SQLite.
- Elegir conscientemente entre
RESTRICT,CASCADEySET NULL. - Detectar redundancia y anomalías en diseños deficientes.
- Aplicar primera, segunda y tercera forma normal en casos prácticos.
- Realizar cambios básicos del esquema mediante
ALTER TABLE. - Eliminar tablas de práctica mediante un orden seguro.
- Documentar un modelo mediante diagrama, modelo relacional y diccionario de datos.
- Reconocer diferencias importantes entre SQLite y otros motores.
Producto que construirás
El proyecto principal será la base de datos de una clínica:
clinica.db
├── especialidades
├── medicos
├── medico_especialidad
├── pacientes
├── consultorios
└── citasLas tablas estarán conectadas mediante claves:
especialidades ──< medico_especialidad >── medicos
│
pacientes ───────────────────────────────< citas >── consultoriosEl proyecto no incluirá una aplicación ni una interfaz gráfica. El objetivo es construir una estructura relacional correcta, comprobar sus reglas y documentar las decisiones.
Ruta de trabajo y distribución del tiempo
| Actividad | Tiempo aproximado |
|---|---|
| Explicaciones y demostraciones | 50 minutos |
| Prácticas guiadas | 45 minutos |
| Ejercicios individuales, diseño y depuración | 35 minutos |
| Mini proyecto: estructura organizacional de una empresa | 25 minutos |
| Proyecto del módulo: sistema de gestión para una clínica | 70 minutos |
| Evaluación, revisión y preparación de la entrega | 15 minutos |
| Total | 4 horas |
Los tiempos son orientativos. El diseño puede necesitar varias revisiones. Corregir un diagrama antes de construir las tablas forma parte del trabajo profesional.
Del problema real al modelo de datos
1 No comiences creando tablas
Lee esta solicitud:
“Necesitamos una base de datos para una clínica.”
Todavía no existe información suficiente para diseñarla. Antes de escribir SQL debes descubrir:
- Qué actividades realizará la clínica.
- Qué información necesita conservar.
- Qué reglas no se pueden incumplir.
- Qué situaciones pueden ocurrir más de una vez.
- Qué datos son obligatorios y cuáles son opcionales.
Crear tablas sin comprender el problema produce estructuras difíciles de corregir.
2 Tres niveles de diseño
El proceso puede dividirse en tres niveles:
REALIDAD Y REQUISITOS
│
▼
MODELO CONCEPTUAL
Entidades, atributos y relaciones
│
▼
MODELO LÓGICO
Tablas, claves y cardinalidades
│
▼
MODELO FÍSICO
CREATE TABLE y reglas del motorModelo conceptual
Describe qué existe en el problema, sin preocuparse todavía por una sintaxis concreta.
Modelo lógico
Convierte los conceptos en tablas, columnas, claves y relaciones.
Modelo físico
Implementa el diseño en SQLite mediante tipos, restricciones e instrucciones SQL.
Separar estos niveles evita que una decisión técnica oculte un requisito del negocio.
3 Entidades
Una entidad es algo relevante sobre lo que se necesita conservar información.
En una clínica podrían existir:
- Paciente.
- Médico.
- Especialidad.
- Consultorio.
- Cita.
Una entidad suele convertirse en una tabla.
Una palabra no es automáticamente una entidad. Debe tener importancia propia para el sistema y normalmente varias ocurrencias.
4 Atributos
Un atributo describe una propiedad de una entidad.
Entidad: paciente
├── nombre
├── documento
├── fecha_nacimiento
├── telefono
└── correoLos atributos suelen convertirse en columnas.
Pregunta útil
¿Este elemento tiene propiedades propias y varias ocurrencias, o solamente describe otra cosa?
Ejemplo:
pacientees una entidad.telefononormalmente es un atributo del paciente.citaes una entidad porque posee fecha, estado, motivo y relaciones propias.
5 Reglas de negocio
Una regla de negocio describe una condición que debe cumplirse dentro del sistema.
Ejemplos:
- Cada médico posee un número de licencia irrepetible.
- Una cita pertenece a un paciente.
- Una cita es atendida por un médico.
- Un médico puede tener varias especialidades.
- Una especialidad puede corresponder a varios médicos.
- El estado de una cita solo puede ser programada, confirmada, atendida o cancelada.
- Dos médicos diferentes pueden utilizar el mismo consultorio, pero no a la misma hora.
Estas reglas guían el diseño. Algunas se protegerán con restricciones de la base y otras requerirán lógica de aplicación en cursos posteriores.
6 Hechos, suposiciones y preguntas
No conviertas una suposición en una regla sin reconocerla.
| Tipo | Ejemplo |
|---|---|
| Hecho proporcionado | Cada médico posee un número de licencia |
| Suposición | Todo paciente tiene correo electrónico |
| Pregunta pendiente | ¿Un médico puede tener varias especialidades? |
Cuando falta información, registra la pregunta. En un proyecto real se consultaría con la persona responsable del proceso.
Práctica guiada 1 — Analizar un centro deportivo
Lee el caso:
Un centro deportivo ofrece clases. Cada clase pertenece a una disciplina y es impartida por un instructor. Los socios pueden inscribirse en varias clases. Cada clase admite muchos socios. El correo de cada socio debe ser único.
Paso 1. Identifica entidades
- Socio.
- Clase.
- Disciplina.
- Instructor.
- Inscripción.
Paso 2. Identifica atributos iniciales
socio: nombre, correo, telefono
clase: nombre, horario, capacidad
disciplina: nombre
instructor: nombre, correo
inscripcion: fecha_inscripcionPaso 3. Escribe reglas
- Una disciplina puede tener muchas clases.
- Cada clase pertenece a una disciplina.
- Un instructor puede impartir varias clases.
- Cada clase posee un instructor.
- Un socio puede inscribirse en varias clases.
- Una clase puede recibir varios socios.
- Un socio no debe inscribirse dos veces en la misma clase.
Observa que inscripcion aparece porque la relación entre socios y clases necesita conservar información propia y evitar duplicados.
Claves: identidad y referencia
1 Por qué cada registro necesita identidad
Una clínica puede tener dos pacientes llamados Laura Gómez. El nombre no basta para distinguirlos.
Laura Gómez, documento P-104
Laura Gómez, documento P-281Una clave permite identificar o relacionar registros sin depender de descripciones ambiguas.
2 Clave candidata
Una clave candidata es un atributo, o conjunto de atributos, capaz de identificar de manera única cada registro.
En una tabla de pacientes podrían considerarse:
- Documento de identidad.
- Número interno de expediente.
Ambos podrían ser únicos, pero se debe elegir cuál será la clave principal.
3 Clave natural
Una clave natural ya existe en el dominio del problema.
Ejemplos:
- Número de licencia médica.
- ISBN de una edición de un libro.
- Código oficial de un país.
Ventaja: posee significado fuera de la base.
Riesgos:
- Puede cambiar.
- Puede ser larga.
- Puede contener errores de captura.
- Su formato puede depender de una institución externa.
4 Clave sustituta
Una clave sustituta se crea únicamente para identificar registros dentro del sistema.
id INTEGER PRIMARY KEYNo describe al paciente ni al médico. Su función es proporcionar una identidad estable y sencilla.
En este curso se utilizará normalmente una clave sustituta id, mientras que las claves naturales importantes se protegerán con UNIQUE.
Ejemplo:
CREATE TABLE pacientes (
id INTEGER PRIMARY KEY,
documento TEXT NOT NULL UNIQUE,
nombre TEXT NOT NULL
);id identifica internamente. documento conserva su valor real y no permite duplicados.
5 Clave primaria
La clave primaria identifica de manera única cada fila.
Propiedades prácticas:
- No debe repetirse.
- No debe estar ausente.
- Debe permanecer estable.
- Cada tabla posee una clave primaria, que puede estar formada por una o varias columnas.
Ejemplo simple:
id INTEGER PRIMARY KEY6 Clave compuesta
Una clave compuesta utiliza varias columnas.
En una tabla que conecta médicos y especialidades:
PRIMARY KEY (medico_id, especialidad_id)La combinación no se puede repetir:
| medico_id | especialidad_id | ¿Válido? |
|---|---|---|
| 1 | 2 | Sí |
| 1 | 3 | Sí |
| 1 | 2 | No; la combinación ya existe |
7 Clave foránea
Una clave foránea contiene un valor que debe corresponder a una clave de otra tabla.
departamentos
┌────┬──────────────┐
│ id │ nombre │
├────┼──────────────┤
│ 1 │ Tecnología │
│ 2 │ Finanzas │
└────┴──────────────┘
empleados
┌────┬────────────┬─────────────────┐
│ id │ nombre │ departamento_id │
├────┼────────────┼─────────────────┤
│ 1 │ Ana Mora │ 1 │
│ 2 │ Luis Vega │ 2 │
└────┴────────────┴─────────────────┘empleados.departamento_id hace referencia a departamentos.id.
En SQL:
FOREIGN KEY (departamento_id)
REFERENCES departamentos(id)8 Tabla padre y tabla hija
En la relación anterior:
departamentoses la tabla padre o referenciada.empleadoses la tabla hija o referente.- La fila hija depende de que exista una fila padre válida.
Una clave foránea evita empleados que señalen departamentos inexistentes.
departamento_id = 2 → válido si departamentos.id = 2 existe
departamento_id = 99 → inválido si no existe el departamento 99Práctica guiada 2 — Elegir claves
Para cada entidad, selecciona una clave primaria sustituta y una posible clave natural que debería ser única.
| Entidad | Clave primaria | Clave natural única |
|---|---|---|
| Médico | id | numero_licencia |
| Paciente | id | documento |
| Consultorio | id | codigo |
| Curso | id | codigo_curso |
| Producto | id | codigo_producto |
La clave natural no reemplaza obligatoriamente a id. Ambas pueden cumplir funciones diferentes.
Relaciones, cardinalidad y opcionalidad
1 Qué expresa una relación
Una relación responde cómo se asocian las ocurrencias de dos entidades.
Ejemplo:
Un departamento tiene empleados y cada empleado pertenece a un departamento.
No basta con decir que las tablas “están conectadas”. Debes determinar cuántos registros pueden relacionarse y si la relación es obligatoria.
2 Relación uno a muchos
Un departamento puede tener muchos empleados. Cada empleado pertenece a un departamento.
departamentos 1 ─────────── N empleadosLa clave foránea se coloca normalmente en el lado “muchos”:
empleados.departamento_id → departamentos.idEjemplos comunes:
- Una categoría tiene muchos productos.
- Un paciente tiene muchas citas.
- Un curso tiene muchas lecciones.
- Un hotel tiene muchas habitaciones.
3 Relación uno a uno
Una persona posee como máximo un expediente adicional y cada expediente pertenece a una persona.
personas 1 ─────────── 1 expedientesUna forma de protegerla consiste en utilizar la clave de la tabla principal como clave primaria y foránea de la tabla dependiente:
CREATE TABLE usuarios (
id INTEGER PRIMARY KEY,
nombre TEXT NOT NULL
);
CREATE TABLE perfiles (
usuario_id INTEGER PRIMARY KEY,
biografia TEXT,
FOREIGN KEY (usuario_id)
REFERENCES usuarios(id)
ON DELETE CASCADE
);Como usuario_id es clave primaria, no puede existir más de un perfil para el mismo usuario.
No dividas automáticamente toda entidad en parejas de tablas. Una relación uno a uno debe responder a una necesidad real, como separar información opcional, sensible o con un ciclo de vida diferente.
4 Relación muchos a muchos
Un médico puede poseer varias especialidades y una especialidad puede corresponder a varios médicos.
medicos N ─────────── N especialidadesUna base relacional resuelve esta relación mediante una tabla intermedia:
medicos 1 ──< medico_especialidad >── 1 especialidadesCREATE TABLE medico_especialidad (
medico_id INTEGER,
especialidad_id INTEGER,
PRIMARY KEY (medico_id, especialidad_id),
FOREIGN KEY (medico_id)
REFERENCES medicos(id),
FOREIGN KEY (especialidad_id)
REFERENCES especialidades(id)
);La tabla intermedia puede contener atributos propios, por ejemplo, la fecha en que se acreditó la especialidad.
5 Opcionalidad
La cardinalidad indica cuántos. La opcionalidad indica si la relación debe existir.
Ejemplo:
- Un paciente puede no tener ninguna cita todavía.
- Cada cita debe tener exactamente un paciente.
paciente 1 ─────────── 0..N citas
cita 1 ─────────── 1 pacienteUna clave foránea con NOT NULL hace obligatoria la relación desde la fila hija:
paciente_id INTEGER NOT NULLSi se permite NULL, la relación puede estar ausente, salvo que otra regla lo impida.
6 Notación de pata de cuervo
Una notación común utiliza símbolos en los extremos:
| Símbolo | Significado | ||
|---|---|---|---|
| | Exactamente uno | |
| `o | | Cero o uno | |
| {` | Uno o muchos | |
o{ | Cero o muchos |
Ejemplo:
departamentos ||────────o{ empleadosSe interpreta así:
- Cada empleado pertenece a exactamente un departamento.
- Un departamento puede tener cero o muchos empleados.
7 Diagrama entidad-relación
Un diagrama entidad-relación muestra visualmente:
- Entidades.
- Atributos principales.
- Claves.
- Relaciones.
- Cardinalidad.
- Opcionalidad.
Ejemplo:
┌───────────────────┐ ┌────────────────────┐
│ departamentos │ │ empleados │
├───────────────────┤ ├────────────────────┤
│ PK id │ ||─────o{ │ PK id │
│ UQ nombre │ │ nombre │
│ presupuesto │ │ correo │
└───────────────────┘ │ FK departamento_id │
└────────────────────┘Convenciones utilizadas en el curso:
PK: clave primaria.FK: clave foránea.UQ: valor único.NN: valor obligatorio.
8 Herramientas para diagramar
Puedes dibujar a mano durante el análisis y preparar la versión final con:
- diagrams.net, herramienta gratuita de diagramación.
- dbdiagram.io, herramienta especializada en esquemas de bases de datos.
La herramienta no corrige automáticamente las reglas del negocio. Un diagrama atractivo puede contener un diseño incorrecto.
Video recomendado
Ejemplo de diseño de una base de datos mediante diagrama entidad-relación — Hernando Moreno A.
Propósito: observar cómo una situación se convierte en entidades y relaciones antes de crear las tablas.
Práctica guiada 3 — Resolver una relación muchos a muchos
Situación:
Una estudiante puede matricular varios cursos. Un curso puede tener muchos estudiantes. La matrícula debe conservar la fecha y el estado.
Modelo:
estudiantes ||──o{ matriculas }o──|| cursosTablas necesarias:
estudiantes
cursos
matriculasLa tabla matriculas contendrá:
estudiante_id.curso_id.fecha_matricula.estado.
La combinación de estudiante y curso puede funcionar como clave primaria compuesta si una persona solo puede tener una matrícula activa por curso dentro del alcance del sistema.
Restricciones: reglas protegidas por la base
1 Qué es una restricción
Una restricción es una regla declarada dentro del esquema. SQLite comprueba la regla antes de aceptar ciertos datos.
Intento de inserción
│
▼
Comprobación de restricciones
│
├── Cumple → se acepta
└── Incumple → se rechaza2 PRIMARY KEY
Identifica de manera única cada fila.
id INTEGER PRIMARY KEYPara una tabla intermedia:
PRIMARY KEY (empleado_id, proyecto_id)3 NOT NULL
Impide que una columna quede sin valor.
nombre TEXT NOT NULLUtilízalo cuando la entidad no pueda tener sentido sin ese dato.
No marques todo como obligatorio por costumbre. Un segundo teléfono o una observación pueden ser opcionales.
4 UNIQUE
Impide valores duplicados.
correo TEXT UNIQUETambién puede aplicarse a una combinación:
UNIQUE (consultorio_id, fecha_hora)La combinación evita reservar el mismo consultorio dos veces en la misma fecha y hora.
5 CHECK
Comprueba una condición.
salario REAL CHECK (salario > 0)activo INTEGER CHECK (activo IN (0, 1))estado TEXT CHECK (
estado IN ('Planificado', 'En curso', 'Finalizado')
)La expresión IN indica que el valor debe pertenecer al conjunto mostrado.
Una restricción CHECK protege reglas que dependen de los valores de la misma fila. Las reglas que requieren comparar muchas filas o consultar otras tablas necesitan otras estrategias.
6 DEFAULT
Proporciona un valor cuando la inserción omite una columna.
activo INTEGER NOT NULL DEFAULT 1estado TEXT NOT NULL DEFAULT 'Programada'DEFAULT no corrige un valor inválido proporcionado explícitamente. Solo se utiliza cuando el valor no se envía.
7 FOREIGN KEY
Protege la existencia de una relación.
FOREIGN KEY (departamento_id)
REFERENCES departamentos(id)Una clave foránea no crea automáticamente una nueva fila padre. El departamento debe existir antes de insertar al empleado.
8 Varias restricciones pueden trabajar juntas
correo TEXT NOT NULL UNIQUEEl correo es obligatorio y no puede repetirse.
estado TEXT NOT NULL DEFAULT 'Programada'
CHECK (estado IN ('Programada', 'Confirmada', 'Atendida', 'Cancelada'))El estado es obligatorio, posee un valor inicial y solo acepta opciones válidas.
Implementar relaciones correctamente en SQLite
1 Activa las claves foráneas
En SQLite la comprobación de claves foráneas debe habilitarse para cada conexión.
Ejecuta al inicio de la sesión o del script:
PRAGMA foreign_keys = ON;Comprueba el estado:
PRAGMA foreign_keys;Resultado esperado:
1Si devuelve 0, la comprobación no está activa.
No asumas que DB Browser la activó por ti. Compruébalo siempre antes de probar relaciones.
2 Crea primero las tablas padre
Orden recomendado:
1. departamentos
2. empleadosLa tabla hija hace referencia a la tabla padre, por lo que el script resulta más comprensible si crea primero la estructura referenciada.
3 Ejemplo completo: departamentos y empleados
PRAGMA foreign_keys = ON;
CREATE TABLE departamentos (
id INTEGER PRIMARY KEY,
nombre TEXT NOT NULL UNIQUE,
presupuesto REAL NOT NULL CHECK (presupuesto >= 0)
);
CREATE TABLE empleados (
id INTEGER PRIMARY KEY,
nombre TEXT NOT NULL,
correo TEXT NOT NULL UNIQUE,
salario REAL NOT NULL CHECK (salario > 0),
activo INTEGER NOT NULL DEFAULT 1
CHECK (activo IN (0, 1)),
departamento_id INTEGER NOT NULL,
FOREIGN KEY (departamento_id)
REFERENCES departamentos(id)
ON UPDATE CASCADE
ON DELETE RESTRICT
);4 Lee el diseño antes de insertar
departamentos
- Posee un identificador.
- Su nombre es obligatorio y único.
- El presupuesto no puede ser negativo.
empleados
- Nombre, correo, salario y departamento son obligatorios.
- El correo no puede repetirse.
- El salario debe ser mayor que cero.
activoutiliza 1 por defecto y solo admite 0 o 1.- El departamento debe existir.
- No se puede eliminar un departamento que todavía tenga empleados.
5 Inserta primero las filas padre
INSERT INTO departamentos (id, nombre, presupuesto)
VALUES
(1, 'Tecnología', 85000.00),
(2, 'Finanzas', 52000.00),
(3, 'Operaciones', 68000.00);Después inserta las filas hijas:
INSERT INTO empleados (
id,
nombre,
correo,
salario,
departamento_id
) VALUES
(1, 'Ana Mora', 'ana.mora@empresa.test', 1800.00, 1),
(2, 'Luis Vega', 'luis.vega@empresa.test', 1650.00, 2),
(3, 'Marta Solís', 'marta.solis@empresa.test', 1725.00, 1);La columna activo se omitió y recibió el valor predeterminado 1.
6 Comprueba que las reglas funcionen
Ejecuta cada prueba por separado sobre una copia de práctica.
Departamento inexistente
INSERT INTO empleados (
id,
nombre,
correo,
salario,
departamento_id
) VALUES (
4,
'Carlos Rojas',
'carlos.rojas@empresa.test',
1500.00,
99
);Debe fallar porque el departamento 99 no existe.
Correo duplicado
INSERT INTO empleados (
id,
nombre,
correo,
salario,
departamento_id
) VALUES (
4,
'Carlos Rojas',
'ana.mora@empresa.test',
1500.00,
3
);Debe fallar por UNIQUE.
Salario inválido
INSERT INTO empleados (
id,
nombre,
correo,
salario,
departamento_id
) VALUES (
4,
'Carlos Rojas',
'carlos.rojas@empresa.test',
-100.00,
3
);Debe fallar por CHECK.
Nombre ausente
INSERT INTO empleados (
id,
nombre,
correo,
salario,
departamento_id
) VALUES (
4,
NULL,
'carlos.rojas@empresa.test',
1500.00,
3
);Debe fallar por NOT NULL.
Una restricción que nunca se prueba podría estar mal escrita o desactivada.
7 Revisa todas las claves foráneas
PRAGMA foreign_key_check;Si la consulta no devuelve filas, no se detectaron violaciones de claves foráneas.
8 Inspecciona la estructura
PRAGMA table_info(empleados);Permite revisar columnas, tipos, valores obligatorios y clave primaria.
PRAGMA foreign_key_list(empleados);Muestra las claves foráneas declaradas para la tabla.
Práctica guiada 4 — Construir y romper de forma controlada
- Crea
empresa_practica.db. - Activa claves foráneas.
- Crea
departamentosyempleados. - Inserta los departamentos.
- Inserta los tres empleados válidos.
- Comprueba que
activorecibió el valor 1. - Ejecuta cada prueba inválida por separado.
- Anota qué restricción rechazó cada intento.
- Ejecuta
PRAGMA foreign_key_check. - Conserva capturas de dos errores distintos.
Acciones referenciales y cambios del esquema
1 Qué ocurre cuando cambia una fila padre
Supón que un departamento tiene empleados. Si alguien intenta eliminarlo, la base debe decidir qué ocurre con las filas hijas.
Las acciones más importantes son:
| Acción | Comportamiento |
|---|---|
RESTRICT | Impide modificar o eliminar el padre mientras existan filas dependientes |
CASCADE | Propaga el cambio o la eliminación a las filas hijas |
SET NULL | Conserva las filas hijas y coloca NULL en su clave foránea |
NO ACTION | No aplica una acción especial; la restricción debe quedar satisfecha |
2 ON DELETE RESTRICT
FOREIGN KEY (departamento_id)
REFERENCES departamentos(id)
ON DELETE RESTRICTEs apropiado cuando eliminar la fila padre dejaría datos sin significado y se prefiere obligar a resolver primero las dependencias.
3 ON DELETE CASCADE
FOREIGN KEY (medico_id)
REFERENCES medicos(id)
ON DELETE CASCADESi se elimina el médico, también se eliminan sus filas en una tabla intermedia.
Utilízalo cuando la fila hija no tenga sentido sin la fila padre. No lo elijas solo porque resulta cómodo: una cascada puede eliminar muchos registros.
4 ON DELETE SET NULL
medico_asignado_id INTEGER,
FOREIGN KEY (medico_asignado_id)
REFERENCES medicos(id)
ON DELETE SET NULLLa fila hija se conserva, pero queda sin médico asignado. La columna debe permitir NULL.
5 ON UPDATE CASCADE
ON UPDATE CASCADESi cambia la clave referenciada, la actualización se propaga a las claves hijas. Las claves primarias deberían cambiar muy rara vez, pero declarar la acción hace explícita la decisión.
6 Cómo elegir
Pregunta:
- ¿La fila hija conserva significado sin el padre?
- ¿Debe preservarse por historial?
- ¿La relación puede quedar temporalmente ausente?
- ¿Eliminar automáticamente sería peligroso?
Ejemplos razonables:
| Relación | Acción posible | Justificación |
|---|---|---|
| Departamento → empleados | RESTRICT | No se desea borrar empleados automáticamente |
| Médico → tabla de especialidades | CASCADE | La asociación no tiene sentido sin el médico |
| Categoría → productos | SET NULL | El producto puede conservarse sin categoría, si la regla lo permite |
| Paciente → citas | RESTRICT | Las citas pueden formar parte del historial |
No existe una acción universalmente correcta. La regla depende del negocio.
7 Añadir una columna con ALTER TABLE
ALTER TABLE empleados
ADD COLUMN telefono TEXT;8 Cambiar el nombre de una columna
ALTER TABLE empleados
RENAME COLUMN correo TO correo_institucional;9 Cambiar el nombre de una tabla
ALTER TABLE empleados
RENAME TO colaboradores;SQLite admite cambios básicos directamente. Las modificaciones complejas pueden requerir crear una tabla nueva, copiar los datos y reemplazar la estructura. Esa migración debe planificarse y probarse.
10 Eliminar una tabla
DROP TABLE empleados;DROP TABLE elimina la estructura y sus datos. Utilízalo solamente en bases de práctica o cuando la eliminación forme parte de un cambio autorizado.
Si existen relaciones, elimina primero las tablas hijas y después las tablas padre:
1. empleados
2. departamentosNo practiques DROP TABLE sobre el único archivo de tu proyecto. Trabaja con una copia que puedas reemplazar.
Práctica guiada 5 — Elegir acciones referenciales
Decide una acción y justifica la elección:
- Eliminar una factura que posee líneas de detalle.
- Eliminar una categoría que tiene productos activos.
- Eliminar un usuario que posee una configuración personal sin valor histórico.
- Eliminar un paciente con citas registradas.
No busques una palabra “correcta” sin contexto. Escribe qué debe conservar el negocio y qué pérdida sería aceptable.
Normalización práctica
1 Por qué se normaliza
La normalización ayuda a reducir repetición innecesaria y prevenir inconsistencias.
Considera:
| cita_id | paciente_nombre | paciente_telefono | medico_nombre | especialidad | fecha |
|---|---|---|---|---|---|
| 1 | Ana Mora | 8888-1111 | Luis Vega | Pediatría | 2026-08-10 |
| 2 | Ana Mora | 8888-1111 | Marta Solís | Medicina general | 2026-08-18 |
| 3 | Ana Mora | 8999-2222 | Luis Vega | Pediatría | 2026-09-02 |
¿Cuál teléfono es correcto? La repetición permitió una contradicción.
2 Anomalías
Anomalía de actualización
Para cambiar el teléfono de una paciente deben modificarse varias filas. Si una queda sin actualizar, aparecen versiones contradictorias.
Anomalía de inserción
No se puede registrar un médico nuevo hasta que tenga una cita, porque toda la información está mezclada en la misma tabla.
Anomalía de eliminación
Si se elimina la única cita de un médico, también se pierde su información profesional.
Separar entidades reduce estas anomalías.
3 Primera forma normal — 1FN
Una tabla en primera forma normal debe evitar grupos repetidos y valores que contengan listas difíciles de consultar.
Diseño problemático:
| paciente_id | nombre | telefonos |
|---|---|---|
| 1 | Ana Mora | 8888-1111, 2222-3333 |
La columna almacena dos valores dentro de una celda.
Otro diseño problemático:
| paciente_id | nombre | telefono_1 | telefono_2 | telefono_3 |
|---|
La cantidad de columnas depende del número de teléfonos.
Diseño normalizado cuando el sistema necesita varios teléfonos:
pacientes
├── id
└── nombre
telefonos_paciente
├── id
├── paciente_id
├── numero
└── tipoNo es necesario crear una tabla separada si el requisito permite exactamente un único teléfono. La estructura debe responder a la realidad del sistema.
4 Segunda forma normal — 2FN
La segunda forma normal resulta relevante especialmente cuando existe una clave primaria compuesta.
Diseño problemático:
detalle_pedido
PK pedido_id
PK producto_id
cantidad
nombre_producto
fecha_pedidoLa clave completa es (pedido_id, producto_id), pero:
nombre_productodepende solamente deproducto_id.fecha_pedidodepende solamente depedido_id.cantidaddepende de la combinación completa.
Diseño mejorado:
pedidos
├── id
└── fecha_pedido
productos
├── id
└── nombre
detalle_pedido
├── pedido_id
├── producto_id
└── cantidadUna tabla con clave simple y que ya cumple 1FN normalmente no presenta una dependencia parcial de la clave.
5 Tercera forma normal — 3FN
La tercera forma normal evita que una columna no clave dependa de otra columna no clave.
Diseño problemático:
empleados
├── id
├── nombre
├── departamento_id
└── departamento_nombredepartamento_nombre depende de departamento_id, no directamente del empleado.
Diseño mejorado:
departamentos
├── id
└── nombre
empleados
├── id
├── nombre
└── departamento_id6 No normalices por reflejo
Normalizar no significa convertir cada columna en una tabla.
Diseño innecesario:
personas
nombres_persona
apellidos_persona
ciudades_persona
correos_personaLa separación debe resolver repetición, dependencias o reglas reales. Un diseño excesivamente fragmentado puede ser difícil de comprender y utilizar.
7 Método práctico de revisión
Para cada tabla, pregunta:
- ¿Qué representa una fila?
- ¿Existe alguna columna con una lista de valores?
- ¿Existen columnas numeradas como
telefono_1,telefono_2ytelefono_3? - ¿Se repite información descriptiva de otra entidad?
- ¿Un cambio obliga a modificar muchas filas?
- ¿Se perdería información importante al eliminar el último registro de una actividad?
- ¿Cada columna depende de la identidad completa de la fila?
Video recomendado
Normalización de bases de datos: 1FN, 2FN y 3FN — Jesús Domínguez Gutú
Propósito: reforzar las tres formas normales mediante ejemplos y reconocer problemas de repetición.
Diccionario de datos y modelo relacional
1 Modelo relacional escrito
Además del diagrama, documenta cada tabla en una forma compacta:
DEPARTAMENTOS(
id PK,
nombre UQ NN,
presupuesto NN
)
EMPLEADOS(
id PK,
nombre NN,
correo UQ NN,
salario NN,
activo NN,
departamento_id FK → DEPARTAMENTOS.id NN
)2 Diccionario de datos
Un diccionario de datos explica el propósito y las reglas de cada columna.
| Tabla | Columna | Tipo | Reglas | Descripción |
|---|---|---|---|---|
| departamentos | id | INTEGER | PK | Identificador interno |
| departamentos | nombre | TEXT | NN, UQ | Nombre del departamento |
| departamentos | presupuesto | REAL | NN, >= 0 | Presupuesto aprobado |
| empleados | departamento_id | INTEGER | FK, NN | Departamento al que pertenece |
Un buen diccionario evita que otra persona tenga que deducir el significado de nombres o códigos.
3 Orden profesional de la documentación
- Descripción del problema.
- Alcance y exclusiones.
- Reglas de negocio.
- Diagrama entidad-relación.
- Modelo relacional.
- Diccionario de datos.
- Decisiones de integridad referencial.
- Evidencias de validación.
Diferencias entre SQLite y otros motores
Los conceptos del modelo relacional se transfieren, pero algunos detalles físicos cambian.
| Tema | SQLite | Otros motores |
|---|---|---|
| Almacenamiento | Base completa en un archivo | Normalmente utilizan un servidor |
| Tipos | Afinidad flexible; tablas STRICT opcionales | Tipos generalmente más rígidos |
| Claves foráneas | Se activan por conexión con PRAGMA foreign_keys = ON | Normalmente se aplican según la configuración del servidor |
| Identificador automático | INTEGER PRIMARY KEY posee comportamiento especial | Puede utilizar IDENTITY, AUTO_INCREMENT o columnas de identidad |
| Booleanos | Se suelen representar con 0 y 1 | Algunos motores tienen tipo booleano propio |
| Fechas | Pueden almacenarse como texto, real o entero | Suelen existir tipos específicos de fecha y hora |
ALTER TABLE | Operaciones directas más limitadas | Algunos motores permiten más cambios directos |
No memorices todas las variantes. Aprende a reconocer qué parte pertenece al modelo relacional y consulta la documentación del motor cuando cambies de entorno.
Buenas prácticas y errores frecuentes
1 Crear una tabla para cada palabra del enunciado
No toda palabra es una entidad. nombre, estado y telefono pueden ser atributos.
2 Utilizar el nombre como clave primaria
Los nombres pueden repetirse, corregirse o cambiar. Prefiere una clave estable y protege las claves naturales importantes con UNIQUE.
3 Colocar la clave foránea en el lado incorrecto
En una relación uno a muchos, la clave foránea suele colocarse en el lado muchos.
departamento 1 ─── N empleados
empleados.departamento_id4 Escribir una relación muchos a muchos sin tabla intermedia
Evita columnas como:
especialidades = 'Pediatría, Cardiología, Medicina general'Utiliza una tabla intermedia.
5 Declarar la clave foránea, pero no activarla
En SQLite debes ejecutar y comprobar:
PRAGMA foreign_keys = ON;
PRAGMA foreign_keys;6 Utilizar CASCADE sin analizar las consecuencias
Una cascada puede eliminar todas las filas relacionadas. Decide primero qué debe conservarse.
7 Permitir NULL en datos obligatorios
Si una cita no puede existir sin paciente, utiliza NOT NULL en paciente_id.
8 Utilizar DEFAULT como sustituto de un dato obligatorio
Un valor predeterminado no debe inventar información real. No asignes un documento, correo o médico ficticio solo para evitar NULL.
9 Confiar únicamente en el diagrama
El diagrama comunica el diseño. El script implementa y protege las reglas. Ambos deben coincidir.
10 Probar solamente casos válidos
Una restricción demuestra su valor cuando rechaza un caso inválido. Incluye pruebas controladas.
Ejercicios individuales
Resuelve los ejercicios antes de consultar las soluciones.
Ejercicio 1 — Entidad o atributo
Un hotel necesita administrar huéspedes, habitaciones, reservas, número de pasaporte, tipo de habitación, fecha de entrada, país y pagos.
Clasifica cada elemento como entidad probable, atributo probable o elemento que necesita más contexto. Justifica las decisiones.
Ejercicio 2 — Extraer reglas
Lee:
Cada producto pertenece a una categoría. Una categoría puede existir aunque todavía no tenga productos. El código de cada producto es único. El precio debe ser mayor que cero. La descripción es opcional.
Escribe al menos seis reglas de diseño o integridad derivadas del texto.
Ejercicio 3 — Elegir claves
Para vehiculos, estudiantes, habitaciones y empleados, propone:
- Una clave primaria sustituta.
- Una clave natural candidata.
- Una razón por la que la clave natural podría no ser la clave primaria.
Ejercicio 4 — Determinar cardinalidad
Clasifica cada relación como 1:1, 1:N o N:M:
- País y ciudades.
- Estudiantes y cursos.
- Usuario y perfil único.
- Pedido y líneas de detalle.
- Actores y películas.
- Habitación y reservas a lo largo del tiempo.
Indica dónde colocarías la clave foránea o si se necesita una tabla intermedia.
Ejercicio 5 — Corregir una lista en una columna
Se diseñó:
medicos(id, nombre, especialidades)La columna especialidades contiene valores como:
'Pediatría, Cardiología'Explica el problema y dibuja un modelo de tres tablas que permita representar la relación correctamente.
Ejercicio 6 — Seleccionar restricciones
Elige una o más restricciones para cada regla:
- El correo del usuario no puede repetirse.
- Una calificación debe estar entre 0 y 100.
- Una cita se crea como programada si no se indica estado.
- Todo producto debe tener nombre.
- Todo empleado debe pertenecer a un departamento existente.
- La misma persona no puede matricular dos veces el mismo curso.
Ejercicio 7 — Reparar un esquema
Corrige todos los problemas que encuentres:
CREATE TABLE categorias (
id INTEGER,
nombre TEXT
);
CREATE TABLE productos (
id INTEGER PRIMARY KEY,
nombre TEXT,
codigo TEXT,
precio REAL,
categoria TEXT,
categoria_id INTEGER,
FOREIGN KEY (categoria_id)
REFERENCES categoria(id)
);Requisitos:
- Las categorías tienen identidad.
- El nombre de categoría no se repite.
- Todo producto posee nombre, código, precio y categoría.
- El código es único.
- El precio debe ser positivo.
- No se debe duplicar el nombre de la categoría dentro de
productos.
Ejercicio 8 — Predecir errores
Utiliza el ejemplo de departamentos y empleados. Indica qué restricción rechazaría cada caso:
- Dos departamentos llamados
Tecnología. - Un empleado sin nombre.
- Un salario de cero.
- Un empleado con departamento 80 inexistente.
- Dos empleados con el mismo correo.
- Un valor de activo igual a 7.
Ejercicio 9 — Elegir una acción referencial
Propón RESTRICT, CASCADE o SET NULL y justifica:
- Autor y borradores temporales sin valor histórico.
- Paciente y citas médicas históricas.
- Categoría opcional y productos.
- Pedido y líneas de detalle.
- Departamento y empleados activos.
Ejercicio 10 — Aplicar 1FN
Corrige:
| estudiante_id | nombre | telefonos | curso_1 | curso_2 |
|---|---|---|---|---|
| 1 | Elena Ruiz | 8888-1111, 2222-2222 | SQL | Python |
Identifica todos los grupos repetidos o valores múltiples y propone las tablas necesarias.
Ejercicio 11 — Aplicar 2FN
La tabla posee clave primaria (reserva_id, servicio_id):
detalle_servicio(
reserva_id,
servicio_id,
fecha_reserva,
nombre_servicio,
cantidad,
precio_aplicado
)Indica qué columnas dependen solo de una parte de la clave y propone una separación adecuada.
Ejercicio 12 — Aplicar 3FN
Analiza:
empleados(
id,
nombre,
puesto_id,
puesto_nombre,
salario_base_puesto
)Explica la dependencia y propone un modelo en tercera forma normal.
Soluciones de los ejercicios — consultar después de intentarlos
Soluciones explicadas de los ejercicios
Solución del ejercicio 1
Entidades probables:
- Huésped.
- Habitación.
- Reserva.
- Tipo de habitación.
- Pago.
Atributos probables:
- Número de pasaporte, asociado al huésped.
- Fecha de entrada, asociada a la reserva.
- País, que podría ser texto o una entidad si el sistema necesita un catálogo oficial.
País necesita contexto: una tabla independiente se justifica si posee código, reglas o relaciones propias.
Solución del ejercicio 2
- Debe existir una tabla
categorias. - Debe existir una tabla
productos. - Una categoría puede relacionarse con cero o muchos productos.
- Cada producto debe relacionarse con exactamente una categoría.
productos.categoria_iddebe serNOT NULLy clave foránea.codigodebe serUNIQUEyNOT NULL.preciodebe poseerCHECK (precio > 0).descripcionpuede permitirNULL.
Solución del ejercicio 3
| Entidad | Sustituta | Natural candidata | Riesgo de la natural |
|---|---|---|---|
| Vehículo | id | placa | Puede cambiar o variar por país |
| Estudiante | id | código institucional | Puede cambiar entre instituciones |
| Habitación | id | número o código | Puede cambiar por remodelación |
| Empleado | id | documento | Puede tener formatos externos o correcciones |
Solución del ejercicio 4
- País 1:N ciudades;
ciudades.pais_id. - Estudiantes N:M cursos; tabla
matriculas. - Usuario 1:1 perfil;
perfiles.usuario_idpuede ser PK y FK. - Pedido 1:N líneas;
lineas_pedido.pedido_id. - Actores N:M películas; tabla
actor_pelicula. - Habitación 1:N reservas a lo largo del tiempo;
reservas.habitacion_id.
Solución del ejercicio 5
medicos
├── id
└── nombre
especialidades
├── id
└── nombre
medico_especialidad
├── medico_id
└── especialidad_idLa tabla intermedia permite cualquier cantidad de asociaciones sin guardar listas en una celda.
Solución del ejercicio 6
NOT NULL UNIQUEpara el correo, si es obligatorio.CHECK (calificacion >= 0 AND calificacion <= 100).DEFAULT 'Programada', junto conNOT NULLy unCHECKde estados válidos.NOT NULL.NOT NULLyFOREIGN KEY.PRIMARY KEY (estudiante_id, curso_id)oUNIQUEsobre esa combinación.
Solución del ejercicio 7
PRAGMA foreign_keys = ON;
CREATE TABLE categorias (
id INTEGER PRIMARY KEY,
nombre TEXT NOT NULL UNIQUE
);
CREATE TABLE productos (
id INTEGER PRIMARY KEY,
nombre TEXT NOT NULL,
codigo TEXT NOT NULL UNIQUE,
precio REAL NOT NULL CHECK (precio > 0),
categoria_id INTEGER NOT NULL,
FOREIGN KEY (categoria_id)
REFERENCES categorias(id)
ON UPDATE CASCADE
ON DELETE RESTRICT
);Se eliminó categoria TEXT porque repetía información que pertenece a categorias.
Solución del ejercicio 8
UNIQUEendepartamentos.nombre.NOT NULLenempleados.nombre.CHECK (salario > 0).FOREIGN KEY.UNIQUEenempleados.correo.CHECK (activo IN (0, 1)).
Solución orientativa del ejercicio 9
CASCADEpodría ser apropiado si los borradores no tienen sentido sin el autor y su eliminación está autorizada.RESTRICTpara proteger el historial.SET NULLsi un producto puede continuar sin categoría.CASCADEsi una línea de detalle no tiene sentido sin el pedido.RESTRICTpara impedir eliminar un departamento con empleados activos.
La justificación es más importante que memorizar una respuesta.
Solución del ejercicio 10
Modelo posible:
estudiantes(id, nombre)
telefonos_estudiante(id, estudiante_id, numero)
cursos(id, nombre)
matriculas(estudiante_id, curso_id)Los teléfonos dejan de formar una lista y los cursos dejan de aparecer como columnas numeradas.
Solución del ejercicio 11
fecha_reservadepende dereserva_id.nombre_serviciodepende deservicio_id.cantidadyprecio_aplicadopueden depender de la combinación completa.
Modelo:
reservas(id, fecha_reserva)
servicios(id, nombre_servicio)
detalle_servicio(reserva_id, servicio_id, cantidad, precio_aplicado)Solución del ejercicio 12
puesto_nombre y salario_base_puesto dependen de puesto_id, no directamente del empleado.
puestos(id, nombre, salario_base)
empleados(id, nombre, puesto_id)Mini proyecto — Estructura organizacional de una empresa
Objetivo
Diseñar e implementar relaciones uno a muchos y muchos a muchos mediante una base pequeña, restricciones verificables y un diagrama entidad-relación.
Situación
Una empresa necesita registrar departamentos, empleados y proyectos. Cada empleado pertenece a un departamento. Un empleado puede participar en varios proyectos y cada proyecto puede incluir varios empleados.
Modelo mínimo
departamentos ||──o{ empleados
empleados ||──o{ asignaciones }o──|| proyectosRequisitos obligatorios
departamentos
idcomo clave primaria.nombreobligatorio y único.ubicacionopcional.
empleados
idcomo clave primaria.nombreobligatorio.correoobligatorio y único.activoobligatorio, con valor predeterminado 1 y limitado a 0 o 1.departamento_idobligatorio y válido.
proyectos
idcomo clave primaria.nombreobligatorio y único.estadoobligatorio, con opcionesPlanificado,En cursoyFinalizado.
asignaciones
empleado_idcomo clave foránea.proyecto_idcomo clave foránea.rolobligatorio.- La combinación de empleado y proyecto no puede repetirse.
- Las asociaciones deben eliminarse mediante
CASCADEsi desaparece el empleado o proyecto en esta base de práctica.
Datos mínimos
- Tres departamentos.
- Cinco empleados.
- Tres proyectos.
- Seis asignaciones.
- Un departamento sin empleados para demostrar opcionalidad.
Pruebas obligatorias
- Intentar repetir un correo.
- Intentar asignar un empleado a un proyecto inexistente.
- Intentar repetir la misma asignación.
- Intentar utilizar un estado no permitido.
Ejecuta las pruebas por separado. Después de observar el error, déjalas comentadas en el script para que la ejecución principal continúe funcionando.
Entregable interno
Conserva:
- Diagrama.
- Script.
- Base
.db. - Dos capturas de restricciones rechazando datos inválidos.
Este mini proyecto se integra en la evidencia de trabajo del módulo. No requiere un formulario independiente.
Lista de comprobación
- Las cuatro tablas representan temas claros.
- Las claves primarias están definidas.
- Las claves foráneas apuntan a tablas y columnas correctas.
- La relación N:M utiliza
asignaciones. PRAGMA foreign_keysdevuelve 1.- Los datos válidos se insertan en el orden correcto.
- Las cuatro pruebas inválidas son rechazadas.
PRAGMA foreign_key_checkno devuelve violaciones.
Proyecto del módulo — Sistema de gestión para una clínica
Desafío
Una clínica necesita reemplazar documentos separados por una base de datos central. El sistema debe registrar pacientes, médicos, especialidades, consultorios y citas, evitando duplicados y relaciones imposibles.
Tu responsabilidad es analizar el caso, diseñar el modelo, implementarlo en SQLite y demostrar que las reglas de integridad funcionan.
Alcance
El proyecto administra la estructura y los datos esenciales de las citas. No incluye historiales clínicos, diagnósticos, recetas, facturación, seguros, autenticación ni una aplicación gráfica.
Excluir conscientemente información fuera del objetivo evita diseñar un sistema imposible de completar en este módulo.
Entidades obligatorias
- Especialidades.
- Médicos.
- Asociación entre médicos y especialidades.
- Pacientes.
- Consultorios.
- Citas.
Reglas de negocio obligatorias
- Cada especialidad posee un nombre único.
- Cada médico posee un número de licencia único.
- Un médico puede tener varias especialidades.
- Una especialidad puede corresponder a varios médicos.
- La misma asociación médico-especialidad no puede repetirse.
- Cada paciente posee un documento único.
- Cada consultorio posee un código único.
- La capacidad de un consultorio debe ser mayor que cero.
- Cada cita pertenece a un paciente existente.
- Cada cita es atendida por un médico existente.
- Cada cita utiliza un consultorio existente.
- El estado inicial de una cita es
Programada. - Los estados permitidos son
Programada,Confirmada,AtendidayCancelada. - Un médico no puede tener dos citas en la misma fecha y hora.
- Un consultorio no puede albergar dos citas en la misma fecha y hora.
- Pacientes, médicos y consultorios con citas asociadas no deben eliminarse automáticamente.
- Las filas de la tabla intermedia pueden eliminarse en cascada si desaparece el médico o la especialidad.
Columnas mínimas
especialidades
id.nombre.descripcion, opcional.
medicos
id.nombre.numero_licencia.correo.telefono.activo.
medico_especialidad
medico_id.especialidad_id.fecha_acreditacion, opcional.
pacientes
id.documento.nombre.fecha_nacimiento.telefono.correo, opcional.
consultorios
id.codigo.piso.capacidad.descripcion, opcional.
citas
id.paciente_id.medico_id.consultorio_id.fecha_hora.estado.motivo.observaciones, opcional.
Decisiones que debes tomar y justificar
- Qué columnas son obligatorias.
- Qué columnas deben ser únicas.
- Qué tipos utilizarás.
- Qué columnas permiten
NULL. - Qué restricciones
CHECKaplicarás. - Qué acciones referenciales utilizarás.
- Cómo evitarás citas duplicadas para médicos y consultorios.
- Qué formato utilizarás para fechas y horas.
Formato recomendado para fecha_hora en SQLite:
AAAA-MM-DD HH:MMEjemplo:
2026-08-15 09:30Cantidad mínima de datos
- Cuatro especialidades.
- Cinco médicos.
- Seis asociaciones médico-especialidad.
- Ocho pacientes.
- Cuatro consultorios.
- Doce citas.
- Por lo menos un valor
NULLlegítimo en cada tabla que posea campos opcionales. - Todos los estados permitidos deben aparecer al menos una vez en los datos de prueba.
Diagrama esperado
El diagrama debe mostrar como mínimo:
especialidades ||──o{ medico_especialidad }o──|| medicos
medicos ||──o{ citas
pacientes ||──o{ citas
consultorios ||──o{ citasIncluye claves primarias, claves foráneas, cardinalidades y opcionalidad.
Pruebas de integridad obligatorias
Demuestra que la base rechaza:
- Una especialidad duplicada.
- Un número de licencia duplicado.
- Un paciente sin nombre.
- Un consultorio con capacidad cero o negativa.
- Una cita con médico inexistente.
- Una cita con estado no permitido.
- La misma especialidad asignada dos veces al mismo médico.
- Dos citas del mismo médico a la misma hora.
- Dos citas en el mismo consultorio a la misma hora.
Las instrucciones inválidas deben permanecer comentadas al final del script, acompañadas por una explicación del error esperado. No deben impedir reconstruir la base.
Consultas de comprobación
En este módulo no se requieren JOIN. Incluye:
SELECT * FROM especialidades;
SELECT * FROM medicos;
SELECT * FROM medico_especialidad;
SELECT * FROM pacientes;
SELECT * FROM consultorios;
SELECT * FROM citas;
PRAGMA foreign_key_check;Las consultas multitabla se estudiarán más adelante.
Orden del script
1. Encabezado
2. PRAGMA foreign_keys = ON
3. Creación de tablas padre
4. Creación de tablas hijas e intermedias
5. Inserción de catálogos y padres
6. Inserción de asociaciones y citas
7. Consultas de comprobación
8. PRAGMA foreign_key_check
9. Pruebas inválidas comentadasProceso de construcción
Fase 1. Reescribe los requisitos
Expresa cada regla con una oración clara. No escribas SQL todavía.
Fase 2. Identifica entidades y atributos
Completa una lista y elimina cualquier atributo duplicado.
Fase 3. Determina claves
Selecciona claves primarias, claves naturales únicas y claves compuestas.
Fase 4. Dibuja relaciones
Marca 1:1, 1:N, N:M y opcionalidad.
Fase 5. Revisa normalización
Comprueba 1FN, 2FN y 3FN mediante las preguntas del módulo.
Fase 6. Construye el diccionario
Documenta tabla, columna, tipo, reglas y descripción.
Fase 7. Escribe CREATE TABLE
Trabaja desde las tablas padre hacia las hijas.
Fase 8. Inserta datos válidos
Respeta el orden de las dependencias.
Fase 9. Prueba datos inválidos
Ejecuta una prueba por vez y conserva evidencia del mensaje recibido.
Fase 10. Verifica relaciones
Ejecuta:
PRAGMA foreign_keys;
PRAGMA foreign_key_check;Fase 11. Reconstruye desde cero
Crea una base vacía de prueba y ejecuta el script principal completo.
Fase 12. Documenta y entrega
Comprueba que el diagrama, el modelo relacional, el diccionario y el script describan la misma estructura.
Restricciones del proyecto
- No utilices Python ni otro lenguaje.
- No agregues historiales clínicos ni facturación.
- No guardes especialidades como una lista dentro de
medicos. - No repitas datos del paciente dentro de
citas. - No utilices nombres como claves primarias.
- No desactives claves foráneas para conseguir que los datos se inserten.
- No utilices
CASCADEsin justificarlo. - No añadas consultas avanzadas que oculten errores del diseño.
- No utilices datos personales reales.
Lista de comprobación del proyecto
- El alcance está explicado.
- Las diecisiete reglas obligatorias están representadas.
- El diagrama contiene seis tablas.
- Las cardinalidades son correctas.
- La relación N:M utiliza una tabla intermedia.
- Todas las tablas tienen clave primaria.
- Las claves naturales importantes son únicas.
- Las claves foráneas están activas.
- Los campos obligatorios utilizan
NOT NULL. - Los valores controlados utilizan
CHECK. - Los valores iniciales apropiados utilizan
DEFAULT. - Las acciones referenciales están justificadas.
- El esquema cumple 1FN, 2FN y 3FN.
- Las cantidades mínimas de datos se cumplen.
- Las nueve pruebas inválidas son rechazadas.
PRAGMA foreign_key_checkno devuelve filas.- El script reconstruye la base desde cero.
- La documentación y las evidencias están completas.
Condición de avance
El proyecto debe alcanzar al menos 70 puntos, cumplir los requisitos críticos y ser aprobado. Si recibe observaciones, deberás corregirlas antes de comenzar el Módulo 3.
Rúbrica de evaluación del proyecto
| Criterio | Evidencia esperada | Puntos |
|---|---|---|
| Análisis y reglas de negocio | Alcance claro, reglas completas y decisiones justificadas | 15 |
| Diagrama y modelo relacional | Entidades, claves, relaciones, cardinalidad y opcionalidad correctas | 20 |
| Estructura SQL | Tablas, tipos y orden de creación correctos | 15 |
| Integridad | PK, FK, NN, UQ, CHECK, DEFAULT y acciones referenciales apropiadas | 25 |
| Normalización | Ausencia de listas, dependencias parciales y dependencias transitivas injustificadas | 10 |
| Datos y validación | Datos suficientes, pruebas inválidas y comprobación de claves foráneas | 10 |
| Organización y documentación | Script legible, diccionario, explicación y evidencias | 5 |
| Total | 100 |
Requisitos críticos
El proyecto no puede aprobarse si:
- No se entrega el script SQL.
- El script no reconstruye la base sobre un archivo vacío.
- Las claves foráneas están desactivadas durante las pruebas.
- La relación entre médicos y especialidades no utiliza una tabla intermedia.
- Existen referencias a registros inexistentes.
- Faltan entidades obligatorias.
- El diseño conserva listas dentro de una columna.
- Las restricciones contienen errores que impiden utilizar el proyecto.
- No se entrega el diagrama o no coincide con el script.
- Se presentan datos personales reales o contenido copiado sin comprensión.
Evaluación práctica del módulo
Situación
Un cine necesita registrar películas, salas y funciones. Cada función corresponde a una película y se realiza en una sala. Una película puede tener muchas funciones y una sala puede utilizarse en muchas funciones en horarios diferentes.
Tareas
- Identifica las tres entidades y sus atributos esenciales.
- Escribe por lo menos seis reglas de negocio.
- Dibuja las relaciones y cardinalidades.
- Selecciona las claves primarias.
- Define una clave natural única para películas y otra para salas.
- Diseña las claves foráneas de
funciones. - Evita dos funciones en la misma sala y fecha-hora.
- Limita el estado de una función a
Programada,DisponibleoCancelada. - Escribe las tres instrucciones
CREATE TABLE. - Inserta una película, una sala y una función válida.
- Explica qué ocurriría al insertar una función con una sala inexistente.
Tiempo sugerido
15 minutos
Criterios de dominio
- La clave foránea está en la tabla correcta.
- Las cardinalidades coinciden con el caso.
- Las claves y restricciones protegen las reglas.
- Las tablas se crean en un orden lógico.
- El estudiante puede explicar el propósito de cada restricción.
La evaluación comprueba diseño y razonamiento. No se califica la decoración del diagrama.
Punto de entrega obligatorio
Todo el módulo se entrega mediante un único punto. No se utilizan formularios separados para cada ejercicio o prueba.
Nombre del archivo
COA_SQL_M02_Apellido_Nombre.zipEjemplo:
COA_SQL_M02_Cerna_Victor.zipContenido obligatorio
COA_SQL_M02_Apellido_Nombre/
├── COA_SQL_M02_Apellido_Nombre.sql
├── clinica.db
├── documentacion_diseno.pdf
└── evidencias/
├── 01_diagrama_entidad_relacion.png
├── 02_estructura_tablas.png
├── 03_foreign_keys_activas.png
├── 04_datos_insertados.png
├── 05_error_clave_foranea.png
├── 06_error_restriccion.png
├── 07_foreign_key_check.png
└── 08_prueba_script_vacio.pngContenido de documentacion_diseno.pdf
- Descripción y alcance.
- Reglas de negocio.
- Diagrama entidad-relación legible.
- Modelo relacional escrito.
- Diccionario de datos.
- Justificación de claves y restricciones.
- Justificación de acciones referenciales.
- Explicación de normalización.
- Resultado de las pruebas inválidas.
Toda la documentación se reúne en un único PDF. No es necesario crear varios documentos separados.
Evidencias
- La captura de claves foráneas debe mostrar que
PRAGMA foreign_keysdevuelve 1. - Las capturas de errores deben mostrar intentos diferentes.
PRAGMA foreign_key_checkdebe ejecutarse sobre la versión final.- La prueba del script debe realizarse sobre una base vacía.
- Las imágenes deben ser legibles y corresponder al proyecto entregado.
Antes de enviar
- Abre el
.zip. - Comprueba los nombres.
- Ejecuta el script sobre una base vacía.
- Abre
clinica.dby revisa las seis tablas. - Compara el diagrama con el script.
- Comprueba las cantidades mínimas de datos.
- Revisa que las pruebas inválidas estén comentadas.
- Ejecuta
PRAGMA foreign_key_checkuna última vez.
Entrega del Módulo 2
Último paso del móduloCuando hayas completado las actividades, el proyecto, las pruebas y la reflexión, reúne todo en un único archivo comprimido.
La entrega única debe incluir:
- El script SQL principal
- La base de datos clinica.db
- La documentación del diseño en PDF
- Las ocho evidencias solicitadas
Ejemplo de nombre: COA_SQL_M02_Cerna_Victor.zip
Antes de enviar, verifica que el archivo tenga el nombre solicitado.
Retos adicionales
Reto 1 — Relación uno a uno
Agrega a una base de práctica las tablas usuarios y preferencias_usuario. Garantiza que cada usuario tenga como máximo una fila de preferencias.
Reto 2 — Catálogo opcional
Diseña productos que puedan conservarse si se elimina su categoría. Implementa y prueba ON DELETE SET NULL. Explica por qué la clave foránea debe permitir NULL.
Reto 3 — Comparar acciones
Crea tres copias pequeñas del mismo esquema y prueba RESTRICT, CASCADE y SET NULL. Registra qué filas permanecen después de intentar eliminar la fila padre.
Reto 4 — Detectar sobrenormalización
Analiza un diseño que separa nombre, apellido, correo y ciudad en cuatro tablas diferentes. Explica qué separaciones aportan valor y cuáles solo aumentan complejidad.
Videos recomendados del módulo
Video esencial 1
Ejemplo de diseño de una base de datos mediante diagrama entidad-relación — Hernando Moreno A.
Tema exacto: análisis y construcción de un diagrama entidad-relación. Momento recomendado: después de estudiar cardinalidades. Objetivo: observar un proceso completo de diseño antes de escribir SQL.
Video esencial 2
Normalización de bases de datos: 1FN, 2FN y 3FN — Jesús Domínguez Gutú
Tema exacto: normalización mediante primera, segunda y tercera forma normal. Momento recomendado: antes de revisar el diseño de la clínica. Objetivo: reconocer redundancia, dependencias y separación correcta de tablas.
Los videos complementan la práctica. El dominio se demuestra diseñando, implementando y probando las restricciones.
Documentación y recursos de lectura
Nivel esencial
- Claves foráneas en SQLite — documentación oficial
- `CREATE TABLE` y restricciones — documentación oficial de SQLite
- Tipos y afinidad en SQLite — documentación oficial
Cambios del esquema
Ampliación opcional
- Tablas `STRICT` — documentación oficial de SQLite
- Modelo entidad-relación: elementos y ejemplo — iLERNA
- diagrams.net — herramienta gratuita de diagramación
No necesitas memorizar la sintaxis completa de la documentación. Busca la restricción que estás implementando, revisa un ejemplo mínimo y comprueba su comportamiento en una base de práctica.
Glosario
| Término | Significado |
|---|---|
| Acción referencial | Comportamiento definido cuando cambia o se elimina una fila referenciada |
| Anomalía | Problema de inserción, actualización o eliminación provocado por un diseño deficiente |
| Atributo | Propiedad de una entidad; suele convertirse en columna |
| Cardinalidad | Cantidad de ocurrencias que pueden relacionarse |
| Clave candidata | Columna o conjunto que podría identificar cada fila |
| Clave compuesta | Clave formada por más de una columna |
| Clave foránea | Columna que referencia una clave de otra tabla |
| Clave natural | Identificador que ya existe en el dominio real |
| Clave primaria | Identificador elegido para distinguir cada fila |
| Clave sustituta | Identificador creado para uso interno del sistema |
CHECK | Restricción que valida una condición |
DEFAULT | Valor utilizado cuando una inserción omite una columna |
| Diccionario de datos | Documento que explica columnas, tipos, reglas y significado |
| Entidad | Elemento relevante sobre el que se conserva información |
| Integridad referencial | Garantía de que las referencias entre tablas son válidas |
| Modelo conceptual | Representación de entidades y relaciones del problema |
| Modelo físico | Implementación concreta en un motor de base de datos |
| Modelo lógico | Conversión de conceptos en tablas, columnas y claves |
| Normalización | Proceso de organizar tablas para reducir redundancia y anomalías |
NOT NULL | Restricción que impide ausencia de valor |
| Opcionalidad | Indica si una relación o atributo puede estar ausente |
| Regla de negocio | Condición que el sistema debe respetar |
| Tabla hija | Tabla que contiene la clave foránea |
| Tabla intermedia | Tabla que resuelve una relación muchos a muchos |
| Tabla padre | Tabla cuya clave es referenciada |
UNIQUE | Restricción que impide duplicados |
Resumen del módulo
Diseñar una base de datos comienza por comprender el problema. Las entidades representan elementos importantes, los atributos describen sus propiedades y las reglas de negocio determinan qué estructuras y restricciones son necesarias.
Requisitos
↓
Entidades y atributos
↓
Claves y relaciones
↓
Normalización
↓
CREATE TABLE y restricciones
↓
Pruebas válidas e inválidasLas claves primarias identifican filas. Las claves foráneas conectan tablas y protegen la existencia de las referencias. Las relaciones pueden ser uno a uno, uno a muchos o muchos a muchos; estas últimas necesitan una tabla intermedia.
Las restricciones permiten que la base proteja reglas:
PRIMARY KEY
FOREIGN KEY
NOT NULL
UNIQUE
CHECK
DEFAULTEn SQLite debes activar las claves foráneas en cada conexión:
PRAGMA foreign_keys = ON;La normalización práctica evita listas dentro de celdas, dependencias parciales y datos descriptivos repetidos que pertenecen a otras entidades.
Habilidades obtenidas
Ahora puedes:
- Analizar requisitos antes de crear tablas.
- Dibujar un diagrama entidad-relación.
- Elegir claves primarias y naturales.
- Implementar relaciones mediante claves foráneas.
- Resolver relaciones muchos a muchos.
- Aplicar restricciones de integridad.
- Elegir acciones referenciales.
- Detectar anomalías y normalizar hasta 3FN.
- Documentar el modelo mediante un diccionario de datos.
- Probar que la base acepta casos válidos y rechaza casos inválidos.
- Reconocer particularidades de SQLite y conceptos transferibles.
Antes de continuar
Comprueba que puedes explicar y demostrar:
- Por qué no se debe comenzar creando tablas sin analizar requisitos.
- Qué diferencia existe entre entidad y atributo.
- Qué diferencia existe entre clave primaria y clave foránea.
- Dónde se coloca la clave foránea en una relación 1:N.
- Cómo se resuelve una relación N:M.
- Qué ocurre si SQLite no tiene las claves foráneas activas.
- Cuándo utilizar
RESTRICT,CASCADEoSET NULL. - Qué problemas corrigen 1FN, 2FN y 3FN.
- Cómo comprobar que no existen referencias inválidas.
- Cómo reconstruir el proyecto completo desde el script.
No continúes con el Módulo 3 hasta que el proyecto de la clínica haya sido aprobado. El siguiente módulo utilizará estas estructuras para insertar, actualizar y eliminar información mediante procedimientos seguros y transacciones.