Sigla en azul →glosario(primera vez: expansión entre paréntesis).
M09 — Bases de datos
Por qué existe
Los datos son el corazón del producto. Un esquema mal modelado te persigue en cada feature; un solo usuario postgres para la app y concatenar SQL son incidentes de seguridad evitables. Esta materia diseña el esquema de Agenda Ops / CRM con SQL real, índices, transacciones y migraciones versionadas.
Seguridad desde el día 1: queries parametrizadas + least privilege (hilo).
En resumen: diseñas el esquema del producto: ER , SQL real, índices y migraciones sin SQL injection .
Objetivos de aprendizaje
Al terminar debes poder:
- Modelar entidades del dominio (cliente, servicio, cita, usuario) en ER y normalizar hasta 3FN con justificación.
- Escribir SQL de joins, agregaciones y subconsultas contra PostgreSQL.
- Leer un plan de ejecución con
EXPLAINy decidir cuándo añadir un índice. - Aplicar transacciones ACID en operaciones multi-paso (p. ej. crear cita + auditoría).
- Versionar el esquema con migraciones reproducibles y seeds de demo.
- Crear un rol de aplicación con permisos mínimos (sin superuser).
Cómo estudiar esta materia (lecciones)
M09 sigue el formato de lecciones cortas y completas (como M01/M06): marcas una a una cuando cumples “Hecho cuando”.
- Abre las lecciones en orden (L01 → L20).
- Cada lección trae objetivo, pasos, lectura y criterio “Hecho cuando”.
- Marca la lección en la UI solo si cumple ese criterio.
- Diseña en papel o diagrama antes de
CREATE TABLE; cada FK debe tener una razón de negocio. - Ejecuta todo contra una BD local (Docker o nativa); no solo leas Elmasri.
- Método general: Cómo estudiar.
Semana tipo (20 h)
| Bloque | Horas | Qué haces |
|---|---|---|
| Modelo ER | 6–8 | Diagrama + normalización (L01–L08) |
| SQL + EXPLAIN | 6–8 | Queries del dominio (L09–L16) |
| Migraciones | 4–6 | Seeds + least privilege (L17–L20) |
| Retro | 1 | Una query lenta explicada |
Si un día solo tienes 2 h: una lección práctica (pasos + evidencia). No saltes la fila de lectura de esa lección.
Lecciones
Semana 1 — Modelo ER y diseño conceptual (~20 h)
| ID | Lección | ~h |
|---|---|---|
| L01 | PostgreSQL local y carpeta de evidencia | 5 |
| L02 | Entidades Cliente, Servicio, Cita | 5 |
| L03 | Cardinalidades y reglas de negocio | 5 |
| L04 | Glosario alineado al dominio | 5 |
Semana 2 — Normalización (~20 h)
| ID | Lección | ~h |
|---|---|---|
| L05 | Primera forma normal y anomalías | 5 |
| L06 | Segunda forma normal | 5 |
| L07 | Tercera forma normal (P1) | 5 |
| L08 | Trade-offs de desnormalización | 5 |
Semana 3 — SQL avanzado (~20 h)
| ID | Lección | ~h |
|---|---|---|
| L09 | Joins inner y left | 5 |
| L10 | Agregaciones y GROUP BY | 5 |
| L11 | Subconsultas y HAVING | 5 |
| L12 | Cinco consultas P2 comentadas | 5 |
Semana 4 — Índices y rendimiento (~20 h)
| ID | Lección | ~h |
|---|---|---|
| L13 | Índices B-tree intro | 5 |
| L14 | EXPLAIN ANALYZE en consultas reales | 5 |
| L15 | Optimizar query lenta de reporte | 5 |
| L16 | Documentar planes de ejecución | 5 |
Semana 5 — Transacciones, migraciones y proyecto (~20 h)
| ID | Lección | ~h |
|---|---|---|
| L17 | Transacciones ACID | 5 |
| L18 | Migraciones versionadas | 5 |
| L19 | Least privilege (P3) | 5 |
| L20 | Reportes, seeds y cierre M09 | 5 |
Empieza por L01 hoy.
Lecturas (mapa rápido)
Canon: Fundamentos de sistemas de bases de datos — Elmasri & Navathe (ed. ES). Alternativa: tutorial PostgreSQL oficial. Ver bibliografía.
| Semana | Lecciones | Capítulos / secciones |
|---|---|---|
| 1 | L01–L04 | Modelo ER + diseño conceptual |
| 2 | L05–L08 | Normalización (1FN–3FN, BCNF intro) |
| 3 | L09–L12 | SQL avanzado (joins, agregaciones, subconsultas) |
| 4 | L13–L16 | Índices, plan de ejecución / EXPLAIN |
| 5 | L17–L20 | Transacciones (ACID) + migraciones + proyecto |
Regla: cada concepto SQL → consulta ejecutada contra tu BD de práctica, no solo lectura.
Ejemplo — query parametrizada (idea)
// Bien: parámetros. Mal: `WHERE id = ${id}` concatenado.
await db.query(
"SELECT * FROM citas WHERE id = $1 AND negocio_id = $2",
[citaId, negocioId]
);
Regla: el identificador de negocio/tenant en el WHERE es autorización, no solo filtro de UI.
Prácticas
- P1 — ER:
er-agenda.mdhasta 3FN — L01–L08. - P2 — SQL:
sql/+explain-notas.md— L09–L16. - P3 — Migraciones:
migrations/+roles.md— L17–L19.
Proyecto útil
Esquema CRM / Agenda Ops con seeds y reportes: todo bajo projects/m09-bases-datos/.
Ya hay un scaffold listo para L01: docker-compose.yml, .env.example, migrations/001_init.sql (clientes / servicios / citas + tenant_id), plantillas er-agenda.md, sql/, seeds/, roles.md, reportes.md.
Tu trabajo:
- Completar ER hasta 3FN y las lecciones L01→L20 (no reescribir el scaffold desde cero).
- Migraciones adicionales (auditoría, índices, rol app) reproducibles en máquina limpia.
- Seeds realistas (clientes, servicios, citas en distintos estados).
- Dos reportes SQL en
reportes.md(pregunta de negocio + query + ejemplo de salida). - README con
docker compose up(o PG nativo) sin secretos en git.
Piensa en M17: tenant_id ya está preparado; no implementes multi-tenant aún.
Errores comunes
- SQL injection por concatenación en el código de aplicación.
- Un solo usuario
postgrespara migraciones y runtime de la app. - Migraciones manuales en producción sin historial en git.
- Índices en todas las columnas “por si acaso” sin medir.
- Olvidar FKs y arreglar integridad solo en la capa de aplicación.
- Marcar lecciones sin cumplir “Hecho cuando”.
Evidencia de hecho
Marca la práctica en la UI solo si existe esto (o equivalente claro):
- P1 — ER:
projects/m09-bases-datos/er-agenda.md(hasta 3FN) enlazado en README. - P2 — SQL:
projects/m09-bases-datos/sql/+explain-notas.md. - P3 — Migraciones:
projects/m09-bases-datos/migrations/+roles.mdcon least privilege demostrable. - Proyecto — Esquema: Seeds +
reportes.mdcon ≥2 reportes útiles.
Criterios de dominio
- Diseñas un esquema nuevo en ~30 min y justificas cada FK.
- Demuestras una query parametrizada y un rol de BD sin superuser.
- Explicas un plan
EXPLAINde una query tuya en lenguaje llano. - Otro dev puede recrear la BD siguiendo solo tu README.