academia/docs/entregables/02-diseno/base-datos/DI-003-diseno-base-datos.md

8.1 KiB

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

-- 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)

-- 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

-- 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