# 📘 Guía práctica: Organización de scripts SQL en Ubuntu (LAMP con MariaDB/MySQL) ## 0) (Opcional) Instalar LAMP con MariaDB Si todavía no tienes tu entorno: ```bash sudo apt update sudo apt install -y apache2 mariadb-server php libapache2-mod-php php-mysql sudo systemctl enable --now mariadb sudo mysql_secure_installation # asegura root, elimina test DB, etc. ``` > Nota: en MariaDB puedes entrar al cliente con `sudo mysql` o `sudo mariadb`. ## 1) Crear base de datos y usuario de trabajo Abre el cliente como root: ```bash sudo mysql ``` En el prompt SQL: ```sql -- Crea la BD (utf8mb4 = Unicode completo) CREATE DATABASE IF NOT EXISTS uni_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; -- Usuario para base de datos CREATE USER IF NOT EXISTS 'dev'@'localhost' IDENTIFIED BY 'Dev.2025!'; -- OJO: Aquí según se requiera puede dar privilegios -- Todos los privilegios para el usuario GRANT ALL ON uni_db.* TO 'dev'@'localhost'; -- Privilegios (no root, sólo lo necesario) GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, ALTER, INDEX ON uni_db.* TO 'dev'@'localhost'; FLUSH PRIVILEGES; EXIT; ``` ## 2) Estructura de carpetas y archivos `/sql` Dentro de tu proyecto: Considera que podría estár en cualquier carpeta, pero, para ser ordenado/a, podría ser recomendable ubicarlos en la carpeta html: `cd /var/www/html` Luego de ello: ```bash cd /var/www/html mkdir -p proyecto/sql cd proyecto/sql touch 01_schema.sql 02_seed.sql 03_queries.sql ``` ## 3) Contenido de ejemplo (Universidad) ### 📂 `01_schema.sql` — Definición de tablas (DDL) ```sql -- 01_schema.sql SET NAMES utf8mb4; SET time_zone = '+00:00'; CREATE DATABASE IF NOT EXISTS uni_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; USE uni_db; -- Tabla STUDENT CREATE TABLE IF NOT EXISTS student ( student_id INT AUTO_INCREMENT PRIMARY KEY, student_code VARCHAR(20) NOT NULL UNIQUE, full_name VARCHAR(100) NOT NULL, email VARCHAR(255) UNIQUE, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ) ENGINE=InnoDB; -- Tabla COURSE CREATE TABLE IF NOT EXISTS course ( course_id INT AUTO_INCREMENT PRIMARY KEY, code VARCHAR(20) NOT NULL UNIQUE, title VARCHAR(120) NOT NULL, credits TINYINT NOT NULL CHECK (credits BETWEEN 1 AND 10) ) ENGINE=InnoDB; -- Relación N:M → ENROLLMENT CREATE TABLE IF NOT EXISTS enrollment ( enrollment_id INT AUTO_INCREMENT PRIMARY KEY, student_id INT NOT NULL, course_id INT NOT NULL, enrolled_at DATETIME DEFAULT CURRENT_TIMESTAMP, CONSTRAINT fk_enr_student FOREIGN KEY (student_id) REFERENCES student(student_id) ON DELETE CASCADE, CONSTRAINT fk_enr_course FOREIGN KEY (course_id) REFERENCES course(course_id) ON DELETE RESTRICT, CONSTRAINT uq_enr UNIQUE (student_id, course_id) ) ENGINE=InnoDB; -- Índice para consultas frecuentes CREATE INDEX idx_enr_course_student ON enrollment (course_id, student_id); ``` ### 📂 `02_seed.sql` — Datos iniciales (DML) ```sql -- 02_seed.sql USE uni_db; START TRANSACTION; -- Estudiantes INSERT INTO student (student_code, full_name, email) VALUES ('S-001','Ana Pérez','[email protected]'), ('S-002','Luis Díaz','[email protected]'), ('S-003','Marta Ríos','[email protected]'); -- Cursos INSERT INTO course (code, title, credits) VALUES ('CS101','Fundamentos de Programación',4), ('DB201','Bases de Datos I',3), ('MA110','Cálculo I',4); -- Matrículas (usando SELECT para obtener IDs) INSERT INTO enrollment (student_id, course_id) SELECT s.student_id, c.course_id FROM student s JOIN course c WHERE s.student_code='S-001' AND c.code='CS101'; INSERT INTO enrollment (student_id, course_id) SELECT s.student_id, c.course_id FROM student s JOIN course c WHERE s.student_code='S-001' AND c.code='DB201'; INSERT INTO enrollment (student_id, course_id) SELECT s.student_id, c.course_id FROM student s JOIN course c WHERE s.student_code='S-002' AND c.code='DB201'; COMMIT; -- Validaciones rápidas SELECT COUNT(*) AS total_students FROM student; SELECT COUNT(*) AS total_courses FROM course; SELECT COUNT(*) AS total_enrollments FROM enrollment; ``` ### 📂 `03_queries.sql` — Consultas representativas ```sql -- 03_queries.sql USE uni_db; -- Q1: Filtrar por nombre SELECT student_id, full_name, email FROM student WHERE full_name LIKE 'Ana%'; -- Q2: JOIN → lista inscripciones con nombre de alumno y curso SELECT e.enrollment_id, s.full_name, c.title, e.enrolled_at FROM enrollment e JOIN student s ON s.student_id = e.student_id JOIN course c ON c.course_id = e.course_id ORDER BY e.enrolled_at DESC; -- Q3: Agregación → número de estudiantes por curso SELECT c.code, c.title, COUNT(*) AS enrolled_students FROM enrollment e JOIN course c ON c.course_id = e.course_id GROUP BY c.course_id, c.code, c.title HAVING COUNT(*) >= 1 ORDER BY enrolled_students DESC; -- Q4: Subconsulta → estudiantes SIN matrícula en DB201 SELECT s.full_name FROM student s WHERE s.student_id NOT IN ( SELECT e.student_id FROM enrollment e JOIN course c ON c.course_id = e.course_id WHERE c.code='DB201' ); -- Q5: Vista de resumen CREATE OR REPLACE VIEW vw_enroll_summary AS SELECT s.student_code, s.full_name, c.code AS course_code, c.title, e.enrolled_at FROM enrollment e JOIN student s ON s.student_id = e.student_id JOIN course c ON c.course_id = e.course_id; -- Consultar la vista SELECT * FROM vw_enroll_summary; ``` ## 4) Ejecutar los scripts en orden ```bash #Ubiquese en en la carpeta de trabajo. cd var/www/html/proyecto/sql # 1) Esquema (DDL) mysql -u root -p < 01_schema.sql # 2) Datos iniciales (DML) mysql -u dev -p --database=uni_db < 02_seed.sql # 3) Consultas y vista mysql -u dev -p --database=uni_db < 03_queries.sql ``` > ⚠️ Recuerda: el **orden importa** → primero el esquema, luego los datos, después las consultas. ## 5) Integración con proyecto LAMP Si tu aplicación web está en `/var/www/html/miapp`, puedes copiar los scripts allí: ```bash sudo mkdir -p /var/www/html/miapp/sql sudo cp var/www/html/proyecto/sql/*.sql /var/www/html/miapp/sql/ sudo chown -R $USER:www-data /var/www/html/miapp/sql sudo chmod -R 750 /var/www/html/miapp/sql ``` > Apache no ejecuta SQL: estos archivos se usan desde la consola o desde tu app PHP. ## 🚀 Consejos finales - **Valida siempre**: después de correr `02_seed.sql`, usa `SELECT COUNT(*)` para comprobar registros. - **Evita sorpresas**: si necesitas rehacer, crea un `00_reset.sql` con `DROP TABLE ...` en orden inverso. - **Documenta**: pon comentarios (`-- ...`) en cada bloque de tus scripts para que sepas qué hace cada parte. - **Engine**: mantén `InnoDB` para soportar claves foráneas y transacciones.