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