Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 75 additions & 0 deletions resoluciones/maria-montepeque/ejercicio-69/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# Ejercicio 69: DROP Nivel Intermedio

**Nombre:** Maria Jose Montepeque
**Fecha:** 2026-08-21

## Descripcion del problema

Una clinica agenda citas relacionando pacientes con medicos. La lista
de medicos llego en una tabla temporal de importacion que, una vez
migrada a la tabla definitiva, ya no sirve para nada. Ademas, la clinica
necesita entender que pasa si intenta eliminar una tabla (`medicos`) que
todavia tiene citas dependiendo de ella por `FOREIGN KEY`.

## Tablas y relaciones

- `medicos`: catalogo de medicos, tabla definitiva y permanente.
- `pacientes`: catalogo de pacientes.
- `citas`: relaciona un paciente con un medico en una fecha, con un
estado. `pacientes` 1—N `citas`; `medicos` 1—N `citas`.

## Uso de DROP

En `ddl/schema.sql`, despues de crear las 3 tablas y migrar los datos de
medicos desde una tabla temporal de importacion, y de registrar
pacientes y citas:

1. `DROP TABLE medicos_temporal;`: elimina la tabla temporal una vez que
sus datos ya se copiaron a `medicos`. El riesgo real de `DROP` se
explica en un comentario: ejecutarlo antes de migrar los datos
habria perdido esa informacion para siempre.
2. `CREATE VIEW vista_citas_atendidas ...` seguido de
`DROP VIEW vista_citas_atendidas;`: se crea una vista de apoyo para
un reporte puntual y se elimina cuando ya no se va a reutilizar.
`DROP VIEW` no afecta los datos de `citas`, `pacientes` ni `medicos`.

La consulta 5 en `dql/consultas.sql` confirma, consultando
`sqlite_master`, que la tabla temporal y la vista ya no existen,
mientras que los 2 medicos migrados siguen disponibles en `medicos`.

## Otras restricciones aplicadas

- `PRIMARY KEY` autoincremental en las 3 tablas.
- `FOREIGN KEY`: `citas.id_paciente`, `citas.id_medico`.
- `NOT NULL` en todas las columnas obligatorias.
- `UNIQUE`: `medicos.nombre`, `pacientes.telefono`.
- `CHECK`: `citas.estado IN (...)`.
- `DEFAULT` en `citas.estado`.
- `PRAGMA foreign_keys = ON;` activado al inicio del script.

## Caso que falla / no recomendable (comentado en `ddl/schema.sql`)

`DROP TABLE medicos;` falla porque `citas` todavia tiene filas que
dependen de `medicos` por `FOREIGN KEY`, y SQLite (con
`PRAGMA foreign_keys = ON`) no permite eliminar una tabla que sigue
siendo referenciada. Se valido ejecutandolo con Python (`sqlite3`):
lanza `IntegrityError: FOREIGN KEY constraint failed`. Para poder
eliminar `medicos` habria que primero eliminar o reasignar las citas
que dependen de ella (o eliminar `citas` antes que `medicos`).

## Evidencias de ejecucion

Scripts validados en orden (`ddl` -> `inserts` -> `consultas`) con
Python (modulo `sqlite3`), ya que no se tenia el binario `sqlite3`
disponible en el entorno. Detalle completo en
[`evidencias/resultados.md`](evidencias/resultados.md).

- Datos finales: 2 medicos, 4 pacientes, 4 citas.

## Como ejecutar

```bash
sqlite3 ejercicio-69.db < ddl/schema.sql
sqlite3 ejercicio-69.db < dml/inserts.sql
sqlite3 ejercicio-69.db < dql/consultas.sql
```
82 changes: 82 additions & 0 deletions resoluciones/maria-montepeque/ejercicio-69/ddl/schema.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
PRAGMA foreign_keys = ON;

-- Ejercicio 69: DROP Nivel Intermedio
-- Tema central: DROP
-- Contexto: agenda de citas medicas por fecha.

-- Tablas principales, permanentes.
CREATE TABLE medicos (
id_medico INTEGER PRIMARY KEY AUTOINCREMENT,
nombre TEXT NOT NULL UNIQUE,
especialidad TEXT NOT NULL
);

CREATE TABLE pacientes (
id_paciente INTEGER PRIMARY KEY AUTOINCREMENT,
nombre TEXT NOT NULL,
telefono TEXT NOT NULL UNIQUE
);

CREATE TABLE citas (
id_cita INTEGER PRIMARY KEY AUTOINCREMENT,
id_paciente INTEGER NOT NULL,
id_medico INTEGER NOT NULL,
fecha_cita TEXT NOT NULL,
estado TEXT NOT NULL DEFAULT 'programada'
CHECK (estado IN ('programada', 'atendida', 'cancelada')),

FOREIGN KEY (id_paciente) REFERENCES pacientes (id_paciente),
FOREIGN KEY (id_medico) REFERENCES medicos (id_medico)
);

-- Tabla temporal de importacion: la clinica recibio el listado de
-- medicos en un formato plano, sin las restricciones finales, y se uso
-- esta tabla solo para migrar los datos a la tabla definitiva.
CREATE TABLE medicos_temporal (
nombre_bruto TEXT,
especialidad_bruta TEXT
);

INSERT INTO medicos_temporal (nombre_bruto, especialidad_bruta) VALUES
('Dra. Sofia Ramirez', 'Medicina General'),
('Dr. Carlos Perez', 'Pediatria');

INSERT INTO medicos (nombre, especialidad)
SELECT nombre_bruto, especialidad_bruta FROM medicos_temporal;

INSERT INTO pacientes (nombre, telefono) VALUES
('Manuel Estrada', '5555-7001'),
('Alejandra Chinchilla', '5555-7002'),
('Byron Xicay', '5555-7003');

INSERT INTO citas (id_paciente, id_medico, fecha_cita, estado) VALUES
(1, 1, '2026-08-01 09:00', 'atendida'),
(2, 2, '2026-08-01 10:30', 'atendida'),
(3, 1, '2026-08-02 08:00', 'programada');

-- DROP TABLE: la tabla de importacion ya cumplio su proposito (los
-- datos ya viven en `medicos`) y se elimina para no dejar datos
-- duplicados. Este es el riesgo de DROP: si se ejecutara antes de
-- migrar los datos, esa informacion se perderia para siempre.
DROP TABLE medicos_temporal;

-- Vista de apoyo para un reporte puntual de citas ya atendidas...
CREATE VIEW vista_citas_atendidas AS
SELECT c.id_cita, p.nombre AS paciente, m.nombre AS medico, c.fecha_cita
FROM citas c
JOIN pacientes p ON p.id_paciente = c.id_paciente
JOIN medicos m ON m.id_medico = c.id_medico
WHERE c.estado = 'atendida';

-- ...y una vez entregado el reporte, se elimina porque ya no se va a
-- reutilizar. DROP VIEW solo borra la definicion de la vista: los datos
-- de `citas`, `pacientes` y `medicos` siguen intactos.
DROP VIEW vista_citas_atendidas;

-- Caso que debe fallar / no recomendable (queda comentado): intentar
-- eliminar una tabla que todavia esta referenciada por FOREIGN KEY
-- desde otra tabla con filas. SQLite, con PRAGMA foreign_keys = ON, no
-- permite este DROP mientras existan citas que dependan de medicos: hay
-- que eliminar o reasignar esas citas primero (o eliminar la tabla
-- `citas` antes que `medicos`).
-- DROP TABLE medicos;
12 changes: 12 additions & 0 deletions resoluciones/maria-montepeque/ejercicio-69/dml/inserts.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
PRAGMA foreign_keys = ON;

-- Ejercicio 69: DROP Nivel Intermedio
-- Se ejecuta despues de que ddl/schema.sql migro los datos de medicos y
-- elimino la tabla temporal y la vista de apoyo. Aqui solo se agregan
-- registros nuevos directamente a las tablas definitivas.

INSERT INTO pacientes (nombre, telefono) VALUES
('Cristina Barrios', '5555-7004');

INSERT INTO citas (id_paciente, id_medico, fecha_cita, estado) VALUES
(4, 2, '2026-08-03 11:00', 'programada');
40 changes: 40 additions & 0 deletions resoluciones/maria-montepeque/ejercicio-69/dql/consultas.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
.headers on
.mode column

-- Ejercicio 69: DROP Nivel Intermedio
-- Consultas de validacion.

-- 1. Mostrar todos los datos principales (citas con paciente y medico).
SELECT c.id_cita, p.nombre AS paciente, m.nombre AS medico,
c.fecha_cita, c.estado
FROM citas c
JOIN pacientes p ON p.id_paciente = c.id_paciente
JOIN medicos m ON m.id_medico = c.id_medico;

-- 2. Consulta con WHERE: citas ya atendidas.
SELECT id_cita, fecha_cita
FROM citas
WHERE estado = 'atendida';

-- 3. Consulta con ORDER BY: citas ordenadas por fecha.
SELECT id_cita, fecha_cita, estado
FROM citas
ORDER BY fecha_cita;

-- 4. Conteo o resumen: total de citas por estado.
SELECT estado, COUNT(*) AS total
FROM citas
GROUP BY estado;

-- 5. Validacion especifica de DROP: la tabla temporal de medicos y la
-- vista de reporte que se usaron y luego se eliminaron ya no existen en
-- el catalogo de la base de datos, pero los 2 medicos migrados desde la
-- tabla temporal si siguen ahi.
SELECT name, type
FROM sqlite_master
WHERE name IN ('medicos_temporal', 'vista_citas_atendidas');
-- Debe devolver 0 filas: los 2 objetos se eliminaron con DROP.

SELECT nombre, especialidad
FROM medicos;
-- Los 2 medicos migrados desde la tabla temporal siguen disponibles.
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# Evidencias - Ejercicio 69

## Tema

DROP

## Comandos ejecutados

No se conto con el binario `sqlite3` en el entorno de trabajo, por lo que
la ejecucion se valido con Python (`sqlite3`), aplicando los mismos
scripts en el mismo orden:

```bash
sqlite3 ejercicio-69.db < ddl/schema.sql
sqlite3 ejercicio-69.db < dml/inserts.sql
sqlite3 ejercicio-69.db < dql/consultas.sql
```

## Resultados

Estado justo despues de `ddl/schema.sql` (migracion + DROP de tabla
temporal y vista):

```text
medicos: [(1, 'Dra. Sofia Ramirez', 'Medicina General'),
(2, 'Dr. Carlos Perez', 'Pediatria')]

sqlite_master (tabla temporal, vista): [] -- ya no existen
```

Caso que debe fallar (comentado en `ddl/schema.sql`):

```text
DROP TABLE medicos;
Fallo como se esperaba: IntegrityError: FOREIGN KEY constraint failed
```

Estado final (despues de `inserts.sql`), 4 citas en total:

```text
estado total
atendida 2
programada 2
```

Consulta 5 (validacion especifica de DROP):

```text
5a. sqlite_master para los 2 objetos eliminados: sin filas
5b. medicos migrados desde la tabla temporal, siguen disponibles:
('Dra. Sofia Ramirez', 'Medicina General')
('Dr. Carlos Perez', 'Pediatria')
```

## Aprendizaje

Ademas de lo visto en el nivel basico (migrar y luego eliminar una
tabla temporal, o eliminar una vista de apoyo sin afectar los datos),
este ejercicio mostro un limite importante de `DROP` en un modelo con
relaciones: SQLite, con `PRAGMA foreign_keys = ON`, no permite eliminar
una tabla que todavia esta referenciada por `FOREIGN KEY` desde otra
tabla con filas. Esto protege contra dejar datos huerfanos (citas
apuntando a un medico que ya no existe) y obliga a pensar el orden
correcto: eliminar primero las filas o tablas dependientes antes de
eliminar la tabla que referencian.
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# Ejercicio 069: Solicitud de cliente - Diseno 3D Arquitectura

**Nombre:** Maria Jose Montepeque
**Fecha:** 2026-08-21

## Que entendi de la solicitud

El estudio necesita guardar historico porque en auditorias le preguntan
que paso y cuando paso. Se necesita una base de datos que permita
consultar renders y su historial de revisiones, corregir estados,
registrar movimientos y sacar reportes, como saber que proyecto
requirio mas revisiones o cuales estan listos para entrega. El detalle
completo del analisis esta en
[`analisis/requerimiento.md`](analisis/requerimiento.md).

## Tablas y por que se crearon

- `clientes`: catalogo de quien contrata cada proyecto.
- `proyectos`: proyecto de diseno para un cliente.
- `renders`: tabla transaccional; imagen generada para un proyecto.
- `revisiones`: **historico de auditoria**; cada revision de un render
se conserva con su fecha y resultado, nunca se borra.
- `entregas`: version formal del proyecto entregada al cliente.

## Como se relacionan

`clientes` 1—N `proyectos`; `proyectos` 1—N `renders`; `renders` 1—N
`revisiones`; `proyectos` 1—N `entregas`.

## Datos de prueba

3 clientes, 4 proyectos, 9 renders (uno de ellos duplicado por error,
sin revisiones todavia), 12 revisiones y 4 entregas.

## Operaciones (`dml/operaciones.sql`)

- `UPDATE`: un render `'en_proceso'` termina y pasa a `'terminado'`.
- `UPDATE`: se corrige un comentario de revision con error de captura
**sin eliminarlo**, para conservar el historico de auditoria tal
como pidio el cliente.
- `DELETE` controlado (con `WHERE`): se elimina un render duplicado
creado por error, que todavia no tenia ninguna revision asociada.
Este es el unico caso del modelo donde un `DELETE` real es aceptable;
el resto del historico nunca se borra.
- Caso comentado que debe fallar: eliminar un render que ya tiene
revisiones asociadas viola la `FOREIGN KEY` de
`revisiones.id_render`.

## Consultas que responden al cliente

1. Todos los renders con su proyecto y cliente (`JOIN`).
2. Renders filtrados por estado (`en_proceso`, `terminado`,
`descartado`).
3. Ranking de proyectos por numero de revisiones -- el historico de
auditoria (`GROUP BY` + `ORDER BY`).
4. Revisiones ordenadas por fecha, de la mas reciente a la mas antigua.
5. Reporte de decision de negocio: proyectos con renders aprobados,
para saber cuales estan listos para su proxima entrega
(`GROUP BY` + `HAVING`).

## Evidencias de ejecucion

Scripts validados en orden (`ddl` -> `inserts` -> `operaciones` ->
`consultas`) con Python (modulo `sqlite3`), ya que no se tenia el
binario `sqlite3` disponible en el entorno. Detalle completo en
[`evidencias/resultados.md`](evidencias/resultados.md).

- Datos base: 3 clientes, 4 proyectos, 9 renders, 12 revisiones, 4
entregas.
- Tras `operaciones.sql`: 8 renders (se elimino el duplicado sin
historico), render 3 terminado, comentario de revision corregido sin
perder el registro.
- Reporte final: "Casa Vista Verde" es el proyecto con mas renders
aprobados (2).

## Como validar

```bash
sqlite3 ejercicio-069.db < ddl/schema.sql
sqlite3 ejercicio-069.db < dml/inserts.sql
sqlite3 ejercicio-069.db < dml/operaciones.sql
sqlite3 ejercicio-069.db < dql/consultas.sql
```
Loading
Loading