199 lines
8.1 KiB
Markdown
199 lines
8.1 KiB
Markdown
# DI-003: Diseño de Base de Datos
|
|
|
|
**Proyecto:** Sistema de Registro de Estudiantes
|
|
**Fecha:** 2026-01-07
|
|
|
|
---
|
|
|
|
## 1. Modelo Entidad-Relación
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────────────────────┐
|
|
│ PROFESSORS │
|
|
├──────────────┬────────────────┬─────────────────────────────────┤
|
|
│ Id │ INT │ PK, IDENTITY │
|
|
│ Name │ NVARCHAR(100) │ NOT NULL │
|
|
└──────────────┴────────────────┴─────────────────────────────────┘
|
|
│
|
|
│ 1:N (cada profesor → 2 materias)
|
|
▼
|
|
┌─────────────────────────────────────────────────────────────────┐
|
|
│ SUBJECTS │
|
|
├──────────────┬────────────────┬─────────────────────────────────┤
|
|
│ Id │ INT │ PK, IDENTITY │
|
|
│ Name │ NVARCHAR(100) │ NOT NULL │
|
|
│ Credits │ INT │ DEFAULT 3, CHECK (Credits = 3) │
|
|
│ ProfessorId │ INT │ FK → Professors.Id │
|
|
└──────────────┴────────────────┴─────────────────────────────────┘
|
|
│
|
|
│ 1:N
|
|
▼
|
|
┌─────────────────────────────────────────────────────────────────┐
|
|
│ ENROLLMENTS │
|
|
├──────────────┬────────────────┬─────────────────────────────────┤
|
|
│ Id │ INT │ PK, IDENTITY │
|
|
│ StudentId │ INT │ FK → Students.Id │
|
|
│ SubjectId │ INT │ FK → Subjects.Id │
|
|
│ EnrolledAt │ DATETIME2 │ DEFAULT GETUTCDATE() │
|
|
└──────────────┴────────────────┴─────────────────────────────────┘
|
|
▲
|
|
│ 0..3:N
|
|
│
|
|
┌─────────────────────────────────────────────────────────────────┐
|
|
│ STUDENTS │
|
|
├──────────────┬────────────────┬─────────────────────────────────┤
|
|
│ Id │ INT │ PK, IDENTITY │
|
|
│ Name │ NVARCHAR(100) │ NOT NULL │
|
|
│ Email │ NVARCHAR(255) │ NOT NULL, UNIQUE │
|
|
│ RowVersion │ ROWVERSION │ Concurrency control │
|
|
└──────────────┴────────────────┴─────────────────────────────────┘
|
|
```
|
|
|
|
---
|
|
|
|
## 2. Script DDL
|
|
|
|
```sql
|
|
-- Crear base de datos
|
|
CREATE DATABASE StudentEnrollment;
|
|
GO
|
|
|
|
USE StudentEnrollment;
|
|
GO
|
|
|
|
-- Tabla: Professors
|
|
CREATE TABLE Professors (
|
|
Id INT IDENTITY(1,1) PRIMARY KEY,
|
|
Name NVARCHAR(100) NOT NULL
|
|
);
|
|
|
|
-- Tabla: Subjects
|
|
CREATE TABLE Subjects (
|
|
Id INT IDENTITY(1,1) PRIMARY KEY,
|
|
Name NVARCHAR(100) NOT NULL,
|
|
Credits INT NOT NULL DEFAULT 3 CHECK (Credits = 3),
|
|
ProfessorId INT NOT NULL,
|
|
CONSTRAINT FK_Subjects_Professors
|
|
FOREIGN KEY (ProfessorId) REFERENCES Professors(Id)
|
|
);
|
|
|
|
-- Tabla: Students
|
|
CREATE TABLE Students (
|
|
Id INT IDENTITY(1,1) PRIMARY KEY,
|
|
Name NVARCHAR(100) NOT NULL,
|
|
Email NVARCHAR(255) NOT NULL,
|
|
RowVersion ROWVERSION,
|
|
CONSTRAINT UQ_Students_Email UNIQUE (Email)
|
|
);
|
|
|
|
-- Tabla: Enrollments
|
|
CREATE TABLE Enrollments (
|
|
Id INT IDENTITY(1,1) PRIMARY KEY,
|
|
StudentId INT NOT NULL,
|
|
SubjectId INT NOT NULL,
|
|
EnrolledAt DATETIME2 NOT NULL DEFAULT GETUTCDATE(),
|
|
CONSTRAINT FK_Enrollments_Students
|
|
FOREIGN KEY (StudentId) REFERENCES Students(Id) ON DELETE CASCADE,
|
|
CONSTRAINT FK_Enrollments_Subjects
|
|
FOREIGN KEY (SubjectId) REFERENCES Subjects(Id),
|
|
CONSTRAINT UQ_Enrollments_Student_Subject
|
|
UNIQUE (StudentId, SubjectId)
|
|
);
|
|
|
|
-- Índices
|
|
CREATE INDEX IX_Subjects_ProfessorId ON Subjects(ProfessorId);
|
|
CREATE INDEX IX_Enrollments_StudentId ON Enrollments(StudentId);
|
|
CREATE INDEX IX_Enrollments_SubjectId ON Enrollments(SubjectId);
|
|
```
|
|
|
|
---
|
|
|
|
## 3. Datos Iniciales (Seed)
|
|
|
|
```sql
|
|
-- 5 Profesores
|
|
INSERT INTO Professors (Name) VALUES
|
|
('Dr. García'), -- Id: 1
|
|
('Dra. Martínez'), -- Id: 2
|
|
('Dr. López'), -- Id: 3
|
|
('Dra. Rodríguez'), -- Id: 4
|
|
('Dr. Hernández'); -- Id: 5
|
|
|
|
-- 10 Materias (2 por profesor)
|
|
INSERT INTO Subjects (Name, Credits, ProfessorId) VALUES
|
|
('Matemáticas I', 3, 1),
|
|
('Matemáticas II', 3, 1),
|
|
('Física I', 3, 2),
|
|
('Física II', 3, 2),
|
|
('Programación I', 3, 3),
|
|
('Programación II', 3, 3),
|
|
('Base de Datos I', 3, 4),
|
|
('Base de Datos II', 3, 4),
|
|
('Redes I', 3, 5),
|
|
('Redes II', 3, 5);
|
|
```
|
|
|
|
---
|
|
|
|
## 4. Constraints de Negocio
|
|
|
|
| Constraint | Tipo | Descripción |
|
|
|------------|------|-------------|
|
|
| `UQ_Students_Email` | UNIQUE | Email único por estudiante |
|
|
| `UQ_Enrollments_Student_Subject` | UNIQUE | No duplicar inscripción |
|
|
| `CHECK (Credits = 3)` | CHECK | Créditos siempre = 3 |
|
|
| `ON DELETE CASCADE` | FK | Eliminar inscripciones al eliminar estudiante |
|
|
|
|
---
|
|
|
|
## 5. Vistas Útiles
|
|
|
|
```sql
|
|
-- Vista: Compañeros de clase
|
|
CREATE VIEW vw_Classmates AS
|
|
SELECT
|
|
e1.StudentId,
|
|
s.Name AS SubjectName,
|
|
st.Name AS ClassmateName
|
|
FROM Enrollments e1
|
|
INNER JOIN Enrollments e2 ON e1.SubjectId = e2.SubjectId
|
|
AND e1.StudentId != e2.StudentId
|
|
INNER JOIN Subjects s ON e1.SubjectId = s.Id
|
|
INNER JOIN Students st ON e2.StudentId = st.Id;
|
|
|
|
-- Vista: Materias disponibles por estudiante
|
|
CREATE VIEW vw_AvailableSubjects AS
|
|
SELECT
|
|
st.Id AS StudentId,
|
|
su.Id AS SubjectId,
|
|
su.Name AS SubjectName,
|
|
p.Name AS ProfessorName,
|
|
CASE
|
|
WHEN e.Id IS NOT NULL THEN 0 -- Ya inscrito
|
|
WHEN ep.ProfessorId IS NOT NULL THEN 0 -- Mismo profesor
|
|
ELSE 1
|
|
END AS IsAvailable
|
|
FROM Students st
|
|
CROSS JOIN Subjects su
|
|
INNER JOIN Professors p ON su.ProfessorId = p.Id
|
|
LEFT JOIN Enrollments e ON st.Id = e.StudentId AND su.Id = e.SubjectId
|
|
LEFT JOIN (
|
|
SELECT DISTINCT e.StudentId, s.ProfessorId
|
|
FROM Enrollments e
|
|
INNER JOIN Subjects s ON e.SubjectId = s.Id
|
|
) ep ON st.Id = ep.StudentId AND su.ProfessorId = ep.ProfessorId;
|
|
```
|
|
|
|
---
|
|
|
|
## 6. Diccionario de Datos
|
|
|
|
| Tabla | Campo | Tipo | Descripción |
|
|
|-------|-------|------|-------------|
|
|
| Students | Id | INT | Identificador único |
|
|
| Students | Name | NVARCHAR(100) | Nombre completo |
|
|
| Students | Email | NVARCHAR(255) | Correo (único) |
|
|
| Students | RowVersion | ROWVERSION | Control de concurrencia |
|
|
| Subjects | Credits | INT | Siempre 3 |
|
|
| Enrollments | EnrolledAt | DATETIME2 | Fecha de inscripción UTC |
|