├── clase_07 ├── cmd │ ├── alumnos.json │ ├── alumnos.csv │ └── alumnos2.csv ├── alumnos.csv ├── SQL_Clase_07.sql ├── teoria │ ├── importar.md │ ├── diapositivas.md │ └── teoria.md ├── ejercicios │ └── ejercicios.md └── alumnos.json ├── clase_06 ├── ER.mwb ├── ejercicios │ ├── ejercicios.md │ └── soluciones.sql └── README_SQL_DML_Subconsultas.md ├── clase_04 ├── Modelo ER.mwb ├── Modelo ER.mwb.bak ├── Query_Clase_04.sql └── ejercicios │ └── ejercicios.md ├── clase_01 ├── ejercitacion_extra │ └── ejercicios-sql.docx ├── query_01.sql └── resumen.md ├── LICENSE ├── clase_10 ├── backup │ ├── coderhouse_categoria.sql │ ├── coderhouse_cursos_inscripciones_count.sql │ ├── coderhouse_log_inscripciones.sql │ ├── coderhouse_notas.sql │ ├── coderhouse_cursos.sql │ ├── coderhouse_alumnos.sql │ └── coderhouse_inscripciones.sql ├── SQL_Clase_10.sql └── ejercicios │ └── ejercicios.md ├── clase_09 ├── ejercicios │ ├── ejercicios.md │ └── soluciones.md ├── SQL_Clase_09.sql └── teoria │ └── teoria.md ├── clase_05 ├── ejercicios │ ├── ejercicios_sql_sin_resolver.md │ ├── ejercicios_sql_sin_resolver2.md │ └── ejercicios_sql_completos.md ├── teoria │ ├── vistas_sql_clase.md │ └── teoria.md └── Query_Clase_05.sql ├── clase_03 ├── ejercicios │ ├── Ejercicios_extra.md │ └── ejercicios.md ├── SQL_Query_03.sql └── teoria │ └── teoria1.md ├── clase_02 ├── teoria │ ├── temas.md │ └── teoria.md ├── ejercicios │ └── ejercicios.md └── query_clase_02.sql ├── clase_11 ├── ejercicios.md └── teoria.md ├── README.md └── clase_08 ├── ejercicios └── ejercicios.md └── SQL_Clase_08.sql /clase_07/cmd/alumnos.json: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /clase_06/ER.mwb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Drako01/SQL_Flex---75965/HEAD/clase_06/ER.mwb -------------------------------------------------------------------------------- /clase_07/alumnos.csv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Drako01/SQL_Flex---75965/HEAD/clase_07/alumnos.csv -------------------------------------------------------------------------------- /clase_04/Modelo ER.mwb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Drako01/SQL_Flex---75965/HEAD/clase_04/Modelo ER.mwb -------------------------------------------------------------------------------- /clase_07/cmd/alumnos.csv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Drako01/SQL_Flex---75965/HEAD/clase_07/cmd/alumnos.csv -------------------------------------------------------------------------------- /clase_04/Modelo ER.mwb.bak: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Drako01/SQL_Flex---75965/HEAD/clase_04/Modelo ER.mwb.bak -------------------------------------------------------------------------------- /clase_07/cmd/alumnos2.csv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Drako01/SQL_Flex---75965/HEAD/clase_07/cmd/alumnos2.csv -------------------------------------------------------------------------------- /clase_01/ejercitacion_extra/ejercicios-sql.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Drako01/SQL_Flex---75965/HEAD/clase_01/ejercitacion_extra/ejercicios-sql.docx -------------------------------------------------------------------------------- /clase_01/query_01.sql: -------------------------------------------------------------------------------- 1 | CREATE DATABASE IF NOT EXISTS coderhouse; 2 | USE coderhouse; 3 | 4 | CREATE TABLE alumnos ( 5 | id_alumno INT PRIMARY KEY AUTO_INCREMENT NOT NULL, 6 | nombre VARCHAR(30) NOT NULL, 7 | apellido VARCHAR(40) NOT NULL, 8 | email VARCHAR (100) UNIQUE DEFAULT NULL, 9 | dni INT UNIQUE NOT NULL, 10 | telefono VARCHAR (20) UNIQUE DEFAULT NULL, 11 | nacionalidad VARCHAR (30) DEFAULT "Argentina" 12 | ); 13 | 14 | DROP TABLE alumnos; 15 | 16 | INSERT INTO alumnos(nombre, apellido, email, dni, telefono) 17 | VALUES 18 | ("Alejandro", "Di Stefano", "alejandro@mail.com", 22233355, "115555666"); 19 | 20 | SELECT * FROM alumnos; -------------------------------------------------------------------------------- /clase_07/SQL_Clase_07.sql: -------------------------------------------------------------------------------- 1 | CREATE DATABASE IF NOT EXISTS coderhouse3; 2 | USE coderhouse2; 3 | 4 | CREATE TABLE alumnos ( 5 | id_alumno INT PRIMARY KEY AUTO_INCREMENT NOT NULL, 6 | nombre VARCHAR(30) NOT NULL, 7 | apellido VARCHAR(40) NOT NULL, 8 | email VARCHAR (100) UNIQUE DEFAULT NULL, 9 | dni INT UNIQUE NOT NULL, 10 | telefono VARCHAR (20) UNIQUE DEFAULT NULL, 11 | nacionalidad VARCHAR (30) DEFAULT "Argentina", 12 | fecha_inscripcion TIMESTAMP, 13 | instituto VARCHAR (100) DEFAULT NULL, 14 | edad INT NOT NULL 15 | )DEFAULT CHARSET=utf8mb4; 16 | 17 | SET GLOBAL local_infile = 1; 18 | SHOW GLOBAL VARIABLES LIKE "local_infile"; 19 | SHOW VARIABLES LIKE 'secure_file_priv'; 20 | 21 | 22 | LOAD DATA INFILE 'C:/ProgramData/MySQL/MySQL Server 8.0/Uploads/alumnos.csv' 23 | INTO TABLE alumnos 24 | CHARACTER SET utf8mb4 25 | FIELDS TERMINATED BY ',' 26 | OPTIONALLY ENCLOSED BY '"' 27 | LINES TERMINATED BY '\n' 28 | IGNORE 1 LINES; 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 Alejandro Daniel Di Stefano 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /clase_10/backup/coderhouse_categoria.sql: -------------------------------------------------------------------------------- 1 | -- MySQL dump 10.13 Distrib 8.0.41, for Win64 (x86_64) 2 | -- 3 | -- Host: 127.0.0.1 Database: coderhouse 4 | -- ------------------------------------------------------ 5 | -- Server version 8.0.41 6 | 7 | /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; 8 | /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; 9 | /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; 10 | /*!50503 SET NAMES utf8 */; 11 | /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; 12 | /*!40103 SET TIME_ZONE='+00:00' */; 13 | /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; 14 | /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; 15 | /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; 16 | /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; 17 | 18 | -- 19 | -- Table structure for table `categoria` 20 | -- 21 | 22 | DROP TABLE IF EXISTS `categoria`; 23 | /*!40101 SET @saved_cs_client = @@character_set_client */; 24 | /*!50503 SET character_set_client = utf8mb4 */; 25 | CREATE TABLE `categoria` ( 26 | `id_categoria` int NOT NULL AUTO_INCREMENT, 27 | `nombre_categoria` varchar(100) NOT NULL, 28 | PRIMARY KEY (`id_categoria`) 29 | ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; 30 | /*!40101 SET character_set_client = @saved_cs_client */; 31 | 32 | -- 33 | -- Dumping data for table `categoria` 34 | -- 35 | 36 | LOCK TABLES `categoria` WRITE; 37 | /*!40000 ALTER TABLE `categoria` DISABLE KEYS */; 38 | INSERT INTO `categoria` VALUES (1,'Base de Datos'),(2,'Programacion'); 39 | /*!40000 ALTER TABLE `categoria` ENABLE KEYS */; 40 | UNLOCK TABLES; 41 | /*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; 42 | 43 | /*!40101 SET SQL_MODE=@OLD_SQL_MODE */; 44 | /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; 45 | /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; 46 | /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; 47 | /*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; 48 | /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; 49 | /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; 50 | 51 | -- Dump completed on 2025-05-24 12:48:48 52 | -------------------------------------------------------------------------------- /clase_09/ejercicios/ejercicios.md: -------------------------------------------------------------------------------- 1 | # Guía de Ejercicios: Triggers y DCL en MySQL 2 | 3 | ## Parte 1: Triggers 4 | 5 | ### Ejercicio 1 6 | 7 | Cree una tabla llamada `log_estudiantes` para registrar inserciones en la tabla `estudiantes`. 8 | 9 | * Campos: `id_log`, `id_estudiante`, `accion`, `fecha_accion` 10 | * Cree un trigger `AFTER INSERT` que registre en `log_estudiantes` cada vez que se inserta un nuevo estudiante. 11 | 12 | --- 13 | 14 | ### Ejercicio 2 15 | 16 | Cree un trigger `BEFORE DELETE` sobre la tabla `inscripciones` que impida eliminar registros si la fecha de inscripción es anterior al día actual. 17 | 18 | --- 19 | 20 | ### Ejercicio 3 21 | 22 | Implemente un trigger `BEFORE UPDATE` en la tabla `cursos` que registre los cambios de nombre del curso en una tabla `historial_cambios_curso` con los siguientes campos: 23 | 24 | * `id_curso`, `nombre_anterior`, `nombre_nuevo`, `fecha_cambio` 25 | 26 | --- 27 | 28 | ### Ejercicio 4 29 | 30 | Cree un trigger que se dispare `AFTER DELETE` en la tabla `estudiantes` y registre el evento en una tabla de auditoría llamada `auditoria_estudiantes`. 31 | 32 | --- 33 | 34 | ## Parte 2: DCL 35 | 36 | ### Ejercicio 5 37 | 38 | Cree un nuevo usuario `profesor@localhost` con contraseña `educacion123`. 39 | 40 | --- 41 | 42 | ### Ejercicio 6 43 | 44 | Asigne al usuario `profesor` los siguientes permisos sobre la base de datos `institucion`: 45 | 46 | * Permisos de `SELECT` e `INSERT` sobre la tabla `inscripciones` 47 | 48 | --- 49 | 50 | ### Ejercicio 7 51 | 52 | Cree un usuario `auditor@localhost` con permisos sólo de lectura (`SELECT`) sobre todas las tablas de la base de datos `institucion`. 53 | 54 | --- 55 | 56 | ### Ejercicio 8 57 | 58 | Revoque del usuario `profesor` el permiso de insertar en la tabla `cursos`. 59 | 60 | --- 61 | 62 | ### Ejercicio 9 63 | 64 | Utilizando MySQL Workbench, revise los permisos actuales del usuario `profesor` y documente lo que observa. 65 | 66 | --- 67 | 68 | ### Ejercicio 10 69 | 70 | Elimine el usuario `auditor` de la base de datos. 71 | 72 | --- 73 | 74 | ## 🧑‍🏫 Profesor 75 | 76 | 👨‍💻 **Alejandro Daniel Di Stefano** 77 | 📌 **Desarrollador Full Stack** 78 | 🔗 **GitHub:** [Drako01](https://github.com/Drako01) 79 | -------------------------------------------------------------------------------- /clase_05/ejercicios/ejercicios_sql_sin_resolver.md: -------------------------------------------------------------------------------- 1 | 2 | # 🧠 Ejercicios Propuestos de SQL 3 | 4 | 5 | --- 6 | 7 | ## 📌 PARTE 1: Consultas Básicas 8 | 9 | 1. Mostrar todos los datos de la tabla `alumnos`. 10 | 2. Listar todos los cursos ordenados por duración de mayor a menor. 11 | 3. Buscar los alumnos cuyo nombre comience con la letra "A". 12 | 4. Mostrar los primeros 5 cursos más largos. 13 | 5. Obtener los emails únicos de los alumnos. 14 | 15 | --- 16 | 17 | ## 📌 PARTE 2: Funciones de Agregado y Agrupaciones 18 | 19 | 6. Contar cuántos alumnos hay en total. 20 | 7. Calcular la duración promedio de todos los cursos. 21 | 8. Mostrar la cantidad de inscriptos por curso. 22 | 23 | --- 24 | 25 | ## 📌 PARTE 3: Joins y Relaciones 26 | 27 | 9. Obtener el nombre y apellido del alumno junto con el nombre del curso en el que está inscripto. 28 | 10. Listar todos los alumnos que no están inscriptos en ningún curso. 29 | 30 | --- 31 | 32 | ## 📌 PARTE 4: Subconsultas 33 | 34 | 11. Mostrar los cursos que tienen más inscriptos que el promedio general. 35 | 36 | --- 37 | 38 | ## 📌 PARTE 5: Vistas 39 | 40 | 12. Crear una vista que muestre el nombre completo del alumno y el nombre del curso al que está inscripto. 41 | 13. Crear una vista que muestre los alumnos que están inscriptos en más de un curso. 42 | 43 | --- 44 | 45 | ## 📌 PARTE 6: Stored Procedures 46 | 47 | 14. Crear un procedimiento almacenado que devuelva la cantidad de inscripciones por día. 48 | 15. Crear un procedimiento que reciba un `id_curso` y devuelva cuántos alumnos están inscriptos. 49 | 50 | --- 51 | 52 | ## 📌 PARTE 7: Triggers 53 | 54 | 16. Crear un trigger que evite inscripciones duplicadas a un mismo curso por parte del mismo alumno. 55 | 17. Crear un trigger que actualice una tabla con el contador de inscripciones por curso cada vez que se inserta una nueva inscripción. 56 | 57 | --- 58 | 59 | ✏️ **Recomendación**: Intentá resolver cada uno de estos ejercicios antes de ver las posibles soluciones. Consultá la documentación si lo necesitás. ¡La práctica constante es clave para aprender SQL! 60 | 61 | 62 | --- 63 | 64 | 65 | ## 🧑‍🏫 Profesor 66 | 67 | 👨‍💻 **Alejandro Daniel Di Stefano** 68 | 📌 **Desarrollador Full Stack** 69 | 🔗 **GitHub:** [Drako01](https://github.com/Drako01) 70 | -------------------------------------------------------------------------------- /clase_10/backup/coderhouse_cursos_inscripciones_count.sql: -------------------------------------------------------------------------------- 1 | -- MySQL dump 10.13 Distrib 8.0.41, for Win64 (x86_64) 2 | -- 3 | -- Host: 127.0.0.1 Database: coderhouse 4 | -- ------------------------------------------------------ 5 | -- Server version 8.0.41 6 | 7 | /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; 8 | /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; 9 | /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; 10 | /*!50503 SET NAMES utf8 */; 11 | /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; 12 | /*!40103 SET TIME_ZONE='+00:00' */; 13 | /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; 14 | /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; 15 | /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; 16 | /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; 17 | 18 | -- 19 | -- Table structure for table `cursos_inscripciones_count` 20 | -- 21 | 22 | DROP TABLE IF EXISTS `cursos_inscripciones_count`; 23 | /*!40101 SET @saved_cs_client = @@character_set_client */; 24 | /*!50503 SET character_set_client = utf8mb4 */; 25 | CREATE TABLE `cursos_inscripciones_count` ( 26 | `id_curso` int NOT NULL, 27 | `cantidad_inscripciones` int DEFAULT '0', 28 | PRIMARY KEY (`id_curso`), 29 | CONSTRAINT `cursos_inscripciones_count_ibfk_1` FOREIGN KEY (`id_curso`) REFERENCES `cursos` (`id_curso`) 30 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; 31 | /*!40101 SET character_set_client = @saved_cs_client */; 32 | 33 | -- 34 | -- Dumping data for table `cursos_inscripciones_count` 35 | -- 36 | 37 | LOCK TABLES `cursos_inscripciones_count` WRITE; 38 | /*!40000 ALTER TABLE `cursos_inscripciones_count` DISABLE KEYS */; 39 | INSERT INTO `cursos_inscripciones_count` VALUES (2,2),(3,1),(7,1),(12,1); 40 | /*!40000 ALTER TABLE `cursos_inscripciones_count` ENABLE KEYS */; 41 | UNLOCK TABLES; 42 | /*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; 43 | 44 | /*!40101 SET SQL_MODE=@OLD_SQL_MODE */; 45 | /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; 46 | /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; 47 | /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; 48 | /*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; 49 | /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; 50 | /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; 51 | 52 | -- Dump completed on 2025-05-24 12:48:48 53 | -------------------------------------------------------------------------------- /clase_10/backup/coderhouse_log_inscripciones.sql: -------------------------------------------------------------------------------- 1 | -- MySQL dump 10.13 Distrib 8.0.41, for Win64 (x86_64) 2 | -- 3 | -- Host: 127.0.0.1 Database: coderhouse 4 | -- ------------------------------------------------------ 5 | -- Server version 8.0.41 6 | 7 | /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; 8 | /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; 9 | /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; 10 | /*!50503 SET NAMES utf8 */; 11 | /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; 12 | /*!40103 SET TIME_ZONE='+00:00' */; 13 | /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; 14 | /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; 15 | /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; 16 | /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; 17 | 18 | -- 19 | -- Table structure for table `log_inscripciones` 20 | -- 21 | 22 | DROP TABLE IF EXISTS `log_inscripciones`; 23 | /*!40101 SET @saved_cs_client = @@character_set_client */; 24 | /*!50503 SET character_set_client = utf8mb4 */; 25 | CREATE TABLE `log_inscripciones` ( 26 | `id_log` int NOT NULL AUTO_INCREMENT, 27 | `id_alumno` int DEFAULT NULL, 28 | `id_curso` int DEFAULT NULL, 29 | `fecha_inscripcion` datetime DEFAULT NULL, 30 | `log_timestamp` timestamp NULL DEFAULT CURRENT_TIMESTAMP, 31 | PRIMARY KEY (`id_log`) 32 | ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; 33 | /*!40101 SET character_set_client = @saved_cs_client */; 34 | 35 | -- 36 | -- Dumping data for table `log_inscripciones` 37 | -- 38 | 39 | LOCK TABLES `log_inscripciones` WRITE; 40 | /*!40000 ALTER TABLE `log_inscripciones` DISABLE KEYS */; 41 | INSERT INTO `log_inscripciones` VALUES (1,4,12,'2025-04-05 13:22:02','2025-04-05 16:22:02'),(2,4,7,'2025-04-05 13:22:02','2025-04-05 16:22:02'); 42 | /*!40000 ALTER TABLE `log_inscripciones` ENABLE KEYS */; 43 | UNLOCK TABLES; 44 | /*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; 45 | 46 | /*!40101 SET SQL_MODE=@OLD_SQL_MODE */; 47 | /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; 48 | /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; 49 | /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; 50 | /*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; 51 | /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; 52 | /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; 53 | 54 | -- Dump completed on 2025-05-24 12:48:48 55 | -------------------------------------------------------------------------------- /clase_10/backup/coderhouse_notas.sql: -------------------------------------------------------------------------------- 1 | -- MySQL dump 10.13 Distrib 8.0.41, for Win64 (x86_64) 2 | -- 3 | -- Host: 127.0.0.1 Database: coderhouse 4 | -- ------------------------------------------------------ 5 | -- Server version 8.0.41 6 | 7 | /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; 8 | /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; 9 | /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; 10 | /*!50503 SET NAMES utf8 */; 11 | /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; 12 | /*!40103 SET TIME_ZONE='+00:00' */; 13 | /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; 14 | /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; 15 | /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; 16 | /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; 17 | 18 | -- 19 | -- Table structure for table `notas` 20 | -- 21 | 22 | DROP TABLE IF EXISTS `notas`; 23 | /*!40101 SET @saved_cs_client = @@character_set_client */; 24 | /*!50503 SET character_set_client = utf8mb4 */; 25 | CREATE TABLE `notas` ( 26 | `id` int NOT NULL AUTO_INCREMENT, 27 | `alumno_id` int DEFAULT NULL, 28 | `parcial1` decimal(5,2) DEFAULT NULL, 29 | `parcial2` decimal(5,2) DEFAULT NULL, 30 | `final` decimal(5,2) DEFAULT NULL, 31 | `materia` varchar(50) DEFAULT NULL, 32 | PRIMARY KEY (`id`) 33 | ) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; 34 | /*!40101 SET character_set_client = @saved_cs_client */; 35 | 36 | -- 37 | -- Dumping data for table `notas` 38 | -- 39 | 40 | LOCK TABLES `notas` WRITE; 41 | /*!40000 ALTER TABLE `notas` DISABLE KEYS */; 42 | INSERT INTO `notas` VALUES (1,1,7.50,8.00,9.00,NULL),(2,2,5.00,6.50,7.00,NULL),(3,3,9.00,10.00,9.50,NULL),(4,1,7.50,8.00,9.00,NULL),(5,2,5.00,6.50,7.00,NULL),(6,3,9.00,10.00,9.50,NULL),(7,7,7.50,8.00,9.00,'SQL'),(8,8,8.50,8.50,10.00,'SQL'); 43 | /*!40000 ALTER TABLE `notas` ENABLE KEYS */; 44 | UNLOCK TABLES; 45 | /*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; 46 | 47 | /*!40101 SET SQL_MODE=@OLD_SQL_MODE */; 48 | /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; 49 | /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; 50 | /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; 51 | /*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; 52 | /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; 53 | /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; 54 | 55 | -- Dump completed on 2025-05-24 12:48:48 56 | -------------------------------------------------------------------------------- /clase_10/backup/coderhouse_cursos.sql: -------------------------------------------------------------------------------- 1 | -- MySQL dump 10.13 Distrib 8.0.41, for Win64 (x86_64) 2 | -- 3 | -- Host: 127.0.0.1 Database: coderhouse 4 | -- ------------------------------------------------------ 5 | -- Server version 8.0.41 6 | 7 | /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; 8 | /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; 9 | /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; 10 | /*!50503 SET NAMES utf8 */; 11 | /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; 12 | /*!40103 SET TIME_ZONE='+00:00' */; 13 | /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; 14 | /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; 15 | /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; 16 | /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; 17 | 18 | -- 19 | -- Table structure for table `cursos` 20 | -- 21 | 22 | DROP TABLE IF EXISTS `cursos`; 23 | /*!40101 SET @saved_cs_client = @@character_set_client */; 24 | /*!50503 SET character_set_client = utf8mb4 */; 25 | CREATE TABLE `cursos` ( 26 | `id_curso` int NOT NULL AUTO_INCREMENT, 27 | `nombre_curso` varchar(50) NOT NULL, 28 | `duracion_curso` int DEFAULT '20', 29 | `id_categoria` int DEFAULT NULL, 30 | PRIMARY KEY (`id_curso`), 31 | KEY `fk_curso_categoria` (`id_categoria`), 32 | CONSTRAINT `fk_curso_categoria` FOREIGN KEY (`id_categoria`) REFERENCES `categoria` (`id_categoria`) 33 | ) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; 34 | /*!40101 SET character_set_client = @saved_cs_client */; 35 | 36 | -- 37 | -- Dumping data for table `cursos` 38 | -- 39 | 40 | LOCK TABLES `cursos` WRITE; 41 | /*!40000 ALTER TABLE `cursos` DISABLE KEYS */; 42 | INSERT INTO `cursos` VALUES (1,'SQL',20,1),(2,'JavaScript',20,2),(3,'Java',60,2),(4,'HTML',20,2),(5,'Data Analytics',120,1),(6,'React',60,2),(7,'Angular',80,2),(8,'Python',120,2),(9,'SQL nivel Basico',80,1),(10,'SQL nivel Intermedio',60,1),(11,'SQL nivel Avanzado',80,1),(12,'SQL Server',180,1); 43 | /*!40000 ALTER TABLE `cursos` ENABLE KEYS */; 44 | UNLOCK TABLES; 45 | /*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; 46 | 47 | /*!40101 SET SQL_MODE=@OLD_SQL_MODE */; 48 | /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; 49 | /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; 50 | /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; 51 | /*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; 52 | /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; 53 | /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; 54 | 55 | -- Dump completed on 2025-05-24 12:48:48 56 | -------------------------------------------------------------------------------- /clase_04/Query_Clase_04.sql: -------------------------------------------------------------------------------- 1 | USE coderhouse; 2 | 3 | 4 | CREATE INDEX idx_apellido ON alumnos(apellido); 5 | 6 | -- VISTAS 7 | CREATE VIEW view_inscripciones_alumnos AS 8 | SELECT 9 | a.id_alumno, 10 | CONCAT(a.nombre, ' ', a.apellido) AS nombre_completo, 11 | a.email, 12 | c.id_curso, 13 | c.nombre_curso, 14 | i.inscription_at 15 | FROM inscripciones i 16 | JOIN alumnos a ON i.id_alumno = a.id_alumno 17 | JOIN cursos c ON i.id_curso = c.id_curso; 18 | 19 | -- Stored Procedures 20 | DELIMITER // 21 | 22 | CREATE PROCEDURE ObtenerInscripcionesPorDia() 23 | BEGIN 24 | SELECT DATE(inscription_at) AS fecha, 25 | COUNT(*) AS cantidad_inscripciones 26 | FROM inscripciones 27 | GROUP BY fecha 28 | ORDER BY fecha; 29 | END // 30 | 31 | DELIMITER ; 32 | 33 | 34 | CALL ObtenerInscripcionesPorDia(); 35 | 36 | -- Triggers 37 | CREATE TABLE cursos_inscripciones_count ( 38 | id_curso INT PRIMARY KEY, 39 | cantidad_inscripciones INT DEFAULT 0, 40 | FOREIGN KEY (id_curso) REFERENCES cursos(id_curso) 41 | ); 42 | 43 | DELIMITER // 44 | 45 | CREATE TRIGGER after_inscription_insert 46 | AFTER INSERT ON inscripciones 47 | FOR EACH ROW 48 | BEGIN 49 | DECLARE curso_count INT; 50 | SELECT cantidad_inscripciones INTO curso_count 51 | FROM cursos_inscripciones_count 52 | WHERE id_curso = NEW.id_curso; 53 | 54 | -- Validamos si existen los valores 55 | IF curso_count IS NULL THEN 56 | INSERT INTO cursos_inscripciones_count (id_curso, cantidad_inscripciones) 57 | VALUES (NEW.id_curso, 1); 58 | ELSE 59 | UPDATE cursos_inscripciones_count 60 | SET cantidad_inscripciones = cantidad_inscripciones + 1 61 | WHERE id_curso = NEW.id_curso; 62 | END IF; 63 | END // 64 | 65 | DELIMITER ; 66 | 67 | -- Avisar que el Alumno ya se inscribio a un Curso 68 | DELIMITER // 69 | 70 | CREATE TRIGGER before_inscription_insert 71 | BEFORE INSERT ON inscripciones 72 | FOR EACH ROW 73 | BEGIN 74 | DECLARE existe INT; 75 | 76 | SELECT COUNT(*) INTO existe 77 | FROM inscripciones 78 | WHERE id_alumno = NEW.id_alumno AND id_curso = NEW.id_curso; 79 | 80 | -- Si ya existe 81 | IF existe > 0 THEN 82 | SIGNAL SQLSTATE '45000' 83 | SET MESSAGE_TEXT = 'El Alumno ya esta inscripto a este curso'; 84 | END IF; 85 | END // 86 | 87 | DELIMITER ; 88 | 89 | 90 | INSERT INTO inscripciones (id_alumno, id_curso) VALUES 91 | (22,2); 92 | 93 | -- Funciones 94 | DELIMITER // 95 | 96 | CREATE FUNCTION CantidadDeInscriptosCurso(idCurso INT) RETURNS INT 97 | DETERMINISTIC 98 | BEGIN 99 | DECLARE cantidad INT; 100 | 101 | SELECT COUNT(*) INTO cantidad 102 | FROM inscripciones 103 | WHERE id_curso = idCurso; 104 | 105 | RETURN cantidad; 106 | END // 107 | 108 | DELIMITER ; 109 | 110 | -- Llamar a la Funcion 111 | SELECT CantidadDeInscriptosCurso(4); -------------------------------------------------------------------------------- /clase_10/SQL_Clase_10.sql: -------------------------------------------------------------------------------- 1 | -- Transacciones 2 | 3 | -- Podemos hacer esto 4 | 5 | INSERT INTO inscripciones (id_alumno, id_curso) VALUES (4,1); 6 | 7 | DELIMITER // 8 | 9 | CREATE PROCEDURE inscribir_alumnos_seguro(IN p_id_alumno INT, IN p_id_curso INT) 10 | BEGIN 11 | DECLARE existe_alumno INT DEFAULT 0; 12 | DECLARE existe_curso INT DEFAULT 0; 13 | DECLARE existe_inscripcion INT DEFAULT 0; 14 | 15 | -- Validar si existe el Alumno 16 | SELECT COUNT(*) INTO existe_alumno 17 | FROM alumnos 18 | WHERE id_alumno = p_id_alumno; 19 | 20 | -- Validar si existe el Curso 21 | SELECT COUNT(*) INTO existe_curso 22 | FROM cursos 23 | WHERE id_curso = p_id_curso; 24 | 25 | -- Si no existe el Alumno o el Curso, mostramos un mensaje de Error 26 | IF existe_alumno = 0 THEN 27 | SELECT '❌ El Alumno no existe.' AS message; 28 | ELSEIF existe_curso = 0 THEN 29 | SELECT '❌ El Curso no existe.' AS message; 30 | ELSE 31 | SELECT COUNT(*) INTO existe_inscripcion 32 | FROM inscripciones 33 | WHERE id_alumno = p_id_alumno AND id_curso = p_id_curso; 34 | 35 | IF existe_inscripcion > 0 THEN 36 | SELECT '⚠️ El Alumno ya esta Inscripto en este Curso.' AS message; 37 | ELSE 38 | INSERT INTO inscripciones (id_alumno, id_curso) 39 | VALUES (p_id_alumno, p_id_curso); 40 | SELECT '✅ El Alumno esta Inscripto al Curso Correctamente.' AS message; 41 | END IF; 42 | END IF; 43 | END; 44 | // 45 | 46 | DELIMITER ; 47 | /* 48 | START TRANSACTION; 49 | 50 | CALL inscribir_alumnos_seguro(4,3); 51 | CALL inscribir_alumnos_seguro(5,3); 52 | CALL inscribir_alumnos_seguro(7,3); 53 | CALL inscribir_alumnos_seguro(8,3); 54 | CALL inscribir_alumnos_seguro(26,2); 55 | CALL inscribir_alumnos_seguro(28,1); 56 | CALL inscribir_alumnos_seguro(1,1); 57 | 58 | COMMIT; 59 | */ 60 | 61 | SHOW CREATE TABLE inscripciones; 62 | 63 | START TRANSACTION; 64 | INSERT INTO inscripciones (id_alumno, id_curso) VALUES (4,1); 65 | SAVEPOINT paso_1; 66 | 67 | INSERT INTO inscripciones (id_alumno, id_curso) VALUES (20, 1); 68 | SAVEPOINT paso_2; 69 | 70 | INSERT INTO inscripciones (id_alumno, id_curso) VALUES (21,1); 71 | SAVEPOINT paso_3; 72 | 73 | INSERT INTO inscripciones (id_alumno, id_curso) VALUES (23,1); 74 | SAVEPOINT paso_4; 75 | 76 | INSERT INTO inscripciones (id_alumno, id_curso) VALUES (23,99); 77 | ROLLBACK TO paso_4; 78 | 79 | COMMIT; 80 | 81 | -- BackUp (Copia de Seguridad) 82 | 83 | 84 | /* 85 | Comandos por consola 86 | 87 | mysqldump -u usuario -p nombre_base_de_datos > respaldo.sql 88 | 89 | Para Exportar 90 | mysqldump -u root -p coderhouse2 > respaldo_coderhouse2.sql 91 | 92 | Para Importar 93 | mysql -u root -p coderhouse3 < backup.dump.sql 94 | 95 | */ 96 | 97 | /* 98 | Crear archivo .bat para Automatizar Tarea 99 | 100 | Que se llame backup.bat 101 | 102 | 103 | @echo off 104 | set fecha=%date:~10 105 | mysqldump -u root -p coderhouse2 > "C:\backup\respaldo_coderhouse2.sql" 106 | 107 | */ 108 | -------------------------------------------------------------------------------- /clase_09/ejercicios/soluciones.md: -------------------------------------------------------------------------------- 1 | # Soluciones: Triggers y DCL en MySQL 2 | 3 | ## Parte 1: Triggers 4 | 5 | ### Ejercicio 1 6 | 7 | ```sql 8 | CREATE TABLE log_estudiantes ( 9 | id_log INT AUTO_INCREMENT PRIMARY KEY, 10 | id_estudiante INT, 11 | accion VARCHAR(20), 12 | fecha_accion DATETIME 13 | ); 14 | 15 | DELIMITER // 16 | CREATE TRIGGER after_insert_estudiante 17 | AFTER INSERT ON estudiantes 18 | FOR EACH ROW 19 | BEGIN 20 | INSERT INTO log_estudiantes (id_estudiante, accion, fecha_accion) 21 | VALUES (NEW.id_estudiante, 'INSERT', NOW()); 22 | END;// 23 | DELIMITER ; 24 | ``` 25 | 26 | ### Ejercicio 2 27 | 28 | ```sql 29 | DELIMITER // 30 | CREATE TRIGGER before_delete_inscripcion 31 | BEFORE DELETE ON inscripciones 32 | FOR EACH ROW 33 | BEGIN 34 | IF OLD.fecha_inscripcion < CURDATE() THEN 35 | SIGNAL SQLSTATE '45000' 36 | SET MESSAGE_TEXT = 'No se puede eliminar una inscripción anterior a hoy'; 37 | END IF; 38 | END;// 39 | DELIMITER ; 40 | ``` 41 | 42 | ### Ejercicio 3 43 | 44 | ```sql 45 | CREATE TABLE historial_cambios_curso ( 46 | id_curso INT, 47 | nombre_anterior VARCHAR(100), 48 | nombre_nuevo VARCHAR(100), 49 | fecha_cambio DATETIME 50 | ); 51 | 52 | DELIMITER // 53 | CREATE TRIGGER before_update_nombre_curso 54 | BEFORE UPDATE ON cursos 55 | FOR EACH ROW 56 | BEGIN 57 | IF OLD.nombre_curso <> NEW.nombre_curso THEN 58 | INSERT INTO historial_cambios_curso (id_curso, nombre_anterior, nombre_nuevo, fecha_cambio) 59 | VALUES (OLD.id_curso, OLD.nombre_curso, NEW.nombre_curso, NOW()); 60 | END IF; 61 | END;// 62 | DELIMITER ; 63 | ``` 64 | 65 | ### Ejercicio 4 66 | 67 | ```sql 68 | CREATE TABLE auditoria_estudiantes ( 69 | id_auditoria INT AUTO_INCREMENT PRIMARY KEY, 70 | id_estudiante INT, 71 | accion VARCHAR(10), 72 | fecha_accion DATETIME 73 | ); 74 | 75 | DELIMITER // 76 | CREATE TRIGGER after_delete_estudiante 77 | AFTER DELETE ON estudiantes 78 | FOR EACH ROW 79 | BEGIN 80 | INSERT INTO auditoria_estudiantes (id_estudiante, accion, fecha_accion) 81 | VALUES (OLD.id_estudiante, 'DELETE', NOW()); 82 | END;// 83 | DELIMITER ; 84 | ``` 85 | 86 | ## Parte 2: DCL 87 | 88 | ### Ejercicio 5 89 | 90 | ```sql 91 | CREATE USER 'profesor'@'localhost' IDENTIFIED BY 'educacion123'; 92 | ``` 93 | 94 | ### Ejercicio 6 95 | 96 | ```sql 97 | GRANT SELECT, INSERT ON institucion.inscripciones TO 'profesor'@'localhost'; 98 | ``` 99 | 100 | ### Ejercicio 7 101 | 102 | ```sql 103 | CREATE USER 'auditor'@'localhost' IDENTIFIED BY 'auditorpass'; 104 | GRANT SELECT ON institucion.* TO 'auditor'@'localhost'; 105 | ``` 106 | 107 | ### Ejercicio 8 108 | 109 | ```sql 110 | REVOKE INSERT ON institucion.cursos FROM 'profesor'@'localhost'; 111 | ``` 112 | 113 | ### Ejercicio 9 114 | 115 | ```sql 116 | SHOW GRANTS FOR 'profesor'@'localhost'; 117 | ``` 118 | 119 | Esto mostrará una lista de los privilegios asignados al usuario `profesor`. 120 | 121 | ### Ejercicio 10 122 | 123 | ```sql 124 | DROP USER 'auditor'@'localhost'; 125 | ``` 126 | 127 | --- 128 | 129 | ## 🧑‍🏫 Profesor 130 | 131 | 👨‍💻 **Alejandro Daniel Di Stefano** 132 | 📌 **Desarrollador Full Stack** 133 | 🔗 **GitHub:** [Drako01](https://github.com/Drako01) 134 | -------------------------------------------------------------------------------- /clase_03/ejercicios/Ejercicios_extra.md: -------------------------------------------------------------------------------- 1 | # **📌 Ejercicios de SQL - MySQL** 2 | --- 3 | 4 | ## **📌 1. Ejercicios de `JOIN`** 5 | 1️⃣ Obtén una lista de **todos los alumnos con el nombre del curso en el que están inscritos**. 6 | 2️⃣ Muestra **todos los alumnos**, incluyendo aquellos que **no están inscritos en ningún curso**. 7 | 3️⃣ Lista **todos los cursos**, incluyendo aquellos que **no tienen alumnos inscritos**. 8 | 4️⃣ Encuentra **el número total de alumnos en cada curso**. 9 | 5️⃣ Muestra el **nombre del curso y la cantidad de alumnos inscritos**, ordenando de mayor a menor. 10 | 11 | --- 12 | 13 | ## **📌 2. Ejercicios de `LIKE` y `REGEXP`** 14 | 6️⃣ Encuentra **todos los alumnos cuyos nombres comiencen con "J"**. 15 | 7️⃣ Busca los **alumnos cuyo apellido termine en "ez"**. 16 | 8️⃣ Encuentra los **alumnos con un email que termine en "@gmail.com"**. 17 | 9️⃣ Muestra los alumnos **cuyo nombre tiene exactamente 5 letras**. 18 | 🔟 Encuentra los alumnos **cuyo nombre empieza con "A" o "M" y contiene "del" en cualquier parte** usando `REGEXP`. 19 | 1️⃣1️⃣ Busca los alumnos **cuyo nombre NO empiece con "D" o "V"** usando `REGEXP`. 20 | 21 | --- 22 | 23 | ## **📌 3. Ejercicios de Subconsultas (`IN`, `EXISTS`, `NOT IN`)** 24 | 1️⃣2️⃣ Encuentra los alumnos **inscritos en algún curso** utilizando una subconsulta. 25 | 1️⃣3️⃣ Lista los alumnos **que NO están inscritos en ningún curso** usando `NOT IN`. 26 | 1️⃣4️⃣ Encuentra los cursos donde hay **más de 3 alumnos inscritos** usando una subconsulta. 27 | 1️⃣5️⃣ Obtén el **nombre y apellido del alumno más joven**. 28 | 1️⃣6️⃣ Lista los alumnos **que tienen más edad que el promedio de todos los alumnos**. 29 | 30 | --- 31 | 32 | ## **📌 4. Ejercicios de Funciones Escalares** 33 | 1️⃣7️⃣ Convierte **todos los nombres de los alumnos a mayúsculas**. 34 | 1️⃣8️⃣ Muestra la **longitud (cantidad de caracteres) de cada apellido**. 35 | 1️⃣9️⃣ Muestra el **nombre completo del alumno concatenando "nombre" y "apellido"**. 36 | 2️⃣0️⃣ Encuentra el **valor absoluto de la diferencia entre la edad más alta y la más baja**. 37 | 2️⃣1️⃣ Muestra el **promedio de edades de los alumnos**. 38 | 2️⃣2️⃣ Muestra el **año en el que cada alumno se inscribió**. 39 | 40 | --- 41 | 42 | ## **📌 5. Ejercicios de Funciones de Fecha (`NOW()`, `DATEDIFF()`, `DATE_SUB()`)** 43 | 2️⃣3️⃣ Muestra los alumnos que **se inscribieron hace más de 1 año**. 44 | 2️⃣4️⃣ Obtén el **número de días transcurridos desde la inscripción de cada alumno**. 45 | 2️⃣5️⃣ Encuentra los alumnos que **se inscribieron en el último mes**. 46 | 2️⃣6️⃣ Muestra la fecha de inscripción **formateada como "Día/Mes/Año"**. 47 | 2️⃣7️⃣ Encuentra los alumnos que **se inscribieron en 2023**. 48 | 49 | --- 50 | 51 | ## **📌 6. Ejercicios de `ALTER`, `DROP`, `TRUNCATE`, `RENAME`** 52 | 2️⃣8️⃣ Agrega una columna `edad` a la tabla `alumnos`. 53 | 2️⃣9️⃣ Cambia el nombre de la columna `telefono` a `celular`. 54 | 3️⃣0️⃣ Borra la columna `email` de la tabla `alumnos`. 55 | 3️⃣1️⃣ Elimina todos los datos de la tabla `inscripciones`, pero manteniendo su estructura. 56 | 3️⃣2️⃣ Renombra la tabla `alumnos` a `estudiantes`. 57 | 3️⃣3️⃣ Borra completamente la tabla `cursos` de la base de datos. 58 | 59 | --- 60 | 61 | ### 🚀 **¡A practicar SQL!** 62 | Una vez que completes estos ejercicios, intenta aplicarlos en una base de datos real. 63 | 64 | --- 65 | 66 | ## 🧑‍🏫 Profesor 67 | 68 | 👨‍💻 **Alejandro Daniel Di Stefano** 69 | 📌 **Desarrollador Full Stack** 70 | 🔗 **GitHub:** [Drako01](https://github.com/Drako01) 71 | -------------------------------------------------------------------------------- /clase_02/teoria/temas.md: -------------------------------------------------------------------------------- 1 | # Clase 02 - SQL 2 | 3 | 4 | # **📌 Clase #2 - Sentencias y Sublenguajes** 5 | 6 | ## **⏳ Temas a Abordar** 7 | | Sección | Tema| 8 | |---------|------| 9 | | 1 | Introducción a SQL y Sublenguajes | 10 | | 2 | Sentencia `SELECT` | 11 | | 3 | Operadores en SQL | 12 | | 4 | Sentencias complementarias (`INSERT`, `UPDATE`, `DELETE`) | 13 | | 5 | Funciones en SQL | 14 | | 6 | Tipos de intersección en tablas SQL (`JOIN`, `UNION`, etc.) | 15 | | 7 | Ejercicio práctico y dudas | 16 | 17 | --- 18 | 19 | ## **📌 Contenido de la clase** 20 | 21 | ### **1️⃣ Introducción a SQL y Sublenguajes** 22 | 📌 SQL se divide en 4 sublenguajes: 23 | ✅ **DDL (Data Definition Language)** → `CREATE`, `ALTER`, `DROP` 24 | ✅ **DML (Data Manipulation Language)** → `SELECT`, `INSERT`, `UPDATE`, `DELETE` 25 | ✅ **DCL (Data Control Language)** → `GRANT`, `REVOKE` 26 | ✅ **TCL (Transaction Control Language)** → `COMMIT`, `ROLLBACK` 27 | 28 | --- 29 | 30 | ### **2️⃣ Sentencia `SELECT`** 31 | 📌 **Sintaxis básica:** 32 | ```sql 33 | SELECT columna1, columna2 FROM tabla WHERE condición; 34 | ``` 35 | 📌 **Ejemplo:** Obtener todos los alumnos de la tabla `alumnos`: 36 | ```sql 37 | SELECT * FROM alumnos; 38 | ``` 39 | 📌 **Cláusulas importantes:** 40 | ✅ `WHERE` → Filtrar datos 41 | ✅ `ORDER BY` → Ordenar resultados 42 | ✅ `LIMIT` → Limitar cantidad de registros 43 | 44 | --- 45 | 46 | ### **3️⃣ Operadores en SQL** 47 | 📌 **Tipos de operadores:** 48 | ✅ **Aritméticos** (`+`, `-`, `*`, `/`, `%`) 49 | ✅ **Comparación** (`=`, `!=`, `>`, `<`, `>=`, `<=`) 50 | ✅ **Lógicos** (`AND`, `OR`, `NOT`) 51 | 52 | 📌 **Ejemplo:** 53 | ```sql 54 | SELECT * FROM alumnos WHERE nacionalidad = 'Argentina' AND edad >= 18; 55 | ``` 56 | 57 | --- 58 | 59 | ### **4️⃣ Sentencias complementarias (`INSERT`, `UPDATE`, `DELETE`) (20 min)** 60 | 📌 **`INSERT` - Agregar datos:** 61 | ```sql 62 | INSERT INTO alumnos (nombre, apellido, email) VALUES ('Juan', 'Pérez', 'juan@gmail.com'); 63 | ``` 64 | 📌 **`UPDATE` - Modificar datos:** 65 | ```sql 66 | UPDATE alumnos SET email = 'juan.perez@gmail.com' WHERE nombre = 'Juan'; 67 | ``` 68 | 📌 **`DELETE` - Eliminar datos:** 69 | ```sql 70 | DELETE FROM alumnos WHERE nombre = 'Juan'; 71 | ``` 72 | 73 | --- 74 | 75 | ### **5️⃣ Funciones en SQL** 76 | 📌 **Funciones de agregación:** 77 | ✅ `COUNT()` → Cuenta registros 78 | ✅ `SUM()` → Suma valores 79 | ✅ `AVG()` → Promedio 80 | ✅ `MIN()` / `MAX()` → Valor mínimo y máximo 81 | 82 | 📌 **Ejemplo:** 83 | ```sql 84 | SELECT COUNT(*) FROM alumnos WHERE nacionalidad = 'Argentina'; 85 | ``` 86 | 87 | --- 88 | 89 | ### **6️⃣ Tipos de intersección en tablas SQL** 90 | 📌 **Tipos de `JOIN`:** 91 | ✅ `INNER JOIN` → Coincidencias exactas en ambas tablas 92 | ✅ `LEFT JOIN` → Todo de la tabla izquierda + coincidencias 93 | ✅ `RIGHT JOIN` → Todo de la tabla derecha + coincidencias 94 | ✅ `FULL JOIN` → Todos los registros de ambas tablas 95 | 96 | 📌 **Ejemplo:** 97 | ```sql 98 | SELECT alumnos.nombre, pedidos.producto 99 | FROM alumnos 100 | INNER JOIN pedidos ON alumnos.id_alumno = pedidos.id_alumno; 101 | ``` 102 | 103 | --- 104 | 105 | ### **7️⃣ Ejercicio práctico y dudas** 106 | 📌 **Desafíos:** 107 | 1️⃣ Seleccionar todos los alumnos mayores de 20 años. 108 | 2️⃣ Insertar un nuevo pedido en la tabla `pedidos`. 109 | 3️⃣ Hacer un `JOIN` entre `alumnos` y `pedidos`. 110 | 111 | 112 | --- 113 | 114 | ## 🧑‍🏫 Profesor 115 | 116 | 👨‍💻 **Alejandro Daniel Di Stefano** 117 | 📌 **Desarrollador Full Stack** 118 | 🔗 **GitHub:** [Drako01](https://github.com/Drako01) -------------------------------------------------------------------------------- /clase_07/teoria/importar.md: -------------------------------------------------------------------------------- 1 | # 📚 Tutorial: Cómo importar un archivo `.csv` en MySQL Workbench usando `LOAD DATA INFILE` 2 | 3 | --- 4 | 5 | ## 1. Crear la base de datos y la tabla 6 | 7 | Primero, creamos la base de datos (si no existe) y una tabla donde vamos a importar los datos. 8 | 9 | ```sql 10 | CREATE DATABASE IF NOT EXISTS coderhouse2; 11 | USE coderhouse2; 12 | 13 | CREATE TABLE alumnos ( 14 | id_alumno INT PRIMARY KEY AUTO_INCREMENT NOT NULL, 15 | nombre VARCHAR(30) NOT NULL, 16 | apellido VARCHAR(40) NOT NULL, 17 | email VARCHAR(100) UNIQUE DEFAULT NULL, 18 | dni INT UNIQUE NOT NULL, 19 | telefono VARCHAR(20) UNIQUE DEFAULT NULL, 20 | nacionalidad VARCHAR(30) DEFAULT "Argentina", 21 | fecha_inscripcion TIMESTAMP, 22 | instituto VARCHAR(100) DEFAULT NULL, 23 | edad INT NOT NULL 24 | ) DEFAULT CHARSET=utf8mb4; 25 | ``` 26 | 27 | ✅ **Nota:** Siempre usar `DEFAULT CHARSET=utf8mb4` para evitar problemas de caracteres especiales como "ñ", "á", "é", etc. 28 | 29 | --- 30 | 31 | ## 2. Preparar correctamente el archivo `.csv` 32 | 33 | Muy importante: 34 | 35 | - El archivo `.csv` debe estar **codificado en UTF-8** (no ANSI). 36 | - Para verificarlo o convertirlo: 37 | 38 | ### En **Notepad++** 39 | 40 | 1. Abrí el archivo `.csv`. 41 | 2. Ir a menú `Codificación`. 42 | 3. Si dice `ANSI`, hacer clic en: 43 | - `Codificación > Convertir a UTF-8 (sin BOM)`. 44 | 4. Guardar (`Ctrl + S`). 45 | 46 | ✅ Ahora sí tu archivo tiene una codificación correcta. 47 | 48 | --- 49 | 50 | ## 3. Mover el archivo `.csv` a la carpeta correcta 51 | 52 | Por temas de seguridad, **MySQL solo permite importar archivos desde una carpeta especial**. 53 | 54 | Mover el archivo `.csv` a: 55 | 56 | ``` 57 | C:/ProgramData/MySQL/MySQL Server 8.0/Uploads/ 58 | ``` 59 | 60 | ✅ **Importante:** Esta carpeta existe siempre que tengas instalado MySQL Server en Windows. 61 | 62 | --- 63 | 64 | ## 4. Ejecutar el comando `LOAD DATA INFILE` 65 | 66 | Ahora que todo está listo, ejecutamos este comando: 67 | 68 | ```sql 69 | LOAD DATA INFILE 'C:/ProgramData/MySQL/MySQL Server 8.0/Uploads/alumnos.csv' 70 | INTO TABLE alumnos 71 | CHARACTER SET utf8mb4 72 | FIELDS TERMINATED BY ',' 73 | OPTIONALLY ENCLOSED BY '"' 74 | LINES TERMINATED BY '\n' 75 | IGNORE 1 LINES; 76 | ``` 77 | 78 | ✅ **Qué hace cada parte:** 79 | 80 | - `CHARACTER SET utf8mb4`: Le dice a MySQL que los datos vienen en UTF-8 real. 81 | - `FIELDS TERMINATED BY ','`: Cada dato está separado por comas. 82 | - `OPTIONALLY ENCLOSED BY '"'`: Los campos pueden estar entre comillas `"`. 83 | - `LINES TERMINATED BY '\n'`: Cada fila nueva es un salto de línea. 84 | - `IGNORE 1 LINES`: Ignora la primera línea (los encabezados del archivo). 85 | 86 | --- 87 | 88 | ## 5. ¿Errores comunes y cómo solucionarlos? 89 | 90 | | Error | Causa | Solución | 91 | |:---|:---|:---| 92 | | `Error Code: 2068 LOAD DATA LOCAL INFILE file request rejected due to restrictions on access.` | No usar `LOCAL` o configuración de servidor. | Usar `LOAD DATA INFILE` normal y mover archivo a `/Uploads/`. | 93 | | `Error Code: 1290 secure-file-priv` | MySQL no permite importar desde cualquier carpeta. | Mover archivo a `C:/ProgramData/MySQL/MySQL Server 8.0/Uploads/`. | 94 | | `Error Code: 1366 Incorrect string value '\xF1oz'` | Archivo `.csv` en ANSI o mal convertido. | Convertir archivo a UTF-8 real usando Notepad++. | 95 | | `Error Code: 1300 Invalid utf8mb3 character string` | `CHARACTER SET` incorrecto en el comando. | Usar `CHARACTER SET utf8mb4` en el `LOAD DATA INFILE`. | 96 | 97 | --- 98 | 99 | # 🎉 ¡Listo 100 | 101 | --- 102 | 103 | ## 🧑‍🏫 Profesor 104 | 105 | 👨‍💻 **Alejandro Daniel Di Stefano** 106 | 📌 **Desarrollador Full Stack** 107 | 🔗 **GitHub:** [Drako01](https://github.com/Drako01) 108 | -------------------------------------------------------------------------------- /clase_02/teoria/teoria.md: -------------------------------------------------------------------------------- 1 | # 📚 Teoría -Clase 02: Sentencias y Sublenguajes en SQL 2 | 3 | ## **📌 1️⃣ ¿Qué es SQL y sus Sublenguajes?** 4 | SQL (Structured Query Language) es el lenguaje utilizado para manejar bases de datos relacionales. 5 | Se divide en **cuatro sublenguajes principales**: 6 | 7 | ✅ **DDL (Data Definition Language)** → Definir estructuras de datos (`CREATE`, `ALTER`, `DROP`). 8 | ✅ **DML (Data Manipulation Language)** → Manipular datos (`SELECT`, `INSERT`, `UPDATE`, `DELETE`). 9 | ✅ **DCL (Data Control Language)** → Controlar permisos (`GRANT`, `REVOKE`). 10 | ✅ **TCL (Transaction Control Language)** → Manejar transacciones (`COMMIT`, `ROLLBACK`). 11 | 12 | --- 13 | 14 | ## **📌 2️⃣ Sentencia `SELECT`: Cómo consultar datos** 15 | La sentencia `SELECT` permite recuperar información de una base de datos. 16 | 17 | 📌 **Ejemplo básico:** 18 | ```sql 19 | SELECT * FROM alumnos; 20 | ``` 21 | 📌 **Cláusulas más usadas:** 22 | ✅ `WHERE` → Filtrar registros 23 | ✅ `ORDER BY` → Ordenar resultados 24 | ✅ `LIMIT` → Limitar cantidad de registros 25 | 26 | 📌 **Ejemplo filtrando datos:** 27 | ```sql 28 | SELECT nombre, apellido FROM alumnos WHERE nacionalidad = 'Argentina'; 29 | ``` 30 | 31 | --- 32 | 33 | ## **📌 3️⃣ Operadores en SQL** 34 | SQL tiene **tres tipos principales de operadores**: 35 | 36 | ### **🔹 Aritméticos** (`+`, `-`, `*`, `/`, `%`) 37 | 📌 **Ejemplo:** 38 | ```sql 39 | SELECT precio * 1.21 AS precio_con_IVA FROM productos; 40 | ``` 41 | 42 | ### **🔹 Comparación** (`=`, `!=`, `>`, `<`, `>=`, `<=`) 43 | 📌 **Ejemplo:** 44 | ```sql 45 | SELECT * FROM alumnos WHERE edad >= 18; 46 | ``` 47 | 48 | ### **🔹 Lógicos** (`AND`, `OR`, `NOT`) 49 | 📌 **Ejemplo:** 50 | ```sql 51 | SELECT * FROM alumnos WHERE nacionalidad = 'Argentina' AND edad > 18; 52 | ``` 53 | 54 | --- 55 | 56 | ## **📌 4️⃣ Sentencias Complementarias (`INSERT`, `UPDATE`, `DELETE`)** 57 | 58 | ### **🔹 `INSERT` → Agregar datos** 59 | 📌 **Ejemplo:** 60 | ```sql 61 | INSERT INTO alumnos (nombre, apellido, email, dni, telefono, nacionalidad) 62 | VALUES ('Carlos', 'López', 'carlos.lopez@gmail.com', 37845612, '1122334455', 'Chile'); 63 | ``` 64 | 65 | ### **🔹 `UPDATE` → Modificar datos** 66 | 📌 **Ejemplo:** 67 | ```sql 68 | UPDATE alumnos SET email = 'nuevoemail@gmail.com' WHERE nombre = 'Carlos'; 69 | ``` 70 | 71 | ### **🔹 `DELETE` → Eliminar datos** 72 | 📌 **Ejemplo:** 73 | ```sql 74 | DELETE FROM alumnos WHERE nombre = 'Carlos'; 75 | ``` 76 | 77 | --- 78 | 79 | ## **📌 5️⃣ Funciones en SQL** 80 | Las funciones permiten realizar cálculos en los datos. 81 | 82 | ### **🔹 Funciones de Agregación** 83 | ✅ `COUNT()` → Contar registros 84 | ✅ `SUM()` → Sumar valores 85 | ✅ `AVG()` → Promedio 86 | ✅ `MIN()` / `MAX()` → Valor mínimo y máximo 87 | 88 | 📌 **Ejemplo:** 89 | ```sql 90 | SELECT COUNT(*) FROM alumnos WHERE nacionalidad = 'Argentina'; 91 | ``` 92 | 93 | --- 94 | 95 | ## **📌 6️⃣ Tipos de Intersección en Tablas SQL** 96 | Para trabajar con varias tablas, usamos `JOIN`, `UNION` y otras herramientas. 97 | 98 | ### **🔹 Tipos de `JOIN`** 99 | ✅ **`INNER JOIN`** → Coincidencias exactas en ambas tablas 100 | ✅ **`LEFT JOIN`** → Todo de la tabla izquierda + coincidencias 101 | ✅ **`RIGHT JOIN`** → Todo de la tabla derecha + coincidencias 102 | ✅ **`FULL JOIN`** → Todos los registros de ambas tablas 103 | 104 | 📌 **Ejemplo con `INNER JOIN`:** 105 | ```sql 106 | SELECT alumnos.nombre, pedidos.producto 107 | FROM alumnos 108 | INNER JOIN pedidos ON alumnos.id_alumno = pedidos.id_alumno; 109 | ``` 110 | 111 | ### **🔹 `UNION` y `INTERSECT`** 112 | ✅ **`UNION`** → Une los resultados de dos consultas eliminando duplicados. 113 | ✅ **`UNION ALL`** → Une los resultados sin eliminar duplicados. 114 | ✅ **`INTERSECT`** → Muestra solo los datos que están en ambas consultas. 115 | 116 | 📌 **Ejemplo de `UNION`:** 117 | ```sql 118 | SELECT nombre FROM alumnos 119 | UNION 120 | SELECT nombre FROM profesores; 121 | ``` 122 | 123 | --- 124 | 125 | ## 🧑‍🏫 Profesor 126 | 127 | 👨‍💻 **Alejandro Daniel Di Stefano** 128 | 📌 **Desarrollador Full Stack** 129 | 🔗 **GitHub:** [Drako01](https://github.com/Drako01) 130 | -------------------------------------------------------------------------------- /clase_07/teoria/diapositivas.md: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | # Diapositiva 1: Título 4 | **Importación, Exportación e Integridad Referencial en MySQL** 5 | Clase Práctica - 2 horas 6 | 7 | --- 8 | 9 | # Diapositiva 2: Objetivos 10 | 11 | - Importar y exportar datos. 12 | - Trabajar con CSV y JSON. 13 | - Entender la integridad referencial. 14 | - Usar DELETE CASCADE y UPDATE CASCADE. 15 | 16 | --- 17 | 18 | # Diapositiva 3: Exportar Datos 19 | 20 | **Desde Workbench:** 21 | 22 | - Click derecho en base de datos → Export Data. 23 | - Seleccionar "Export to Self-Contained File". 24 | - Guardar `.sql`. 25 | 26 | **Desde consola:** 27 | 28 | ```bash 29 | mysqldump -u usuario -p basededatos > backup.sql 30 | ``` 31 | 32 | --- 33 | 34 | # Diapositiva 4: Importar Datos 35 | 36 | **Desde Workbench:** 37 | 38 | - File → Open SQL Script. 39 | - Ejecutar el archivo `.sql`. 40 | 41 | **Desde consola:** 42 | 43 | ```bash 44 | mysql -u usuario -p basededatos < backup.sql 45 | ``` 46 | 47 | --- 48 | 49 | # Diapositiva 5: Importar CSV en MySQL 50 | 51 | **Desde Workbench:** 52 | 53 | - Table Data Import Wizard. 54 | - Seleccionar archivo CSV. 55 | - Mapear columnas. 56 | 57 | **Importar manualmente:** 58 | 59 | ```sql 60 | LOAD DATA INFILE 'ruta/archivo.csv' 61 | INTO TABLE tabla 62 | FIELDS TERMINATED BY ',' 63 | LINES TERMINATED BY '\n' 64 | IGNORE 1 ROWS; 65 | ``` 66 | 67 | --- 68 | 69 | # Diapositiva 6: Exportar a CSV o JSON 70 | 71 | **Exportar CSV:** 72 | 73 | - Resultado de consulta → Export Resultset → CSV File. 74 | 75 | **Exportar JSON:** 76 | 77 | - Resultado de consulta → Export Resultset → JSON File. 78 | 79 | **Desde consola:** (menos usado) 80 | 81 | --- 82 | 83 | # Diapositiva 7: Integridad Referencial 84 | 85 | **¿Qué es?** 86 | 87 | - Mantener la coherencia entre tablas relacionadas. 88 | - Evitar datos huérfanos (ej: facturas sin cliente). 89 | 90 | **Clave Foránea:** 91 | 92 | ```sql 93 | FOREIGN KEY (campo_hijo) REFERENCES tabla_padre(campo_padre) 94 | ``` 95 | 96 | --- 97 | 98 | # Diapositiva 8: Restricciones de Integridad 99 | 100 | - No permitir valores sin correspondencia. 101 | - Error si insertas un valor que no existe en la tabla padre. 102 | - Protege la base de datos de errores humanos. 103 | 104 | --- 105 | 106 | # Diapositiva 9: ON DELETE CASCADE 107 | 108 | **Definición:** 109 | 110 | - Si eliminas un registro padre, se eliminan los hijos automáticamente. 111 | 112 | **Ejemplo:** 113 | 114 | ```sql 115 | ON DELETE CASCADE 116 | ``` 117 | 118 | **Uso típico:** 119 | 120 | - Eliminar un cliente → eliminar todas sus órdenes. 121 | 122 | --- 123 | 124 | # Diapositiva 10: ON UPDATE CASCADE 125 | 126 | **Definición:** 127 | 128 | - Si cambias el ID en la tabla padre, el cambio se refleja automáticamente en los hijos. 129 | 130 | **Ejemplo:** 131 | 132 | ```sql 133 | ON UPDATE CASCADE 134 | ``` 135 | 136 | **Uso típico:** 137 | 138 | - Actualizar el ID de un producto → actualizar todas las ventas. 139 | 140 | --- 141 | 142 | # Diapositiva 11: Ejemplo Completo 143 | 144 | **Tablas:** 145 | 146 | - `autores` (id_autor, nombre) 147 | - `libros` (id_libro, titulo, id_autor FK) 148 | 149 | **Relación:** 150 | 151 | ```sql 152 | FOREIGN KEY (id_autor) REFERENCES autores(id_autor) 153 | ON DELETE CASCADE 154 | ON UPDATE CASCADE; 155 | ``` 156 | 157 | **Acciones:** 158 | 159 | - Borrar autor = borrar libros. 160 | - Cambiar ID autor = cambiar ID en libros. 161 | 162 | --- 163 | 164 | # Diapositiva 12: Exportación / Importación: Buenas Prácticas 165 | 166 | - Hacer backup antes de cambios grandes. 167 | - Verificar datos después de importar. 168 | - Validar integridad con SELECT. 169 | - Usar nombres claros para archivos. 170 | 171 | --- 172 | 173 | # Diapositiva 13: Ejercicios Prácticos 174 | 175 | - Exportar base completa. 176 | - Crear CSV de productos y cargarlo. 177 | - Crear tablas relacionadas. 178 | - Aplicar DELETE CASCADE y UPDATE CASCADE. 179 | - Hacer backup e importarlo en otra base. 180 | 181 | --- 182 | 183 | # Diapositiva 14: Cierre 184 | 185 | **📊 Hoy aprendimos:** 186 | 187 | - Importar/exportar. 188 | - Manejar CSV/JSON. 189 | - Respetar integridad referencial. 190 | - Trabajar con CASCADE. 191 | 192 | **📢 A practicar mucho!** 193 | ## 🧑‍🏫 Profesor 194 | 195 | 👨‍💻 **Alejandro Daniel Di Stefano** 196 | 📌 **Desarrollador Full Stack** 197 | 🔗 **GitHub:** [Drako01](https://github.com/Drako01) 198 | --- 199 | -------------------------------------------------------------------------------- /clase_07/ejercicios/ejercicios.md: -------------------------------------------------------------------------------- 1 | # Ejercicios de Importación, Exportación e Integridad Referencial en MySQL 2 | 3 | ## 👉 Importación y Exportación de Datos 4 | 5 | 1. Exportar una base de datos completa a un archivo `.sql` usando Workbench. 6 | 2. Exportar solo una tabla específica a un archivo `.sql`. 7 | 3. Importar un archivo `.sql` a una nueva base de datos vacía. 8 | 4. Importar un archivo `.sql` en una base de datos existente. 9 | 5. Exportar datos de una tabla a un archivo CSV usando Workbench. 10 | 6. Importar datos desde un archivo CSV en una tabla vacía. 11 | 7. Corregir errores comunes al importar CSV (ej: delimitadores incorrectos). 12 | 8. Exportar datos de una consulta (resultado) a CSV. 13 | 9. Exportar datos de una tabla a un archivo JSON manualmente. 14 | 10. Crear un archivo JSON de datos y simular su carga en MySQL (parsearlo). 15 | 16 | ## 👉 Trabajo con Archivos CSV y JSON 17 | 18 | 11. Crear un archivo CSV de productos (id, nombre, precio) y cargarlo en MySQL. 19 | 12. Crear un archivo JSON de clientes (id, nombre, email) para usar en simulaciones. 20 | 13. Convertir un archivo Excel a CSV para importarlo en MySQL. 21 | 14. Corregir un CSV que tenga encabezados incorrectos antes de importar. 22 | 15. Importar un CSV que tiene valores NULL representados como `""` (vacío). 23 | 16. Crear un CSV de alumnos con errores (campos mezclados) y corregirlo antes de importar. 24 | 17. Generar un archivo CSV desde datos exportados de MySQL. 25 | 18. Generar un archivo JSON desde datos exportados de MySQL. 26 | 19. Crear y cargar una planilla de pagos de sueldos en CSV en una tabla MySQL. 27 | 20. Crear y cargar una planilla de asistencia de alumnos en CSV en una tabla MySQL. 28 | 29 | ## 👉 Integridad Referencial 30 | 31 | 21. Crear dos tablas relacionadas: autores y libros. 32 | 22. Insertar autores y luego libros asociados correctamente. 33 | 23. Intentar insertar un libro sin autor válido (ver error de integridad referencial). 34 | 24. Crear tablas con claves foráneas correctamente declaradas. 35 | 25. Romper intencionalmente una relación para analizar el error. 36 | 26. Eliminar un autor y ver qué pasa con sus libros (sin CASCADE). 37 | 27. Actualizar el ID de un autor y ver qué pasa en la tabla libros (sin CASCADE). 38 | 39 | ## 👉 Delete Cascade 40 | 41 | 28. Crear tablas `categorias` y `productos` con ON DELETE CASCADE. 42 | 29. Insertar varias categorías y productos asociados. 43 | 30. Borrar una categoría y verificar que los productos se borran automáticamente. 44 | 31. Crear tablas `departamentos` y `empleados` con ON DELETE CASCADE. 45 | 32. Insertar departamentos y empleados. 46 | 33. Eliminar un departamento y observar el comportamiento en empleados. 47 | 34. Crear una restricción de clave foránea con CASCADE manualmente en una tabla ya existente. 48 | 35. Revertir un cambio: eliminar la restricción CASCADE. 49 | 50 | ## 👉 Update Cascade 51 | 52 | 36. Crear tablas `clientes` y `facturas` con ON UPDATE CASCADE. 53 | 37. Insertar clientes y facturas. 54 | 38. Actualizar el ID de un cliente y verificar el cambio automático en facturas. 55 | 39. Modificar una tabla existente para agregar ON UPDATE CASCADE a una clave foránea. 56 | 40. Realizar una prueba de actualización en cascada en un sistema de órdenes y usuarios. 57 | 58 | ## 👉 Ejercicios Combinados 59 | 60 | 41. Exportar una base de datos con tablas relacionadas. 61 | 42. Importar esa base en otra PC o servidor. 62 | 43. Crear una base nueva y restaurar un backup. 63 | 44. Crear CSVs de "inscriptos", "cursos" y "inscripciones" e importarlos. 64 | 45. Crear una tabla `inscripciones` que relacione alumnos y cursos. 65 | 46. Borrar un alumno y verificar que se borran sus inscripciones (DELETE CASCADE). 66 | 47. Actualizar el ID de un curso y verificar que se actualicen las inscripciones (UPDATE CASCADE). 67 | 48. Crear una planilla en CSV con datos erróneos, detectar y corregir antes de importar. 68 | 49. Diseñar una base de datos pequeña que use integridad referencial y realizar pruebas de CASCADE. 69 | 50. Hacer backup de una base de datos y restaurarla en un ambiente nuevo desde consola. 70 | 71 | --- 72 | 73 | # 📚 Recomendación Final 74 | 75 | - Realizar los ejercicios primero en Workbench para familiarizarse. 76 | - Luego repetir en consola para reforzar el manejo básico de terminal. 77 | - Siempre validar los datos importados con `SELECT * FROM tabla;` luego de la carga. 78 | - Usar `SHOW CREATE TABLE tabla;` para confirmar las restricciones y cascadas. 79 | 80 | --- 81 | 82 | ## 🧑‍🏫 Profesor 83 | 84 | 👨‍💻 **Alejandro Daniel Di Stefano** 85 | 📌 **Desarrollador Full Stack** 86 | 🔗 **GitHub:** [Drako01](https://github.com/Drako01) 87 | -------------------------------------------------------------------------------- /clase_02/ejercicios/ejercicios.md: -------------------------------------------------------------------------------- 1 | 2 | # 📝 Ejercicios de SQL - Clase 2 3 | 4 | ## **📌 1️⃣ Sentencia `SELECT`** 5 | 1. Seleccionar todos los registros de la tabla `alumnos`. 6 | ```sql 7 | SELECT * FROM alumnos; 8 | ``` 9 | 2. Seleccionar solo los nombres y apellidos de la tabla `alumnos`. 10 | 3. Seleccionar los alumnos que sean de Argentina. 11 | 4. Seleccionar los alumnos que tengan un `email` registrado (no `NULL`). 12 | 5. Seleccionar los alumnos mayores de 18 años. 13 | 14 | ## **📌 2️⃣ Uso de `WHERE` y Operadores** 15 | 6. Seleccionar los alumnos cuyo nombre comience con "J". 16 | 7. Seleccionar los alumnos cuyo `dni` sea mayor a 30.000.000. 17 | 8. Seleccionar los alumnos que no tengan `telefono` registrado. 18 | 9. Seleccionar los alumnos que sean de Argentina o Uruguay. 19 | 10. Seleccionar los alumnos que no sean de Argentina ni de Uruguay. 20 | 21 | ## **📌 3️⃣ Uso de `ORDER BY` y `LIMIT`** 22 | 11. Seleccionar los alumnos y ordenarlos por apellido en orden ascendente. 23 | 12. Seleccionar los alumnos y ordenarlos por `dni` en orden descendente. 24 | 13. Seleccionar los 5 primeros alumnos registrados en la tabla. 25 | 14. Seleccionar el alumno con el `dni` más alto. 26 | 15. Seleccionar los últimos 3 alumnos registrados. 27 | 28 | ## **📌 4️⃣ Uso de `INSERT`** 29 | 16. Insertar un nuevo alumno en la tabla `alumnos`. 30 | ```sql 31 | INSERT INTO alumnos (nombre, apellido, email, dni, telefono, nacionalidad) 32 | VALUES ('Carlos', 'López', 'carlos.lopez@gmail.com', 37845612, '1122334455', 'Chile'); 33 | ``` 34 | 17. Insertar dos alumnos nuevos en la misma consulta. 35 | 18. Insertar un alumno sin especificar `telefono`. 36 | 19. Insertar un alumno sin especificar `email`. 37 | 20. Insertar un alumno con `nacionalidad` diferente a Argentina. 38 | 39 | ## **📌 5️⃣ Uso de `UPDATE`** 40 | 21. Cambiar el `email` de un alumno con `id_alumno = 2`. 41 | 22. Modificar la `nacionalidad` de todos los alumnos de Chile a Perú. 42 | 23. Cambiar el `telefono` de un alumno específico. 43 | 24. Modificar el `apellido` de un alumno cuyo nombre sea "María". 44 | 25. Aumentar en 1 el `dni` de todos los alumnos que sean de Argentina. 45 | 46 | ## **📌 6️⃣ Uso de `DELETE`** 47 | 26. Eliminar un alumno cuyo `id_alumno = 5`. 48 | 27. Eliminar todos los alumnos de Uruguay. 49 | 28. Eliminar a los alumnos que no tengan `email` registrado. 50 | 29. Eliminar todos los alumnos cuyo `telefono` sea `NULL`. 51 | 30. Eliminar un alumno con `dni` menor a 30.000.000. 52 | 53 | ## **📌 7️⃣ Funciones de Agregación (`COUNT`, `SUM`, `AVG`, `MIN`, `MAX`)** 54 | 31. Contar cuántos alumnos hay en la tabla. 55 | 32. Contar cuántos alumnos tienen `telefono` registrado. 56 | 33. Obtener el `dni` más alto registrado en la tabla. 57 | 34. Obtener el `dni` más bajo registrado en la tabla. 58 | 35. Obtener la cantidad de alumnos por cada `nacionalidad`. 59 | 60 | ## **📌 8️⃣ Uso de `GROUP BY` y `HAVING`** 61 | 36. Obtener el número de alumnos por nacionalidad. 62 | 37. Contar cuántos alumnos tienen el mismo `apellido`. 63 | 38. Obtener la cantidad de alumnos con `email` registrado y agrupar por nacionalidad. 64 | 39. Seleccionar nacionalidades con más de 2 alumnos registrados. 65 | 40. Obtener el promedio de `dni` de los alumnos por nacionalidad. 66 | 67 | ## **📌 9️⃣ Uso de `JOIN`** 68 | 41. Seleccionar todos los pedidos y los nombres de los alumnos que los hicieron. 69 | ```sql 70 | SELECT alumnos.nombre, pedidos.producto 71 | FROM alumnos 72 | INNER JOIN pedidos ON alumnos.id_alumno = pedidos.id_alumno; 73 | ``` 74 | 42. Hacer un `LEFT JOIN` entre `alumnos` y `pedidos`. 75 | 43. Hacer un `RIGHT JOIN` entre `alumnos` y `pedidos`. 76 | 44. Seleccionar solo los alumnos que no han hecho pedidos (`LEFT JOIN` con `NULL`). 77 | 45. Contar cuántos pedidos ha hecho cada alumno. 78 | 79 | ## **📌 🔟 Uso de `UNION` y `INTERSECT`** 80 | 46. Unir los resultados de `alumnos` y `profesores` en una sola consulta. 81 | 47. Obtener los `email` que aparecen tanto en `alumnos` como en `profesores`. 82 | 48. Obtener los `dni` que aparecen en ambas tablas. 83 | 49. Unir los alumnos de Argentina y Uruguay en una misma consulta. 84 | 50. Seleccionar solo los alumnos que han hecho pedidos y unirlo con una lista de profesores que también han hecho pedidos. 85 | 86 | --- 87 | 88 | 📌 **¡Practiquen estos ejercicios para fortalecer sus conocimientos en SQL! 🚀** 89 | 90 | 91 | --- 92 | 93 | ## 🧑‍🏫 Profesor 94 | 95 | 👨‍💻 **Alejandro Daniel Di Stefano** 96 | 📌 **Desarrollador Full Stack** 97 | 🔗 **GitHub:** [Drako01](https://github.com/Drako01) 98 | 99 | -------------------------------------------------------------------------------- /clase_05/teoria/vistas_sql_clase.md: -------------------------------------------------------------------------------- 1 | 2 | # 📘 Ejemplos de Vistas en SQL 3 | 4 | A continuación te muestro varios ejemplos prácticos de cómo crear vistas en SQL usando un sistema de cursos con tablas como `alumnos`, `cursos` e `inscripciones`. 5 | 6 | --- 7 | 8 | ## 1. 🧾 Vista básica de Alumnos 9 | 10 | Muestra los datos más importantes de cada alumno. 11 | 12 | ```sql 13 | CREATE VIEW vista_alumnos_basico AS 14 | SELECT 15 | id_alumno, 16 | nombre, 17 | apellido, 18 | email 19 | FROM alumnos; 20 | ``` 21 | 22 | --- 23 | 24 | ## 2. 👨‍🎓 Vista Alumnos + Cursos 25 | 26 | Relaciona cada alumno con el curso en el que está inscripto. 27 | 28 | ```sql 29 | CREATE VIEW vista_alumnos_cursos AS 30 | SELECT 31 | a.id_alumno, 32 | CONCAT(a.nombre, ' ', a.apellido) AS nombre_completo, 33 | c.nombre_curso 34 | FROM inscripciones i 35 | JOIN alumnos a ON i.id_alumno = a.id_alumno 36 | JOIN cursos c ON i.id_curso = c.id_curso; 37 | ``` 38 | 39 | --- 40 | 41 | ## 3. 🎯 Vista con Filtro - Curso "SQL Avanzado" 42 | 43 | Muestra solo los alumnos inscriptos al curso "SQL Avanzado". 44 | 45 | ```sql 46 | CREATE VIEW vista_inscriptos_sql AS 47 | SELECT 48 | a.nombre, 49 | a.apellido, 50 | c.nombre_curso 51 | FROM inscripciones i 52 | JOIN alumnos a ON i.id_alumno = a.id_alumno 53 | JOIN cursos c ON i.id_curso = c.id_curso 54 | WHERE c.nombre_curso = 'SQL Avanzado'; 55 | ``` 56 | 57 | --- 58 | 59 | ## 4. 📊 Vista con Agregado - Cantidad de inscriptos por curso 60 | 61 | Cuenta cuántos alumnos hay por curso. 62 | 63 | ```sql 64 | CREATE VIEW vista_cantidad_inscripciones AS 65 | SELECT 66 | c.id_curso, 67 | c.nombre_curso, 68 | COUNT(i.id_alumno) AS cantidad_inscriptos 69 | FROM cursos c 70 | LEFT JOIN inscripciones i ON c.id_curso = i.id_curso 71 | GROUP BY c.id_curso, c.nombre_curso; 72 | ``` 73 | 74 | --- 75 | 76 | ## 5. 🕒 Vista de Inscripciones recientes (últimos 7 días) 77 | 78 | Muestra las inscripciones que ocurrieron en la última semana. 79 | 80 | ```sql 81 | CREATE VIEW vista_inscripciones_recientes AS 82 | SELECT 83 | a.nombre, 84 | a.apellido, 85 | c.nombre_curso, 86 | i.inscription_at 87 | FROM inscripciones i 88 | JOIN alumnos a ON i.id_alumno = a.id_alumno 89 | JOIN cursos c ON i.id_curso = c.id_curso 90 | WHERE i.inscription_at >= CURDATE() - INTERVAL 7 DAY; 91 | ``` 92 | 93 | --- 94 | 95 | ## 6. 📑 Vista de Detalle completo (ordenado por fecha) 96 | 97 | Incluye todos los datos relevantes de la inscripción, ordenados por fecha. 98 | 99 | ```sql 100 | CREATE VIEW vista_detalle_inscripciones AS 101 | SELECT 102 | i.id_inscripcion, 103 | a.nombre, 104 | a.apellido, 105 | a.email, 106 | c.nombre_curso, 107 | c.duracion, 108 | i.inscription_at 109 | FROM inscripciones i 110 | JOIN alumnos a ON i.id_alumno = a.id_alumno 111 | JOIN cursos c ON i.id_curso = c.id_curso 112 | ORDER BY i.inscription_at DESC; 113 | ``` 114 | 115 | --- 116 | 117 | ## 7. 🕵️ Vista anonimizada (sin mostrar email) 118 | 119 | Muestra solo el nombre inicial y apellido, ocultando el email. 120 | 121 | ```sql 122 | CREATE VIEW vista_anonima_alumnos AS 123 | SELECT 124 | id_alumno, 125 | CONCAT(SUBSTRING(nombre,1,1), '. ', apellido) AS nombre_visible 126 | FROM alumnos; 127 | ``` 128 | 129 | --- 130 | 131 | ## 8. 🎓 Vista de alumnos en más de un curso 132 | 133 | Muestra alumnos que están inscriptos en **más de un curso**. 134 | 135 | ```sql 136 | CREATE VIEW vista_alumnos_multicurso AS 137 | SELECT 138 | a.id_alumno, 139 | CONCAT(a.nombre, ' ', a.apellido) AS nombre_completo, 140 | COUNT(i.id_curso) AS cantidad_cursos 141 | FROM alumnos a 142 | JOIN inscripciones i ON a.id_alumno = i.id_alumno 143 | GROUP BY a.id_alumno 144 | HAVING cantidad_cursos > 1; 145 | ``` 146 | 147 | --- 148 | 149 | ## ♻️ Reemplazar una vista con `OR REPLACE` 150 | 151 | Permite actualizar el contenido de una vista sin eliminarla previamente. 152 | 153 | ```sql 154 | CREATE OR REPLACE VIEW vista_alumnos_basico AS 155 | SELECT 156 | id_alumno, 157 | nombre, 158 | apellido, 159 | email 160 | FROM alumnos; 161 | ``` 162 | 163 | --- 164 | 165 | ## ❌ Eliminar una vista 166 | 167 | ```sql 168 | DROP VIEW vista_alumnos_cursos; 169 | ``` 170 | 171 | --- 172 | 173 | ✅ **TIP**: Las vistas se pueden usar como tablas normales. Por ejemplo: 174 | 175 | ```sql 176 | SELECT * FROM vista_cantidad_inscripciones; 177 | ``` 178 | 179 | --- 180 | 181 | 182 | ## 🧑‍🏫 Profesor 183 | 184 | 👨‍💻 **Alejandro Daniel Di Stefano** 185 | 📌 **Desarrollador Full Stack** 186 | 🔗 **GitHub:** [Drako01](https://github.com/Drako01) 187 | -------------------------------------------------------------------------------- /clase_05/ejercicios/ejercicios_sql_sin_resolver2.md: -------------------------------------------------------------------------------- 1 | # 📘 Ejercicios Adicionales de SQL (Lote 2 - sin resolución) 2 | 3 | A continuación se presentan 50 nuevos ejercicios prácticos para reforzar conceptos clave de SQL. 4 | 5 | --- 6 | 7 | ## 🔹 Consultas Básicas y WHERE 8 | 9 | 1. Mostrar todos los cursos que duren más de 20 horas. 10 | 2. Listar los alumnos cuyo apellido contenga la letra “z”. 11 | 3. Mostrar todos los cursos cuyo nombre termine en “SQL”. 12 | 4. Listar los alumnos con emails que pertenezcan al dominio “gmail.com”. 13 | 5. Mostrar los primeros 3 cursos en orden alfabético. 14 | 6. Listar los alumnos cuyo nombre tenga exactamente 5 letras. 15 | 7. Mostrar los cursos cuya duración sea entre 10 y 30 horas. 16 | 8. Mostrar los alumnos que no tienen apellido registrado. 17 | 9. Contar cuántos cursos tienen una duración menor al promedio general. 18 | 10. Mostrar los cursos donde el nombre incluya la palabra “avanzado”. 19 | 20 | --- 21 | 22 | ## 🔹 Funciones de Agregado y Agrupamiento 23 | 24 | 11. Obtener el promedio de duración de los cursos por categoría. 25 | 12. Mostrar la cantidad de alumnos por apellido. 26 | 13. Mostrar la categoría con más cursos asociados. 27 | 14. Listar los cursos agrupados por duración. 28 | 15. Calcular el total de inscripciones por mes. 29 | 30 | --- 31 | 32 | ## 🔹 JOIN y relaciones entre tablas 33 | 34 | 16. Mostrar el nombre del curso y los nombres de alumnos inscriptos. 35 | 17. Listar las fechas de inscripción de los alumnos junto con el nombre del curso. 36 | 18. Mostrar los cursos que no tienen inscripciones. 37 | 19. Listar todos los alumnos y sus respectivos cursos (aunque no estén inscriptos). 38 | 20. Mostrar los nombres completos de los alumnos y la duración del curso al que se inscribieron. 39 | 40 | --- 41 | 42 | ## 🔹 Subconsultas y expresiones 43 | 44 | 21. Mostrar los cursos que tengan más inscriptos que el curso “MySQL Básico”. 45 | 22. Listar los alumnos con más inscripciones que el promedio. 46 | 23. Mostrar los cursos que tienen la misma duración que el curso con más duración. 47 | 24. Listar los emails de los alumnos inscriptos en más de un curso. 48 | 25. Mostrar los cursos que no aparecen en la tabla de inscripciones. 49 | 50 | --- 51 | 52 | ## 🔹 Vistas 53 | 54 | 26. Crear una vista que contenga el nombre completo del alumno y el nombre del curso. 55 | 27. Crear una vista que muestre alumnos que cursan más de 2 cursos. 56 | 28. Crear una vista que muestre las últimas 10 inscripciones ordenadas por fecha. 57 | 29. Crear una vista con los cursos que tienen más de 5 alumnos. 58 | 30. Crear una vista que oculte los emails de los alumnos (anonimización). 59 | 60 | --- 61 | 62 | ## 🔹 Stored Procedures 63 | 64 | 31. Crear un procedimiento que reciba un ID de curso y devuelva todos los alumnos inscriptos. 65 | 32. Crear un procedimiento que inserte una nueva inscripción (recibiendo alumno y curso). 66 | 33. Crear un procedimiento que borre todas las inscripciones de un alumno específico. 67 | 34. Crear un procedimiento que devuelva la duración total de todos los cursos que cursa un alumno. 68 | 35. Crear un procedimiento que muestre las inscripciones del día actual. 69 | 70 | --- 71 | 72 | ## 🔹 Triggers 73 | 74 | 36. Crear un trigger que impida inscribir a un alumno dos veces en el mismo curso. 75 | 37. Crear un trigger que registre en un log cada vez que un alumno se inscribe. 76 | 38. Crear un trigger que actualice un contador de inscriptos por curso. 77 | 39. Crear un trigger que evite borrar un curso si tiene alumnos inscriptos. 78 | 40. Crear un trigger que registre la fecha de modificación de una inscripción. 79 | 80 | --- 81 | 82 | ## 🔹 Bonus: Consultas avanzadas y combinadas 83 | 84 | 41. Listar los cursos junto con la cantidad de alumnos, ordenado de mayor a menor. 85 | 42. Mostrar los cursos con la menor cantidad de inscriptos. 86 | 43. Mostrar qué alumnos comparten curso con un alumno específico. 87 | 44. Crear una vista que contenga alumnos, curso e institución. 88 | 45. Listar los alumnos que no cursan en ninguna institución. 89 | 46. Mostrar la institución con más alumnos inscriptos. 90 | 47. Crear un procedimiento que devuelva inscripciones por institución. 91 | 48. Mostrar el porcentaje de alumnos que cursan más de un curso. 92 | 49. Crear una vista que combine alumnos, cursos y categorías. 93 | 50. Crear un trigger que impida registrar un curso con nombre duplicado. 94 | 95 | --- 96 | 97 | 📚 Estos ejercicios te ayudarán a reforzar todo lo aprendido. ¡No te olvides de probarlos en un entorno real! 98 | """ 99 | 100 | --- 101 | 102 | ## 🧑‍🏫 Profesor 103 | 104 | 👨‍💻 **Alejandro Daniel Di Stefano** 105 | 📌 **Desarrollador Full Stack** 106 | 🔗 **GitHub:** [Drako01](https://github.com/Drako01) 107 | -------------------------------------------------------------------------------- /clase_10/backup/coderhouse_alumnos.sql: -------------------------------------------------------------------------------- 1 | -- MySQL dump 10.13 Distrib 8.0.41, for Win64 (x86_64) 2 | -- 3 | -- Host: 127.0.0.1 Database: coderhouse 4 | -- ------------------------------------------------------ 5 | -- Server version 8.0.41 6 | 7 | /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; 8 | /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; 9 | /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; 10 | /*!50503 SET NAMES utf8 */; 11 | /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; 12 | /*!40103 SET TIME_ZONE='+00:00' */; 13 | /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; 14 | /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; 15 | /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; 16 | /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; 17 | 18 | -- 19 | -- Table structure for table `alumnos` 20 | -- 21 | 22 | DROP TABLE IF EXISTS `alumnos`; 23 | /*!40101 SET @saved_cs_client = @@character_set_client */; 24 | /*!50503 SET character_set_client = utf8mb4 */; 25 | CREATE TABLE `alumnos` ( 26 | `id_alumno` int NOT NULL AUTO_INCREMENT, 27 | `nombre` varchar(30) NOT NULL, 28 | `apellido` varchar(40) NOT NULL, 29 | `email` varchar(100) DEFAULT NULL, 30 | `dni` int NOT NULL, 31 | `telefono` varchar(20) DEFAULT NULL, 32 | `nacionalidad` varchar(30) DEFAULT 'Argentina', 33 | `fecha_inscripcion` datetime DEFAULT CURRENT_TIMESTAMP, 34 | `instituto` varchar(60) DEFAULT 'CoderHouse', 35 | `edad` int DEFAULT NULL, 36 | PRIMARY KEY (`id_alumno`), 37 | UNIQUE KEY `dni` (`dni`), 38 | UNIQUE KEY `email` (`email`), 39 | UNIQUE KEY `telefono` (`telefono`), 40 | KEY `idx_apellido` (`apellido`) 41 | ) ENGINE=InnoDB AUTO_INCREMENT=32 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; 42 | /*!40101 SET character_set_client = @saved_cs_client */; 43 | 44 | -- 45 | -- Dumping data for table `alumnos` 46 | -- 47 | 48 | LOCK TABLES `alumnos` WRITE; 49 | /*!40000 ALTER TABLE `alumnos` DISABLE KEYS */; 50 | INSERT INTO `alumnos` VALUES (4,'Alejandro','Di Stefano','nuevoemaildealejandro@mail.com',22233355,'115555666','Argentina','2025-03-15 12:43:04','CoderHouse',49),(5,'Juan','Perez','perez@mail.com',113333666,'1166667777','Argentina','2025-03-15 12:43:04','CoderHouse',30),(7,'Marcela','Muñoz','ivana@mail.com',33555888,'1166333777','Argentina','2025-03-15 12:52:35','CoderHouse',20),(8,'Marcela','Perez','marce@mail.com',22686777,'12555666','Uruguaya','2025-03-15 12:53:52','CoderHouse',26),(15,'Marcelo','Perez','marcelo@gmail.com',55666677,'1254654','Uruguaya','2025-03-15 13:28:56','CoderHouse',29),(16,'Enzo','Godoy','enzo@mail.com',55996677,'1253354','Brasilero','2025-03-15 13:28:56','CoderHouse',22),(17,'Julian','Alvarez','julian@mail.com',55688677,'1251124','Peruano','2025-03-15 13:28:56','CoderHouse',33),(18,'Cristian','Diaz','cris@gmail.com',55222677,'1111654','Chileno','2025-03-15 13:28:56','CoderHouse',21),(19,'Raul','Leiva','raul@mail.com',55446677,'1251654','Chileno','2025-03-15 13:28:56','CoderHouse',31),(20,'Wanda','Nara','wandaylgante@mail.com',22444488,'4545454','Argentina','2025-03-15 13:28:56','CoderHouse',31),(21,'Romina','Baron','romy@mail.com',53333677,'1254154','Peruano','2025-03-15 13:28:56','CoderHouse',27),(22,'China','Suarez','chinaicardi@gmail.com',22686677,'19955666','Argentina','2025-03-15 13:29:43','CoderHouse',35),(23,'Adrian','Perez','Adrian@mail.com',55669997,'12154654','Uruguaya','2025-03-22 12:41:18','CoderHouse',29),(24,'Andres','Perez','Andres@mail.com',57866677,'12541654','Uruguaya','2025-03-22 12:41:18','CoderHouse',29),(25,'Adrian','Perez','Adrian@gmail.com',556699947,'121454654','Uruguaya','2025-03-22 12:42:18','CoderHouse',29),(26,'Andres','Perez','Andres@gmail.com',574866677,'125414654','Uruguaya','2025-03-22 12:42:18','CoderHouse',29),(27,'Juan','Perez','juanperez@mail.com',12345678,'1166665555','Argentina','2025-05-10 12:35:14','CoderHouse',20),(28,'Pedro','Lopez','pedrito@mail.com',23232323,'1155554444','Argentina','2025-05-10 13:01:37','CoderHouse',30),(29,'Romina','Etchegaray','romina@mail.com',66555444,'222555444','Argentina','2025-05-10 13:02:32','CoderHouse',25),(31,'Romina Lorena','Garcia','romina2@mail.com',55666333,'335555666','Ururguay','2025-05-10 13:03:40','Mi Instituto',25); 51 | /*!40000 ALTER TABLE `alumnos` ENABLE KEYS */; 52 | UNLOCK TABLES; 53 | /*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; 54 | 55 | /*!40101 SET SQL_MODE=@OLD_SQL_MODE */; 56 | /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; 57 | /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; 58 | /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; 59 | /*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; 60 | /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; 61 | /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; 62 | 63 | -- Dump completed on 2025-05-24 12:48:48 64 | -------------------------------------------------------------------------------- /clase_11/ejercicios.md: -------------------------------------------------------------------------------- 1 | # Repaso general 2 | 3 | ## 🧠 Ejercicios de Práctica por Tema 4 | 5 | ### 1. **Consultas Básicas (SELECT, WHERE, ORDER BY)** 6 | 7 | * **Objetivo:** Practicar la selección y filtrado de datos en una sola tabla. 8 | * **Ejemplo de ejercicio:** Obtener todos los productos con un precio mayor a \$100, ordenados de mayor a menor precio. 9 | * **Recurso recomendado:** [10 Ejercicios de Práctica SQL para Principiantes con Soluciones](https://learnsql.es/blog/10-ejercicios-de-practica-sql-para-principiantes-con-soluciones/)([mode.com][1], [learnsql.es][2]) 10 | 11 | ### 2. **Joins (INNER, LEFT, RIGHT)** 12 | 13 | * **Objetivo:** Aprender a combinar datos de múltiples tablas relacionadas. 14 | * **Ejemplo de ejercicio:** Listar todos los productos junto con el nombre de su fabricante. 15 | * **Recurso recomendado:** [7 Ejemplos de SQL JOIN con explicaciones detalladas](https://learnsql.es/blog/7-ejemplos-de-sql-join-con-explicaciones-detalladas/)([udb.edu.sv][3], [Studocu][4], [learnsql.es][5]) 16 | 17 | ### 3. **Funciones de Agregación y Agrupamiento (GROUP BY, HAVING)** 18 | 19 | * **Objetivo:** Utilizar funciones como COUNT, SUM, AVG para resumir datos. 20 | * **Ejemplo de ejercicio:** Calcular el precio promedio de los productos por fabricante. 21 | * **Recurso recomendado:** [Ejercicios. Realización de consultas SQL](https://josejuansanchez.org/bd/ejercicios-consultas-sql/index.html)([josejuansanchez.org][6]) 22 | 23 | ### 4. **Subconsultas (Subqueries)** 24 | 25 | * **Objetivo:** Realizar consultas anidadas para resolver problemas más complejos. 26 | * **Ejemplo de ejercicio:** Encontrar los productos que tienen un precio superior al promedio de todos los productos. 27 | * **Recurso recomendado:** [Ejercicios SubQuerys](https://es.scribd.com/document/219914360/Ejercicios-SubQuerys)([Scribd][7], [udb.edu.sv][3]) 28 | 29 | ### 5. **Consultas Avanzadas y Casos Prácticos** 30 | 31 | * **Objetivo:** Aplicar conocimientos en escenarios más realistas y complejos. 32 | * **Ejemplo de ejercicio:** Listar los productos que no han sido vendidos en el último mes. 33 | * **Recurso recomendado:** [Guía de ejercicios SQL para Sistemas de Bases de Datos I - UCAB](https://biblioteca2.ucab.edu.ve/anexos/biblioteca/marc/texto/AAU4531.pdf)([biblioteca2.ucab.edu.ve][8]) 34 | 35 | --- 36 | 37 | ## 📚 Recursos Adicionales 38 | 39 | * **Curso interactivo:** [LearnSQL.es](https://learnsql.es/) ofrece cursos con ejercicios prácticos para diferentes niveles. 40 | * **Repositorio GitHub:** [FabianNorbertoEscobar/sql-ejercicios](https://github.com/FabianNorbertoEscobar/sql-ejercicios) contiene una variedad de ejercicios prácticos.([learnsql.es][9], [GitHub][10]) 41 | 42 | --- 43 | 44 | ## 📘 Recomendaciones de Libros 45 | 46 | Para profundizar aún más, aca tienen algunas opciones de libros que podrían interesarles: 47 | 48 | ### [SQL: Guía Completa Para Principiantes De La Programación SQL]() 49 | 50 | ### [SQL: Guía Para Principiantes Para Aprender SQL]() 51 | 52 | ### [Curso De SQL de Martínez Cruz, Carmen]() 53 | 54 | --- 55 | 56 | ## 🧑‍🏫 Profesor 57 | 58 | 👨‍💻 **Alejandro Daniel Di Stefano** 59 | 📌 **Desarrollador Full Stack** 60 | 🔗 **GitHub:** [Drako01](https://github.com/Drako01) 61 | 62 | [1]: https://mode.com/sql-tutorial/sql-joins-where-vs-on/?utm_source=chatgpt.com "SQL Joins Using WHERE or ON - Mode Analytics" 63 | [2]: https://learnsql.es/blog/10-ejercicios-de-practica-sql-para-principiantes-con-soluciones/?utm_source=chatgpt.com "10 Ejercicios de Práctica SQL para Principiantes con Soluciones" 64 | [3]: https://www.udb.edu.sv/udb_files/recursos_guias/informatica-ingenieria/modelamiento-y-diseno-de-base-de-datos/2019/ii/guia-6.pdf?utm_source=chatgpt.com "[PDF] Guía N° 6 Tema: Combinación de tablas" 65 | [4]: https://www.studocu.com/cl/document/centro-de-formacion-tecnica-estatal-tarapaca/taller-de-base-de-datos/guia-ejercicios-sql-join-resuelta/37727533?utm_source=chatgpt.com "Guía Ejercicios SQL JOIN - resuelta - Carrera TNS en Informática y ..." 66 | [5]: https://learnsql.es/blog/7-ejemplos-de-sql-join-con-explicaciones-detalladas/?utm_source=chatgpt.com "7 Ejemplos de SQL JOIN con explicaciones detalladas | LearnSQL.es" 67 | [6]: https://josejuansanchez.org/bd/ejercicios-consultas-sql/index.html?utm_source=chatgpt.com "Ejercicios. Realización de consultas SQL" 68 | [7]: https://es.scribd.com/document/219914360/Ejercicios-SubQuerys?utm_source=chatgpt.com "Ejercicios SubQuerys | PDF | SQL | Gestión de datos - Scribd" 69 | [8]: https://biblioteca2.ucab.edu.ve/anexos/biblioteca/marc/texto/AAU4531.pdf?utm_source=chatgpt.com "[PDF] Guía de ejercicios SQL para Sistemas de Bases de Datos I - UCAB" 70 | [9]: https://learnsql.es/blog/22-ejercicios-para-practicar-comandos-sql/?utm_source=chatgpt.com "22 Ejercicios para Practicar Comandos SQL | LearnSQL.es" 71 | [10]: https://github.com/FabianNorbertoEscobar/sql-ejercicios?utm_source=chatgpt.com "FabianNorbertoEscobar/sql-ejercicios: Ejercicios de SQL ... - GitHub" 72 | -------------------------------------------------------------------------------- /clase_05/teoria/teoria.md: -------------------------------------------------------------------------------- 1 | # Clase: Vistas en SQL 2 | 3 | ## ¿Qué es una Vista? 4 | 5 | Una **vista** es una tabla virtual basada en el resultado de una consulta SQL. Aunque se comporta como una tabla, no almacena los datos por sí misma, sino que muestra los datos de una o varias tablas subyacentes. 6 | 7 | ### Ejemplo: 8 | ```sql 9 | CREATE VIEW vista_alumnos AS 10 | SELECT nombre, apellido FROM alumno; 11 | ``` 12 | 13 | Esta vista muestra solamente el nombre y apellido de los alumnos. 14 | 15 | --- 16 | 17 | ## Tipos de Vistas 18 | 19 | ### 1. Vistas Simples 20 | Basadas en una sola tabla, sin funciones agregadas ni uniones. 21 | 22 | ```sql 23 | CREATE VIEW vista_cursos AS 24 | SELECT nombre_curso, duracion FROM curso; 25 | ``` 26 | 27 | ### 2. Vistas Complejas 28 | Pueden incluir JOINs, funciones agregadas, subconsultas, etc. 29 | 30 | ```sql 31 | CREATE VIEW vista_alumnos_cursos AS 32 | SELECT a.nombre, c.nombre_curso 33 | FROM alumno a 34 | JOIN curso c ON a.id_curso = c.id_curso; 35 | ``` 36 | 37 | --- 38 | 39 | ## Objetivos de una Vista 40 | 41 | - **Simplificar consultas**: Facilita el acceso a datos complejos. 42 | - **Seguridad**: Se pueden ocultar columnas sensibles. 43 | - **Abstracción**: Se puede modificar la estructura de las tablas sin afectar a las aplicaciones que usan las vistas. 44 | - **Reutilización**: Usar una misma consulta en varios lugares. 45 | 46 | --- 47 | 48 | ## Creación y Actualización de Vistas 49 | 50 | ### Crear una Vista 51 | ```sql 52 | CREATE VIEW vista_instituciones AS 53 | SELECT nombre, ciudad FROM institucion; 54 | ``` 55 | 56 | ### Actualizar una Vista con OR REPLACE 57 | ```sql 58 | CREATE OR REPLACE VIEW vista_instituciones AS 59 | SELECT nombre, ciudad, provincia FROM institucion; 60 | ``` 61 | 62 | Esto reemplaza la vista anterior con la nueva definición. 63 | 64 | --- 65 | 66 | ## Eliminación de una Vista 67 | 68 | ```sql 69 | DROP VIEW vista_instituciones; 70 | ``` 71 | 72 | --- 73 | 74 | ## Crear Vistas ya existentes (cuando las tablas ya existen) 75 | 76 | Si ya tenemos las siguientes tablas: 77 | - `alumno(id_alumno, nombre, apellido, id_curso)` 78 | - `curso(id_curso, nombre_curso, id_categoria)` 79 | - `categoria(id_categoria, nombre_categoria)` 80 | 81 | Podemos crear una vista que relacione esta información: 82 | 83 | ```sql 84 | CREATE VIEW vista_alumnos_detalle AS 85 | SELECT a.nombre, a.apellido, c.nombre_curso, cat.nombre_categoria 86 | FROM alumno a 87 | JOIN curso c ON a.id_curso = c.id_curso 88 | JOIN categoria cat ON c.id_categoria = cat.id_categoria; 89 | ``` 90 | 91 | --- 92 | 93 | ## Aplicar Filtros a una Vista 94 | 95 | Se pueden aplicar filtros directamente en la definición: 96 | 97 | ```sql 98 | CREATE VIEW vista_alumnos_matematica AS 99 | SELECT a.nombre, a.apellido 100 | FROM alumno a 101 | JOIN curso c ON a.id_curso = c.id_curso 102 | WHERE c.nombre_curso = 'Matemática'; 103 | ``` 104 | 105 | O bien aplicar filtros al consultar la vista: 106 | 107 | ```sql 108 | SELECT * FROM vista_alumnos_detalle WHERE nombre_categoria = 'Ciencias'; 109 | ``` 110 | 111 | --- 112 | 113 | ## Crear una Vista con Más de una Tabla (JOINs) 114 | 115 | ### Ejemplo completo: 116 | Tablas involucradas: 117 | - **alumno**: (id_alumno, nombre, apellido, id_curso) 118 | - **curso**: (id_curso, nombre_curso, duracion, id_categoria) 119 | - **categoria**: (id_categoria, nombre_categoria) 120 | - **institucion**: (id_institucion, nombre, ciudad) 121 | 122 | Queremos una vista que muestre: 123 | - Nombre del alumno 124 | - Curso que está cursando 125 | - Categoría del curso 126 | - Ciudad de la institución 127 | 128 | ```sql 129 | CREATE VIEW vista_completa_alumnos AS 130 | SELECT a.nombre AS nombre_alumno, a.apellido, 131 | c.nombre_curso, cat.nombre_categoria, 132 | i.ciudad 133 | FROM alumno a 134 | JOIN curso c ON a.id_curso = c.id_curso 135 | JOIN categoria cat ON c.id_categoria = cat.id_categoria 136 | JOIN institucion i ON c.id_institucion = i.id_institucion; 137 | ``` 138 | 139 | Esto permite tener una vista global de la información para consultas más rápidas y ordenadas. 140 | 141 | --- 142 | 143 | ## Consideraciones Finales 144 | - Una vista **no almacena datos**, solo la consulta. 145 | - Se pueden consultar como si fueran tablas. 146 | - Algunas vistas pueden no ser actualizables (por ejemplo si usan funciones agregadas o GROUP BY). 147 | - Muy útiles en reportes, dashboards, y para ocultar detalles internos. 148 | 149 | 150 | 151 | --- 152 | 153 | ## Recursos Adicionales 154 | - [Documentación oficial de MySQL sobre Vistas](https://dev.mysql.com/doc/refman/8.0/en/create-view.html) 155 | - [W3Schools - SQL Views](https://www.w3schools.com/sql/sql_view.asp) 156 | 157 | 158 | 159 | ## 🧑‍🏫 Profesor 160 | 161 | 👨‍💻 **Alejandro Daniel Di Stefano** 162 | 📌 **Desarrollador Full Stack** 163 | 🔗 **GitHub:** [Drako01](https://github.com/Drako01) 164 | -------------------------------------------------------------------------------- /clase_03/SQL_Query_03.sql: -------------------------------------------------------------------------------- 1 | USE coderhouse; 2 | 3 | CREATE TABLE alumnos ( 4 | id_alumno INT PRIMARY KEY AUTO_INCREMENT NOT NULL, 5 | nombre VARCHAR(30) NOT NULL, 6 | apellido VARCHAR(40) NOT NULL, 7 | email VARCHAR (100) UNIQUE DEFAULT NULL, 8 | dni INT UNIQUE NOT NULL, 9 | telefono VARCHAR (20) UNIQUE DEFAULT NULL, 10 | nacionalidad VARCHAR (30) DEFAULT "Argentina" 11 | ); 12 | 13 | CREATE TABLE cursos ( 14 | id_curso INT PRIMARY KEY AUTO_INCREMENT, 15 | nombre_curso VARCHAR(50) NOT NULL 16 | ); 17 | 18 | CREATE TABLE inscripciones ( 19 | id_alumno INT, 20 | id_curso INT, 21 | inscription_at DATETIME DEFAULT CURRENT_TIMESTAMP, 22 | PRIMARY KEY (id_alumno, id_curso), 23 | FOREIGN KEY (id_alumno) REFERENCES alumnos(id_alumno), 24 | FOREIGN KEY (id_curso) REFERENCES cursos(id_curso) 25 | ); 26 | 27 | 28 | INSERT INTO cursos (nombre_curso) VALUES 29 | ("SQL"), 30 | ("JavaScript"), 31 | ("Java"), 32 | ("HTML"); 33 | 34 | INSERT INTO inscripciones (id_alumno, id_curso) VALUES 35 | (4,1), 36 | (4,3), 37 | (8,1), 38 | (8,2), 39 | (22,1), 40 | (21,1), 41 | (21,4), 42 | (19,1); 43 | 44 | 45 | -- UNION de Tablas 46 | 47 | -- INNER JOIN 48 | SELECT a.nombre, a.apellido, a.dni, c.nombre_curso 49 | FROM alumnos a 50 | INNER JOIN inscripciones i ON a.id_alumno = i.id_alumno 51 | INNER JOIN cursos c ON i.id_curso = c.id_curso; 52 | 53 | -- LEFT JOIN 54 | SELECT a.nombre, a.apellido, a.dni, c.nombre_curso 55 | FROM alumnos a 56 | LEFT JOIN inscripciones i ON a.id_alumno = i.id_alumno 57 | LEFT JOIN cursos c ON i.id_curso = c.id_curso; 58 | 59 | -- RIGHT JOIN 60 | SELECT a.nombre, a.apellido, a.dni, c.nombre_curso 61 | FROM alumnos a 62 | RIGHT JOIN inscripciones i ON a.id_alumno = i.id_alumno 63 | RIGHT JOIN cursos c ON i.id_curso = c.id_curso; 64 | 65 | -- UNION 66 | -- LEFT JOIN 67 | SELECT a.nombre, a.apellido, a.dni, c.nombre_curso 68 | FROM alumnos a 69 | LEFT JOIN inscripciones i ON a.id_alumno = i.id_alumno 70 | LEFT JOIN cursos c ON i.id_curso = c.id_curso 71 | 72 | UNION 73 | 74 | SELECT a.nombre, a.apellido, a.dni, c.nombre_curso 75 | FROM alumnos a 76 | RIGHT JOIN inscripciones i ON a.id_alumno = i.id_alumno 77 | RIGHT JOIN cursos c ON i.id_curso = c.id_curso; 78 | 79 | -- SELF JOIN 80 | -- SELECT a1.nombre AS alumno, a2.nombre AS tutor 81 | -- FROM alumnos a1 82 | -- JOIN alumnos a2 ON a1.tutor_id = a2.id_alumno; 83 | 84 | 85 | -- Uso de LIKE y Comodines + REGEX 86 | INSERT INTO alumnos(nombre, apellido, email, dni, telefono, nacionalidad, edad) 87 | VALUES 88 | ("Adrian", "Perez", "Adrian@mail.com", 55669997, "12154654", 'Uruguaya', 29), 89 | ("Andres", "Perez", "Andres@mail.com", 57866677, "12541654", 'Uruguaya', 29); 90 | 91 | INSERT INTO alumnos(nombre, apellido, email, dni, telefono, nacionalidad, edad) 92 | VALUES 93 | ("Adrian", "Perez", "Adrian@gmail.com", 556699947, "121454654", 'Uruguaya', 29), 94 | ("Andres", "Perez", "Andres@gmail.com", 574866677, "125414654", 'Uruguaya', 29); 95 | 96 | 97 | SELECT nombre, apellido, dni, telefono, edad 98 | FROM alumnos 99 | WHERE nombre LIKE "A%" 100 | ORDER BY nombre ASC; 101 | 102 | SELECT nombre, apellido, dni, telefono, edad , email 103 | FROM alumnos 104 | WHERE email LIKE "%gmail.com" 105 | ORDER BY nombre ASC; 106 | 107 | SELECT nombre, apellido, dni, telefono, edad 108 | FROM alumnos 109 | WHERE nombre REGEXP "^[A-C]" 110 | ORDER BY nombre ASC; 111 | 112 | SELECT nombre, apellido, dni, telefono, edad 113 | FROM alumnos 114 | WHERE nombre LIKE "A%" 115 | OR nombre LIKE "C%" 116 | ORDER BY nombre ASC; 117 | 118 | 119 | SELECT nombre, apellido, dni, telefono, edad , email FROM alumnos WHERE email REGEXP '^[a-z]+@[a-z]+\\.(com|net)$'; 120 | 121 | 122 | 123 | -- Subconsultas de SQL 124 | 125 | SELECT nombre, edad 126 | FROM alumnos 127 | WHERE edad = (SELECT MAX(edad) FROM alumnos); 128 | 129 | SELECT nombre, edad 130 | FROM alumnos 131 | WHERE edad = (SELECT MIN(edad) FROM alumnos); 132 | 133 | SELECT nombre, edad, nacionalidad 134 | FROM alumnos 135 | WHERE (nacionalidad, edad) IN ( 136 | SELECT nacionalidad, MIN(edad) 137 | FROM alumnos 138 | GROUP BY nacionalidad 139 | ); 140 | 141 | -- Funciones de Texto 142 | SELECT UPPER(email) AS email_mayuscula, nombre, LOWER(apellido) AS Apellido, edad 143 | FROM alumnos 144 | WHERE edad > (SELECT AVG(edad) FROM alumnos); 145 | 146 | 147 | SELECT a.nombre, a.apellido, i.inscription_at AS fecha_inscripcion 148 | FROM alumnos a 149 | INNER JOIN inscripciones i ON a.id_alumno = i.id_alumno 150 | WHERE i.inscription_at < DATE_SUB(NOW(), INTERVAL 1 YEAR); 151 | 152 | -- DDL 153 | TRUNCATE inscripciones; 154 | 155 | -- No es recomendable porque puede ser Destructivo 156 | RENAME TABLE alumnos TO estudiantes; 157 | RENAME TABLE estudiantes TO alumnos; 158 | -------------------------------------------------------------------------------- /clase_05/ejercicios/ejercicios_sql_completos.md: -------------------------------------------------------------------------------- 1 | 2 | # 🧠 Ejercicios Prácticos de SQL 3 | 4 | 5 | --- 6 | 7 | ## 📌 PARTE 1: Consultas Básicas 8 | 9 | ### 1. Mostrar todos los alumnos 10 | 11 | ```sql 12 | SELECT * FROM alumnos; 13 | ``` 14 | 15 | ### 2. Listar todos los cursos ordenados por duración descendente 16 | 17 | ```sql 18 | SELECT * FROM cursos 19 | ORDER BY duracion DESC; 20 | ``` 21 | 22 | ### 3. Buscar alumnos cuyo nombre comience con "A" 23 | 24 | ```sql 25 | SELECT * FROM alumnos 26 | WHERE nombre LIKE 'A%'; 27 | ``` 28 | 29 | ### 4. Mostrar los 5 cursos más largos 30 | 31 | ```sql 32 | SELECT * FROM cursos 33 | ORDER BY duracion DESC 34 | LIMIT 5; 35 | ``` 36 | 37 | ### 5. Obtener los emails de los alumnos únicos 38 | 39 | ```sql 40 | SELECT DISTINCT email FROM alumnos; 41 | ``` 42 | 43 | --- 44 | 45 | ## 📌 PARTE 2: Funciones de Agregado y Agrupaciones 46 | 47 | ### 6. Cantidad total de alumnos 48 | 49 | ```sql 50 | SELECT COUNT(*) AS total_alumnos FROM alumnos; 51 | ``` 52 | 53 | ### 7. Duración promedio de los cursos 54 | 55 | ```sql 56 | SELECT AVG(duracion) AS promedio_duracion FROM cursos; 57 | ``` 58 | 59 | ### 8. Cantidad de inscriptos por curso 60 | 61 | ```sql 62 | SELECT id_curso, COUNT(id_alumno) AS cantidad 63 | FROM inscripciones 64 | GROUP BY id_curso; 65 | ``` 66 | 67 | --- 68 | 69 | ## 📌 PARTE 3: Joins y Relaciones 70 | 71 | ### 9. Obtener el nombre del alumno y el nombre del curso en el que está inscripto 72 | 73 | ```sql 74 | SELECT a.nombre, a.apellido, c.nombre_curso 75 | FROM inscripciones i 76 | JOIN alumnos a ON i.id_alumno = a.id_alumno 77 | JOIN cursos c ON i.id_curso = c.id_curso; 78 | ``` 79 | 80 | ### 10. Alumnos sin inscripción 81 | 82 | ```sql 83 | SELECT a.* 84 | FROM alumnos a 85 | LEFT JOIN inscripciones i ON a.id_alumno = i.id_alumno 86 | WHERE i.id_alumno IS NULL; 87 | ``` 88 | 89 | --- 90 | 91 | ## 📌 PARTE 4: Subconsultas 92 | 93 | ### 11. Mostrar los cursos con más inscriptos que el promedio 94 | 95 | ```sql 96 | SELECT id_curso, COUNT(*) AS total 97 | FROM inscripciones 98 | GROUP BY id_curso 99 | HAVING total > (SELECT AVG(cantidad) 100 | FROM (SELECT COUNT(*) AS cantidad 101 | FROM inscripciones 102 | GROUP BY id_curso) subquery); 103 | ``` 104 | 105 | --- 106 | 107 | ## 📌 PARTE 5: Vistas 108 | 109 | ### 12. Crear una vista con alumnos y su curso 110 | 111 | ```sql 112 | CREATE VIEW vista_alumnos_cursos AS 113 | SELECT a.nombre, a.apellido, c.nombre_curso 114 | FROM inscripciones i 115 | JOIN alumnos a ON i.id_alumno = a.id_alumno 116 | JOIN cursos c ON i.id_curso = c.id_curso; 117 | ``` 118 | 119 | ### 13. Vista de alumnos inscriptos en más de un curso 120 | 121 | ```sql 122 | CREATE VIEW vista_multicurso AS 123 | SELECT id_alumno, COUNT(*) AS cantidad 124 | FROM inscripciones 125 | GROUP BY id_alumno 126 | HAVING cantidad > 1; 127 | ``` 128 | 129 | --- 130 | 131 | ## 📌 PARTE 6: Stored Procedures 132 | 133 | ### 14. Procedimiento para contar inscripciones por día 134 | 135 | ```sql 136 | DELIMITER // 137 | 138 | CREATE PROCEDURE ObtenerInscripcionesPorDia() 139 | BEGIN 140 | SELECT DATE(inscription_at) AS fecha, COUNT(*) AS cantidad 141 | FROM inscripciones 142 | GROUP BY fecha; 143 | END // 144 | 145 | DELIMITER ; 146 | 147 | CALL ObtenerInscripcionesPorDia(); 148 | ``` 149 | 150 | --- 151 | 152 | ## 📌 PARTE 7: Triggers 153 | 154 | ### 15. Trigger para evitar inscripciones duplicadas 155 | 156 | ```sql 157 | DELIMITER // 158 | 159 | CREATE TRIGGER before_inscription_insert 160 | BEFORE INSERT ON inscripciones 161 | FOR EACH ROW 162 | BEGIN 163 | DECLARE existe INT; 164 | SELECT COUNT(*) INTO existe 165 | FROM inscripciones 166 | WHERE id_alumno = NEW.id_alumno AND id_curso = NEW.id_curso; 167 | 168 | IF existe > 0 THEN 169 | SIGNAL SQLSTATE '45000' 170 | SET MESSAGE_TEXT = 'El Alumno ya está inscripto en este curso'; 171 | END IF; 172 | END // 173 | 174 | DELIMITER ; 175 | ``` 176 | 177 | ### 16. Trigger para actualizar contador de inscripciones 178 | 179 | ```sql 180 | DELIMITER // 181 | 182 | CREATE TRIGGER after_inscription_insert 183 | AFTER INSERT ON inscripciones 184 | FOR EACH ROW 185 | BEGIN 186 | DECLARE curso_count INT; 187 | 188 | SELECT cantidad_inscripciones INTO curso_count 189 | FROM cursos_inscripciones_count 190 | WHERE id_curso = NEW.id_curso; 191 | 192 | IF curso_count IS NULL THEN 193 | INSERT INTO cursos_inscripciones_count (id_curso, cantidad_inscripciones) 194 | VALUES (NEW.id_curso, 1); 195 | ELSE 196 | UPDATE cursos_inscripciones_count 197 | SET cantidad_inscripciones = cantidad_inscripciones + 1 198 | WHERE id_curso = NEW.id_curso; 199 | END IF; 200 | END // 201 | 202 | DELIMITER ; 203 | ``` 204 | 205 | --- 206 | 207 | 208 | 209 | ## 🧑‍🏫 Profesor 210 | 211 | 👨‍💻 **Alejandro Daniel Di Stefano** 212 | 📌 **Desarrollador Full Stack** 213 | 🔗 **GitHub:** [Drako01](https://github.com/Drako01) 214 | -------------------------------------------------------------------------------- /clase_02/query_clase_02.sql: -------------------------------------------------------------------------------- 1 | USE coderhouse; 2 | 3 | -- Sublenguages SQL 4 | -- DDL Data Definition Language 5 | -- DML Data Manipulatin Language 6 | -- DCL (Data Control Language) -- Controlar Permisos 7 | -- TCL (Transaction Control Language) -- Controlar Transacciones 8 | 9 | -- ------------------------------------------------------ 10 | 11 | -- DDL Data Definition Language 12 | CREATE DATABASE IF NOT EXISTS coderhouse; 13 | CREATE TABLE coderhouse.alumnos ( 14 | id_alumno INT PRIMARY KEY AUTO_INCREMENT NOT NULL, 15 | nombre VARCHAR(30) NOT NULL, 16 | apellido VARCHAR(40) NOT NULL, 17 | email VARCHAR (100) UNIQUE DEFAULT NULL, 18 | dni INT UNIQUE NOT NULL, 19 | telefono VARCHAR (20) UNIQUE DEFAULT NULL, 20 | nacionalidad VARCHAR (30) DEFAULT "Argentina" 21 | ); 22 | 23 | -- DROP TABLE coderhouse.alumnos; 24 | ALTER TABLE coderhouse.alumnos ADD COLUMN fecha_inscripcion DATETIME DEFAULT CURRENT_TIMESTAMP; 25 | ALTER TABLE coderhouse.alumnos ADD COLUMN instituto VARCHAR(60); 26 | ALTER TABLE coderhouse.alumnos ADD COLUMN edad INT DEFAULT NULL; 27 | ALTER TABLE coderhouse.alumnos MODIFY COLUMN instituto VARCHAR(60) DEFAULT 'CoderHouse'; 28 | 29 | -- DML Data Manipulatin Language 30 | 31 | -- INSERT INTO alumnos(nombre, apellido, email, dni, telefono) 32 | -- VALUES 33 | -- ("Alejandro", "Di Stefano", "alejandro@mail.com", 22233355, "115555666"); 34 | 35 | -- INSERT INTO alumnos(nombre, apellido, email, dni, telefono) 36 | -- VALUES 37 | -- ("Juan", "Perez", "perez@mail.com", 113333666, "1166667777"); 38 | -- INSERT INTO alumnos(nombre, apellido, email, dni, telefono) 39 | -- VALUES 40 | -- ("Ivanna", "Muñoz", "ivana@mail.com", 33555888, "1166333777"); 41 | 42 | INSERT INTO alumnos(nombre, apellido, email, dni, telefono) 43 | VALUES 44 | ("Alejandro", "Di Stefano", "alejandro@mail.com", 22233355, "115555666"), 45 | ("Juan", "Perez", "perez@mail.com", 113333666, "1166667777"), 46 | ("Ivanna", "Muñoz", "ivana@mail.com", 33555888, "1166333777"); 47 | INSERT INTO alumnos(nombre, apellido, email, dni, telefono, edad) 48 | VALUES 49 | ("Marcela", "Muñoz", "ivana@mail.com", 33555888, "1166333777", 20); 50 | 51 | INSERT INTO alumnos(nombre, apellido, email, dni, telefono, nacionalidad, edad) 52 | VALUES 53 | ("Marcela", "Perez", "marce@mail.com", 22686777, "12555666", 'Uruguaya', 20); 54 | 55 | INSERT INTO alumnos(nombre, apellido, email, dni, telefono, nacionalidad, edad) 56 | VALUES 57 | ("Marcelo", "Perez", "marcelo@mail.com", 55666677, "1254654", 'Uruguaya', 29), 58 | ("Enzo", "Godoy", "enzo@mail.com", 55996677, "1253354", 'Brasilero', 22), 59 | ("Julian", "Alvarez", "julian@mail.com", 55688677, "1251124", 'Peruano', 33), 60 | ("Cristian", "Diaz", "cris@mail.com", 55222677, "1111654", 'Chileno', 21), 61 | ("Raul", "Leiva", "raul@mail.com", 55446677, "1251654", 'Chileno', 31), 62 | ("Wanda", "Nara", "wandaylgante@mail.com", 22444488, "4545454", 'Argentina', 31), 63 | ("Romina", "Baron", "romy@mail.com", 53333677, "1254154", 'Peruano', 27); 64 | 65 | INSERT INTO alumnos(nombre, apellido, email, dni, telefono, nacionalidad, edad) 66 | VALUES 67 | ("China", "Suarez", "chinaicardi@mail.com", 22686677, "19955666", 'Argentina', 35); 68 | 69 | 70 | SELECT * FROM alumnos; 71 | 72 | UPDATE coderhouse.alumnos SET instituto = 'CoderHouse', nacionalidad = 'Argentina'; 73 | 74 | SET SQL_SAFE_UPDATES = 0; 75 | SET SQL_SAFE_UPDATES = 1; 76 | 77 | DELETE FROM coderhouse.alumnos; 78 | UPDATE coderhouse.alumnos SET edad = 49 WHERE dni = '22233355'; 79 | UPDATE coderhouse.alumnos SET edad = 30 WHERE dni = '113333666'; 80 | UPDATE coderhouse.alumnos SET edad = 16 WHERE dni = '33555888'; 81 | 82 | SELECT nombre, apellido FROM alumnos WHERE edad >= 18; 83 | 84 | DELETE FROM coderhouse.alumnos WHERE edad < 18; 85 | 86 | SELECT COUNT(*) AS alumnos_uruguayos FROM alumnos WHERE nacionalidad = 'Uruguaya'; 87 | SELECT COUNT(*) AS alumnos_argentinos FROM alumnos WHERE nacionalidad = 'Argentina'; 88 | 89 | SELECT SUM(edad) AS suma_total_de_edades_alumnos_argentinos FROM alumnos WHERE nacionalidad = 'Argentina'; 90 | SELECT AVG(edad) AS promedio_de_edades_alumnos_argentinos FROM alumnos WHERE nacionalidad = 'Argentina'; 91 | 92 | SELECT 93 | COUNT(*) AS cantidad_alumnos, 94 | SUM(edad) AS suma_de_edades, 95 | AVG(edad) AS promedio_de_edades 96 | FROM alumnos 97 | WHERE nacionalidad = 'Argentina'; 98 | 99 | -- != (Desigual) 100 | 101 | 102 | SELECT id_alumno, nombre, apellido, dni, telefono, edad 103 | FROM alumnos 104 | WHERE edad >= 18 105 | ORDER BY edad ASC; 106 | 107 | SELECT nombre, apellido, dni, telefono 108 | FROM alumnos 109 | WHERE edad >= 18 110 | ORDER BY apellido DESC; 111 | 112 | UPDATE coderhouse.alumnos SET edad = 26 WHERE id_alumno = 8; 113 | 114 | SELECT 115 | MIN(edad) AS "Mas Joven", 116 | MAX(edad) AS Mayor 117 | FROM alumnos ; 118 | 119 | 120 | SELECT nacionalidad, 121 | MIN(edad) AS "Mas Joven", 122 | MAX(edad) AS "Mas Adulto" 123 | FROM alumnos 124 | GROUP BY nacionalidad; 125 | 126 | 127 | 128 | SELECT nombre, apellido, dni, telefono 129 | FROM alumnos 130 | ORDER BY apellido ASC 131 | LIMIT 5; 132 | -------------------------------------------------------------------------------- /clase_10/ejercicios/ejercicios.md: -------------------------------------------------------------------------------- 1 | # Ejercicios Clase 10 2 | 3 | ## Transacciones 4 | 5 | ### 📁 `ejercicios.md` 6 | 7 | # 🧠 Ejercicios de Práctica – Transacciones y Backup en MySQL Workbench 8 | 9 | ## 🎯 Objetivos de la clase 10 | 11 | - Reconocer e implementar las sentencias del sublenguaje **TCL**. 12 | - Identificar en qué situación usar cada sentencia (**COMMIT, ROLLBACK, SAVEPOINT**). 13 | - Definir los conceptos **Backup** y **Restauración**. 14 | - Identificar los componentes del proceso de **Backup & Restore**. 15 | - Implementar **Backups** y **Restauraciones** en Workbench y línea de comandos. 16 | 17 | --- 18 | 19 | ## 🧪 SECCIÓN 1 – Transacciones (TCL) 20 | 21 | ### 🧩 Ejercicio 1: Insertar múltiples registros con COMMIT 22 | 23 | 1. Crear una base de datos `ejemplo_tcl`. 24 | 2. Crear una tabla `clientes` con id, nombre, email. 25 | 3. Iniciar una transacción e insertar 3 registros. 26 | 4. Ejecutar `COMMIT`. 27 | 5. Verificar que los datos se guardaron. 28 | 29 | ```sql 30 | START TRANSACTION; 31 | 32 | INSERT INTO clientes (nombre, email) VALUES ('Carlos', 'carlos@mail.com'); 33 | INSERT INTO clientes (nombre, email) VALUES ('Lucía', 'lucia@mail.com'); 34 | INSERT INTO clientes (nombre, email) VALUES ('Damián', 'damian@mail.com'); 35 | 36 | COMMIT; 37 | ```` 38 | 39 | --- 40 | 41 | ### 🧩 Ejercicio 2: Usar ROLLBACK para deshacer errores 42 | 43 | 1. Iniciar una nueva transacción. 44 | 2. Insertar 2 registros nuevos en `clientes`. 45 | 3. Por error, intentá insertar uno con un email repetido. 46 | 4. Al fallar, usar `ROLLBACK`. 47 | 5. Verificar que no se insertó nada. 48 | 49 | --- 50 | 51 | ### 🧩 Ejercicio 3: Usar SAVEPOINT para retroceder parcialmente 52 | 53 | 1. Iniciar una transacción. 54 | 2. Insertar 3 productos en una tabla `productos`. 55 | 3. Usar `SAVEPOINT` después del primero y segundo insert. 56 | 4. Luego hacé un rollback al segundo punto. 57 | 5. Commit final. 58 | 59 | ```sql 60 | START TRANSACTION; 61 | 62 | INSERT INTO productos (nombre, precio) VALUES ('Mouse', 1500); 63 | SAVEPOINT luego_del_mouse; 64 | 65 | INSERT INTO productos (nombre, precio) VALUES ('Teclado', 3500); 66 | SAVEPOINT luego_del_teclado; 67 | 68 | INSERT INTO productos (nombre, precio) VALUES ('Monitor', 25000); 69 | 70 | ROLLBACK TO luego_del_teclado; 71 | COMMIT; 72 | ``` 73 | 74 | --- 75 | 76 | ### 🧩 Ejercicio 4: Restaurar valores iniciales en múltiples tablas 77 | 78 | 1. Crear tablas `cuentas` y `movimientos`. 79 | 2. Insertar datos iniciales con una transacción. 80 | 3. Simular una transferencia entre cuentas usando transacciones. 81 | 4. Si algo falla, usar `ROLLBACK`. 82 | 5. Si todo está bien, `COMMIT`. 83 | 84 | --- 85 | 86 | ## 💾 SECCIÓN 2 – Backup y Restauración 87 | 88 | ### 📌 Ejercicio 5: Crear un backup completo con MySQL Workbench 89 | 90 | 1. Crear una base `backup_demo` con varias tablas y registros. 91 | 2. Ir a `Server > Data Export`. 92 | 3. Exportar la base completa a un archivo `.sql`. 93 | 4. Guardar el archivo en tu PC. 94 | 95 | --- 96 | 97 | ### 📌 Ejercicio 6: Eliminar una tabla por accidente (simulado) 98 | 99 | 1. Eliminar una tabla (por ejemplo, `empleados`). 100 | 2. Verificar que ya no existe. 101 | 102 | ```sql 103 | DROP TABLE empleados; 104 | ``` 105 | 106 | --- 107 | 108 | ### 📌 Ejercicio 7: Restaurar la base desde el backup 109 | 110 | 1. Ir a `Server > Data Import`. 111 | 2. Importar el archivo `.sql` creado en el Ejercicio 5. 112 | 3. Confirmar que la tabla eliminada volvió. 113 | 114 | --- 115 | 116 | ### 📌 Ejercicio 8: Crear un backup desde línea de comandos (si usás terminal) 117 | 118 | ```bash 119 | mysqldump -u root -p backup_demo > backup_respaldo.sql 120 | ``` 121 | 122 | ### 📌 Ejercicio 9: Restaurar el backup desde terminal 123 | 124 | ```bash 125 | mysql -u root -p backup_demo < backup_respaldo.sql 126 | ``` 127 | 128 | --- 129 | 130 | ## 📘 SECCIÓN 3 – Preguntas teóricas 131 | 132 | 1. ¿Qué diferencia hay entre `ROLLBACK` y `ROLLBACK TO SAVEPOINT`? 133 | 2. ¿En qué casos usarías `START TRANSACTION`? 134 | 3. ¿Qué ventaja tiene usar SAVEPOINT en vez de hacer un rollback completo? 135 | 4. ¿Qué datos incluye un archivo de backup `.sql`? 136 | 5. ¿Qué sucede si restaurás un backup sobre una base que ya tiene datos? 137 | 138 | --- 139 | 140 | ## 🧠 BONUS – Proyecto Integrador 141 | 142 | Crea un sistema de inscripción a cursos: 143 | 144 | 1. Tablas: `alumnos`, `cursos`, `inscripciones`. 145 | 2. Simulá una transacción donde varios alumnos se inscriben. 146 | 3. Introducí un error (como un ID inexistente) a propósito. 147 | 4. Hacé rollback y corregilo. 148 | 5. Exportá un backup y volvé a importar para verificar todo. 149 | 150 | --- 151 | 152 | ## ✅ Checklist Final 153 | 154 | - [ ] Sé usar `START TRANSACTION`, `COMMIT`, `ROLLBACK`, `SAVEPOINT`. 155 | - [ ] Puedo generar un backup en `.sql`. 156 | - [ ] Sé restaurar desde Workbench y terminal. 157 | - [ ] Identifico cuándo usar cada técnica. 158 | 159 | --- 160 | 161 | ## 🧑‍🏫 Profesor 162 | 163 | 👨‍💻 **Alejandro Daniel Di Stefano** 164 | 📌 **Desarrollador Full Stack** 165 | 🔗 **GitHub:** [Drako01](https://github.com/Drako01) 166 | -------------------------------------------------------------------------------- /clase_01/resumen.md: -------------------------------------------------------------------------------- 1 | 2 | ## **📌 Clase 01** 3 | ### **Unidad 1: Bases de Datos Relacionales** 4 | 🎯 **Objetivos de la clase** 5 | 1. Definir qué es una base de datos. 6 | 2. Identificar los componentes de una base de datos. 7 | 3. Presentar los tipos de bases de datos y su importancia. 8 | 4. Explicar el glosario técnico clave. 9 | 5. Definir qué es una base de datos relacional y sus aspectos generales. 10 | 6. Identificar los componentes de una base de datos relacional. 11 | 12 | --- 13 | 14 | 15 | # **📌 Contenido de la clase** 16 | ## **1️⃣ ¿Qué es una Base de Datos?** 17 | 🎯 **Definición** 18 | Una base de datos (DB) es un conjunto organizado de información que permite almacenar, gestionar y recuperar datos de manera eficiente. 19 | 20 | 📌 **Ejemplo práctico:** 21 | Piensa en una hoja de cálculo donde guardas una lista de clientes con nombres, correos y teléfonos. Si esta información crece demasiado, Excel deja de ser eficiente. Aquí es donde entra una base de datos. 22 | 23 | 📌 **Importancia:** 24 | - Permite almacenar grandes volúmenes de información. 25 | - Facilita el acceso y la manipulación de los datos. 26 | - Asegura la integridad y seguridad de la información. 27 | 28 | --- 29 | 30 | ## **2️⃣ Componentes de una Base de Datos** 31 | 1. **Datos:** Información almacenada en tablas. 32 | 2. **Software de Base de Datos:** Programa que gestiona los datos (Ej.: MySQL, PostgreSQL, SQL Server). 33 | 3. **Usuarios:** Personas o sistemas que interactúan con la base de datos. 34 | 4. **Lenguaje de Consulta:** Como SQL, para manejar los datos. 35 | 36 | 📌 **Ejemplo:** 37 | Una base de datos de una tienda online tiene: 38 | - Tabla `Clientes` (con nombres, correos y teléfonos). 39 | - Tabla `Pedidos` (con productos comprados y montos). 40 | 41 | --- 42 | 43 | ## **3️⃣ Tipos de Bases de Datos y su Importancia** 44 | 📌 **Tipos de bases de datos más comunes:** 45 | 1. **Bases de Datos Relacionales (SQL)**: Organizan datos en tablas relacionadas. Ejemplo: MySQL. 46 | 2. **Bases de Datos No Relacionales (NoSQL)**: Usan documentos o clave-valor (Ej.: MongoDB). 47 | 48 | 📌 **Comparación rápida:** 49 | | Característica | Relacional (SQL) | No Relacional (NoSQL) | 50 | |--------------|-----------------|------------------| 51 | | Estructura | Tablas y relaciones | Documentos o claves | 52 | | Ejemplo | MySQL, PostgreSQL | MongoDB, Firebase | 53 | | Uso típico | Aplicaciones empresariales | Big Data, Apps móviles | 54 | 55 | --- 56 | 57 | ## **4️⃣ Glosario Técnico Clave** 58 | - **SQL (Structured Query Language):** Lenguaje para manejar bases de datos relacionales. 59 | - **Tabla:** Conjunto de datos organizados en filas y columnas. 60 | - **Registro:** Cada fila dentro de una tabla. 61 | - **Campo:** Cada columna dentro de una tabla. 62 | - **Clave Primaria (Primary Key):** Identificador único de cada registro. 63 | - **Clave Foránea (Foreign Key):** Relaciona una tabla con otra. 64 | 65 | 📌 **Ejemplo visual de tabla:** 66 | | ID | Nombre | Email | 67 | |----|--------|----------------| 68 | | 1 | Juan | juan@gmail.com | 69 | | 2 | Ana | ana@gmail.com | 70 | 71 | Aquí, el campo `ID` es la **Clave Primaria**. 72 | 73 | --- 74 | 75 | ## **5️⃣ ¿Qué es una Base de Datos Relacional?** 76 | 🎯 **Definición** 77 | Una base de datos relacional organiza los datos en tablas que pueden relacionarse entre sí mediante claves primarias y claves foráneas. 78 | 79 | 📌 **Ejemplo de Relación entre Tablas:** 80 | 1. **Tabla `Clientes`** 81 | | ClienteID | Nombre | Email | 82 | |----------|--------|----------------| 83 | | 1 | Juan | juan@gmail.com | 84 | | 2 | Ana | ana@gmail.com | 85 | 86 | 2. **Tabla `Pedidos`** 87 | | PedidoID | ClienteID | Producto | 88 | |---------|----------|------------| 89 | | 101 | 1 | Laptop | 90 | | 102 | 2 | Teléfono | 91 | 92 | **Relación:** `Pedidos.ClienteID` es una **Clave Foránea** que conecta con `Clientes.ClienteID`. 93 | 94 | --- 95 | 96 | ## **6️⃣ Ejercicio Práctico en Vivo** 97 | ✍ **Objetivo:** Crear una base de datos simple y hacer consultas en SQL. 98 | 99 | 📌 **Pasos:** 100 | 1. **Crear la base de datos:** 101 | ```sql 102 | CREATE DATABASE Tienda; 103 | USE Tienda; 104 | ``` 105 | 106 | 2. **Crear la tabla `Clientes`:** 107 | ```sql 108 | CREATE TABLE Clientes ( 109 | ClienteID INT PRIMARY KEY, 110 | Nombre VARCHAR(100), 111 | Email VARCHAR(100) UNIQUE 112 | ); 113 | ``` 114 | 115 | 3. **Insertar datos:** 116 | ```sql 117 | INSERT INTO Clientes (ClienteID, Nombre, Email) 118 | VALUES (1, 'Juan Pérez', 'juan@gmail.com'), 119 | (2, 'Ana Gómez', 'ana@gmail.com'); 120 | ``` 121 | 122 | 4. **Consultar datos:** 123 | ```sql 124 | SELECT * FROM Clientes; 125 | ``` 126 | 127 | 📌 **Desafío:** 128 | - Crear una tabla `Pedidos` con `PedidoID`, `ClienteID` y `Producto`. 129 | - Insertar registros en `Pedidos`. 130 | - Hacer una consulta para obtener los pedidos de cada cliente. 131 | 132 | --- 133 | 134 | ## 🧑‍🏫 Profesor 135 | 136 | 👨‍💻 **Alejandro Daniel Di Stefano** 137 | 📌 **Desarrollador Full Stack** 138 | 🔗 **GitHub:** [Drako01](https://github.com/Drako01) -------------------------------------------------------------------------------- /clase_05/Query_Clase_05.sql: -------------------------------------------------------------------------------- 1 | -- Creacion de una vista basica 2 | CREATE VIEW vista_alumnos AS 3 | SELECT nombre, apellido FROM alumnos; 4 | 5 | -- Consultar una Vista 6 | SELECT * FROM vista_alumnos; 7 | 8 | -- Vistas Complejas (Usando JOIN) 9 | 10 | CREATE VIEW view_inscripciones_alumnos AS 11 | SELECT 12 | a.id_alumno, 13 | CONCAT(a.nombre, ' ', a.apellido) AS nombre_completo, 14 | a.email, 15 | c.id_curso, 16 | c.nombre_curso, 17 | i.inscription_at 18 | FROM inscripciones i 19 | JOIN alumnos a ON i.id_alumno = a.id_alumno 20 | JOIN cursos c ON i.id_curso = c.id_curso; 21 | 22 | SELECT * FROM view_inscripciones_alumnos; 23 | 24 | CREATE VIEW view_alumno_completa AS 25 | SELECT 26 | nombre, 27 | apellido, 28 | email, 29 | instituto 30 | FROM alumnos; 31 | 32 | SELECT * FROM view_alumno_completa; 33 | 34 | -- Eliminacion de una Vista 35 | 36 | DROP VIEW view_alumno_completa; 37 | 38 | -- Modificar o Actualizar una Vista con OR REPLACE 39 | 40 | CREATE OR REPLACE VIEW view_alumno_completa AS 41 | SELECT 42 | a.nombre, 43 | a.apellido, 44 | a.email, 45 | a.instituto, 46 | c.nombre_curso, 47 | i.inscription_at 48 | FROM inscripciones i 49 | JOIN alumnos a ON i.id_alumno = a.id_alumno 50 | JOIN cursos c ON i.id_curso = c.id_curso; 51 | 52 | -- Ejecicios de Repaso 53 | 54 | SELECT * FROM cursos; 55 | -- Agregamos columna duracion 56 | ALTER TABLE cursos ADD COLUMN duracion_curso INT DEFAULT 20; 57 | 58 | UPDATE cursos SET duracion_curso = 60 WHERE id_curso = 3; 59 | INSERT INTO cursos (nombre_curso, duracion_curso) VALUES 60 | ("Data Analytics", 120), 61 | ("React", 60), 62 | ("Angular", 80), 63 | ("Python" ,120); 64 | 65 | -- Mostrar todos los cursos que duren más de 20 horas. 66 | SELECT 67 | nombre_curso AS nombre, 68 | duracion_curso AS duracion 69 | FROM cursos 70 | WHERE duracion_curso > 20; 71 | 72 | -- Listar los alumnos cuyo apellido contenga la letra “z”. 73 | SELECT * FROM alumnos; 74 | SELECT * FROM alumnos WHERE UPPER(apellido) LIKE "%Z%"; 75 | SELECT * FROM alumnos WHERE LOWER(apellido) LIKE "%z%"; 76 | SELECT * FROM alumnos WHERE LOWER(apellido) LIKE "%ez%"; 77 | SELECT * FROM alumnos WHERE LOWER(email) LIKE "%gmail.com"; 78 | SELECT * FROM alumnos WHERE LOWER(email) LIKE "ma%"; 79 | 80 | -- Mostrar todos los cursos cuyo nombre empiece en “SQL”. 81 | SELECT * FROM cursos; 82 | INSERT INTO cursos (nombre_curso, duracion_curso) VALUES 83 | ("SQL nivel Basico", 80), 84 | ("SQL nivel Intermedio", 60), 85 | ("SQL nivel Avanzado", 80), 86 | ("SQL Server" ,180); 87 | 88 | SELECT * FROM cursos WHERE LOWER(nombre_curso) LIKE "SQL%"; 89 | 90 | -- Mostrar los primeros 3 cursos en orden alfabético. 91 | SELECT * FROM cursos; 92 | SELECT * FROM cursos 93 | ORDER BY id_curso ASC 94 | LIMIT 3; 95 | 96 | 97 | -- Obtener el promedio de duración de los cursos por categoría. 98 | CREATE TABLE categoria ( 99 | id_categoria INT AUTO_INCREMENT PRIMARY KEY, 100 | nombre_categoria VARCHAR(100) NOT NULL 101 | ); 102 | ALTER TABLE cursos ADD COLUMN id_categoria INT; 103 | ALTER TABLE cursos 104 | ADD CONSTRAINT fk_curso_categoria 105 | FOREIGN KEY (id_categoria) REFERENCES categoria (id_categoria); 106 | 107 | INSERT INTO categoria (nombre_categoria) VALUES 108 | ("Base de Datos"), 109 | ("Programacion"); 110 | 111 | SELECT * FROM categoria; 112 | 113 | SELECT 114 | cat.nombre_categoria, 115 | ROUND(AVG(cur.duracion_curso)) AS promedio_duracion 116 | FROM cursos cur 117 | JOIN categoria cat ON cur.id_categoria = cat.id_categoria 118 | GROUP BY cat.nombre_categoria; 119 | 120 | -- Mostrar la categoría con más cursos asociados. 121 | CREATE VIEW view_categoria_mas_cursos AS 122 | SELECT 123 | cat.nombre_categoria, 124 | COUNT(cur.id_curso) AS cantidad_cursos 125 | FROM categoria cat 126 | LEFT JOIN cursos cur ON cur.id_categoria = cat.id_categoria 127 | GROUP BY cat.id_categoria 128 | ORDER BY cantidad_cursos DESC 129 | LIMIT 1; 130 | 131 | SELECT * FROM view_categoria_mas_cursos; 132 | 133 | -- Crear un trigger que registre en un log cada vez que un alumno se inscribe. 134 | CREATE TABLE log_inscripciones ( 135 | id_log INT AUTO_INCREMENT PRIMARY KEY, 136 | id_alumno INT, 137 | id_curso INT, 138 | fecha_inscripcion DATETIME, 139 | log_timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP 140 | ); 141 | 142 | DELIMITER // 143 | 144 | CREATE TRIGGER tr_log_inscriptios 145 | AFTER INSERT ON inscripciones 146 | FOR EACH ROW 147 | BEGIN 148 | INSERT INTO log_inscripciones (id_alumno, id_curso, fecha_inscripcion) 149 | VALUES (NEW.id_alumno, NEW.id_curso, NEW.inscription_at); 150 | END // 151 | 152 | DELIMITER ; 153 | SELECT * FROM cursos; 154 | SELECT * FROM inscripciones; 155 | SELECT * FROM log_inscripciones; 156 | 157 | INSERT INTO inscripciones (id_alumno, id_curso) VALUES 158 | (4,12), 159 | (4,7); 160 | 161 | -- Listar los cursos junto con la cantidad de alumnos, ordenado de mayor a menor. 162 | CREATE VIEW view_cantidad_alumnos_curso AS 163 | SELECT 164 | c.nombre_curso, 165 | COUNT(i.id_alumno) AS cantidad_alumnos 166 | FROM cursos c 167 | LEFT JOIN inscripciones i ON c.id_curso = i.id_curso 168 | GROUP BY c.id_curso, c.nombre_curso 169 | ORDER BY cantidad_alumnos DESC; 170 | 171 | SELECT * FROM view_cantidad_alumnos_curso; -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 🗄️ SQL - Modalidad Flex | CoderHouse 🏫 2 | 3 |

4 | CoderHouse 5 |

6 | 7 |

8 | 9 | sql 10 | 11 |

12 | 13 | 14 | ## 📌 Comisión **75965** 15 | 16 | 🔹 **Días:** Sábados 17 | 🔹 **Horario:** 11:30 a 13:30 hs 18 | 🔹 **Inicio:** 22/02/2025 19 | 🔹 **Fin:** 10/05/2025 20 | 🔹 **Cantidad de clases:** 12 21 | 22 | --- 23 | 24 | ## 📖 Sobre el Curso 25 | 26 | Este curso de **SQL** en modalidad **Flex** te brindará los conocimientos fundamentales sobre bases de datos relacionales, desde la teoría hasta la práctica con consultas avanzadas. Aprenderás a manejar MySQL y a optimizar estructuras de datos para aplicaciones reales. 27 | 28 | ✅ **Aprenderás sobre:** 29 | ✔️ Creación y modelado de bases de datos 30 | ✔️ Consultas SQL (SELECT, INSERT, UPDATE, DELETE) 31 | ✔️ Relaciones entre tablas 32 | ✔️ Normalización de bases de datos 33 | ✔️ Procedimientos almacenados y funciones 34 | ✔️ Optimización y buenas prácticas 35 | 36 | 📌 **Más información sobre el curso:** 37 | 🔗 [Curso SQL - CoderHouse](https://www.coderhouse.com/ar/cursos/sql) 38 | 39 | --- 40 | 41 | ## 📋 Temario del Curso 42 | 43 | ### **🔹 Unidad 1: Introducción a SQL y Bases de Datos** 44 | ✅ Conceptos básicos de bases de datos 45 | ✅ Tipos de bases de datos: Relacionales vs No Relacionales 46 | ✅ Instalación y configuración de MySQL 47 | ✅ Uso de MySQL Workbench 48 | 49 | ### **🔹 Unidad 2: Creación y Manipulación de Datos** 50 | ✅ Crear bases de datos y tablas (`CREATE DATABASE`, `CREATE TABLE`) 51 | ✅ Tipos de datos en SQL 52 | ✅ Insertar datos (`INSERT INTO`) 53 | ✅ Modificar y eliminar datos (`UPDATE`, `DELETE`) 54 | 55 | ### **🔹 Unidad 3: Consultas Básicas y Filtrado de Datos** 56 | ✅ Seleccionar datos (`SELECT`) 57 | ✅ Filtrar información con `WHERE`, `ORDER BY`, `LIMIT` 58 | ✅ Funciones de agregación (`COUNT`, `SUM`, `AVG`, `MIN`, `MAX`) 59 | ✅ Agrupación de datos con `GROUP BY` y `HAVING` 60 | 61 | ### **🔹 Unidad 4: Relaciones entre Tablas y Claves** 62 | ✅ Claves primarias (`PRIMARY KEY`) y foráneas (`FOREIGN KEY`) 63 | ✅ Tipos de relaciones: **1 a 1, 1 a muchos, muchos a muchos** 64 | ✅ Uso de `JOIN` (`INNER JOIN`, `LEFT JOIN`, `RIGHT JOIN`, `FULL JOIN`) 65 | 66 | ### **🔹 Unidad 5: Normalización y Buenas Prácticas** 67 | ✅ Normalización de bases de datos (1FN, 2FN, 3FN) 68 | ✅ Índices y su impacto en el rendimiento (`INDEX`) 69 | ✅ Vistas (`VIEW`) y su utilidad 70 | 71 | ### **🔹 Unidad 6: Procedimientos, Funciones y Triggers** 72 | ✅ Creación de **Procedimientos Almacenados** 73 | ✅ Creación de **Funciones** en SQL 74 | ✅ Uso de **Triggers** para automatización 75 | 76 | ### **🔹 Unidad 7: Seguridad y Optimización de Consultas** 77 | ✅ Permisos y roles de usuario 78 | ✅ Copias de seguridad y restauración 79 | ✅ Optimización de consultas con **EXPLAIN** y **Índices** 80 | 81 | --- 82 | 83 | 📌 **Programa detallado:** 84 | 🔗 [Descargar Programa](https://drive.google.com/file/d/1SoauqtUY_gWG32e-J7f6FzUfVrD8GWDZ/preview) 85 | 86 | --- 87 | 88 | ## 🛠️ Requisitos 89 | 90 | - PC con acceso a internet 91 | - Instalación de MySQL y MySQL Workbench 92 | - Conocimientos básicos de programación (opcional) 93 | 94 | --- 95 | 96 | 97 | ## 🎓 Proyecto Final - Temática y Diseño 98 | 99 | ### **📌 Consigna** 100 | Para el proyecto final, cada estudiante deberá **elegir una temática** sobre la cual desarrollar una base de datos. El objetivo es pensar en una estructura que refleje la realidad del dominio elegido, aplicando los conceptos aprendidos en el curso. 101 | 102 | 📌 **Ejemplos de temáticas posibles:** 103 | ✔️ Gestión de una tienda online 104 | ✔️ Administración de reservas en un hotel 105 | ✔️ Base de datos para un sistema escolar 106 | ✔️ Plataforma de seguimiento de pacientes en un hospital 107 | ✔️ Sistema de control de inventario 108 | 109 | ### **📌 Aspectos a incluir** 110 | Para la **Clase 04**, comenzaremos a diseñar el **Diagrama Entidad-Relación (DER)** de nuestro proyecto final. 111 | Si bien la estructura puede cambiar a medida que avanzamos, es importante **definir las bases** del modelo desde ahora. 112 | 113 | 🔹 **Elementos clave a considerar:** 114 | ✅ Identificación de **entidades principales** (ej.: clientes, productos, pedidos, empleados). 115 | ✅ Definición de **atributos** relevantes en cada entidad. 116 | ✅ Establecimiento de **relaciones** entre entidades. 117 | ✅ Consideración de **restricciones e integridad de los datos**. 118 | 119 | 📌 **Objetivo:** Construir un modelo sólido que pueda ser implementado en **MySQL**, optimizado y con buenas prácticas. 120 | 121 | --- 122 | 123 | 🚀 **¡Manos a la obra!** Elige una temática que te interese y comencemos a dar forma a tu base de datos. 124 | 125 | 126 | 127 | ## 🧑‍🏫 Profesor 128 | 129 | 👨‍💻 **Alejandro Daniel Di Stefano** 130 | 📌 **Desarrollador Full Stack** 131 | 🔗 **GitHub:** [Drako01](https://github.com/Drako01) 132 | 133 | 📩 Para consultas, puedes escribirme en la plataforma de **CoderHouse** o dejar un mensaje en el repositorio. 🚀 134 | 135 | --- 136 | 137 | 📌 **¡Nos vemos en clase!** 🎓✨ 138 | -------------------------------------------------------------------------------- /clase_08/ejercicios/ejercicios.md: -------------------------------------------------------------------------------- 1 | # Ejercicios Prácticos de SQL - Unidad Completa 2 | 3 | Este documento contiene **50 ejercicios** prácticos para estudiantes principiantes de SQL, organizados por tema y con un enfoque educativo. 4 | 5 | --- 6 | 7 | ## 🏠 Contexto: Institución Educativa 8 | 9 | Usaremos las siguientes tablas para contextualizar los ejercicios: 10 | 11 | ```sql 12 | CREATE TABLE Alumnos ( 13 | id INT PRIMARY KEY, 14 | nombre VARCHAR(100), 15 | apellido VARCHAR(100), 16 | email VARCHAR(100), 17 | fecha_nacimiento DATE 18 | ); 19 | 20 | CREATE TABLE Profesores ( 21 | id INT PRIMARY KEY, 22 | nombre VARCHAR(100), 23 | apellido VARCHAR(100), 24 | especialidad VARCHAR(100) 25 | ); 26 | 27 | CREATE TABLE Cursos ( 28 | id INT PRIMARY KEY, 29 | nombre VARCHAR(100), 30 | profesor_id INT, 31 | FOREIGN KEY (profesor_id) REFERENCES Profesores(id) 32 | ); 33 | 34 | CREATE TABLE Inscripciones ( 35 | id INT PRIMARY KEY, 36 | alumno_id INT, 37 | curso_id INT, 38 | fecha_inscripcion DATE, 39 | FOREIGN KEY (alumno_id) REFERENCES Alumnos(id), 40 | FOREIGN KEY (curso_id) REFERENCES Cursos(id) 41 | ); 42 | 43 | CREATE TABLE Notas ( 44 | id INT PRIMARY KEY, 45 | alumno_id INT, 46 | curso_id INT, 47 | parcial1 DECIMAL(5,2), 48 | parcial2 DECIMAL(5,2), 49 | final DECIMAL(5,2), 50 | FOREIGN KEY (alumno_id) REFERENCES Alumnos(id), 51 | FOREIGN KEY (curso_id) REFERENCES Cursos(id) 52 | ); 53 | ``` 54 | 55 | --- 56 | 57 | ## ✅ DDL - Definición de Estructura (5 ejercicios) 58 | 59 | 1. Crear una tabla de asistencias con fecha, alumno y curso. 60 | 2. Agregar un campo "activo" a la tabla de cursos. 61 | 3. Eliminar el campo "email" de la tabla de profesores. 62 | 4. Cambiar el tipo de dato del campo "nombre" en alumnos a VARCHAR(150). 63 | 5. Crear una tabla para registrar usuarios del sistema (admin, profesor, alumno). 64 | 65 | --- 66 | 67 | ## ✍️ DML - Manipulación de Datos (10 ejercicios) 68 | 69 | 6. Insertar 5 alumnos en la tabla `Alumnos`. 70 | 7. Insertar 3 profesores con diferentes especialidades. 71 | 8. Crear 3 cursos y asignar profesores. 72 | 9. Inscribir alumnos en cursos. 73 | 10. Registrar 2 notas por alumno en cada curso. 74 | 11. Actualizar el apellido de un alumno. 75 | 12. Borrar una inscripción. 76 | 13. Actualizar el profesor de un curso. 77 | 14. Insertar una nota faltante. 78 | 15. Cambiar la nota final de un alumno a 10. 79 | 80 | --- 81 | 82 | ## ⚖️ Funciones Escalares (5 ejercicios) 83 | 84 | 16. Crear una función que calcule el promedio de un alumno dado curso y notas. 85 | 17. Crear una función que calcule el porcentaje de asistencia. 86 | 18. Crear una función que devuelva la edad de un alumno según su fecha de nacimiento. 87 | 19. Crear una función que devuelva "Aprobado" o "Desaprobado" según promedio. 88 | 20. Usar una función en un SELECT para todos los alumnos. 89 | 90 | --- 91 | 92 | ## ⚙️ Stored Procedures (5 ejercicios) 93 | 94 | 21. Crear un procedimiento para registrar una nueva nota. 95 | 22. Crear un procedimiento para inscribir un alumno a un curso. 96 | 23. Crear un procedimiento para cambiar el profesor de un curso. 97 | 24. Crear un procedimiento para borrar todas las inscripciones de un alumno. 98 | 25. Crear un procedimiento para mostrar el resumen de notas de un alumno. 99 | 100 | --- 101 | 102 | ## 🗓 Joins (INNER, LEFT, RIGHT) (5 ejercicios) 103 | 104 | 26. Mostrar los nombres de los alumnos y los cursos en los que están inscritos (INNER JOIN). 105 | 27. Mostrar todos los cursos, aunque no tengan inscriptos (LEFT JOIN). 106 | 28. Mostrar todos los alumnos y sus notas (aunque no tengan notas). 107 | 29. Mostrar profesores y los cursos que dictan. 108 | 30. Mostrar alumnos junto a sus profesores, usando joins entre 3 tablas. 109 | 110 | --- 111 | 112 | ## 🎓 Subconsultas (5 ejercicios) 113 | 114 | 31. Mostrar alumnos con promedio mayor al promedio general. 115 | 32. Mostrar el alumno con la nota más alta en un curso. 116 | 33. Mostrar cursos que no tengan inscriptos. 117 | 34. Mostrar alumnos que están inscritos en más de un curso. 118 | 35. Mostrar profesores que dictan más de un curso. 119 | 120 | --- 121 | 122 | ## ⚠️ Triggers (5 ejercicios) 123 | 124 | 36. Crear un trigger que registre en una tabla de logs cuando se inserta una nueva inscripción. 125 | 37. Crear un trigger que evite que se borre un alumno si tiene inscripciones. 126 | 38. Crear un trigger que actualice un campo "ultimo\_cambio" en notas. 127 | 39. Crear un trigger que bloquee notas mayores a 10. 128 | 40. Crear un trigger que envíe un mensaje (PRINT) al modificar datos en cursos. 129 | 130 | --- 131 | 132 | ## ✏️ Ejercicios de Repaso General (10 ejercicios) 133 | 134 | 41. Mostrar el promedio general de todos los alumnos. 135 | 42. Mostrar cuántos alumnos tiene cada curso. 136 | 43. Listar los cursos con más de 3 inscriptos. 137 | 44. Mostrar los 5 alumnos con mejor promedio. 138 | 45. Listar los alumnos ordenados por edad descendente. 139 | 46. Mostrar alumnos que nunca fueron inscriptos. 140 | 47. Mostrar el promedio de notas por curso. 141 | 48. Mostrar los profesores que no dictan ningún curso. 142 | 49. Listar alumnos y cantidad total de cursos que están cursando. 143 | 50. Crear una vista que muestre: alumno, curso, nombre del profesor y promedio. 144 | 145 | --- 146 | 147 | ## 🔗 Recursos sugeridos 148 | 149 | * [SQL Fiddle](https://sqlfiddle.com/) para probar tus consultas. 150 | * [DB Fiddle](https://www.db-fiddle.com/) para trabajar con MySQL o PostgreSQL. 151 | * [W3Schools SQL](https://www.w3schools.com/sql/) 152 | 153 | --- 154 | 155 | ## 📚 Recomendaciones 156 | 157 | * Siempre respeta las claves foráneas. 158 | * Proba cada instrucción paso a paso. 159 | * Usa `SELECT *` para verificar los cambios. 160 | * Comentá tu código para entenderlo más adelante. 161 | 162 | --- 163 | 164 | ¡A programar! 🚀 165 | 166 | --- 167 | 168 | ## 🧑‍🏫 Profesor 169 | 170 | 👨‍💻 **Alejandro Daniel Di Stefano** 171 | 📌 **Desarrollador Full Stack** 172 | 🔗 **GitHub:** [Drako01](https://github.com/Drako01) 173 | -------------------------------------------------------------------------------- /clase_07/alumnos.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id_alumno": 4, 4 | "nombre": "Alejandro", 5 | "apellido": "Di Stefano", 6 | "email": "alejandro@mail.com", 7 | "dni": 22233355, 8 | "telefono": "115555666", 9 | "nacionalidad": "Argentina", 10 | "fecha_inscripcion": "2025-03-15 12:43:04", 11 | "instituto": "CoderHouse", 12 | "edad": 49 13 | }, 14 | { 15 | "id_alumno": 5, 16 | "nombre": "Juan", 17 | "apellido": "Perez", 18 | "email": "perez@mail.com", 19 | "dni": 113333666, 20 | "telefono": "1166667777", 21 | "nacionalidad": "Argentina", 22 | "fecha_inscripcion": "2025-03-15 12:43:04", 23 | "instituto": "CoderHouse", 24 | "edad": 30 25 | }, 26 | { 27 | "id_alumno": 7, 28 | "nombre": "Marcela", 29 | "apellido": "Mu\u00f1oz", 30 | "email": "ivana@mail.com", 31 | "dni": 33555888, 32 | "telefono": "1166333777", 33 | "nacionalidad": "Argentina", 34 | "fecha_inscripcion": "2025-03-15 12:52:35", 35 | "instituto": "CoderHouse", 36 | "edad": 20 37 | }, 38 | { 39 | "id_alumno": 8, 40 | "nombre": "Marcela", 41 | "apellido": "Perez", 42 | "email": "marce@mail.com", 43 | "dni": 22686777, 44 | "telefono": "12555666", 45 | "nacionalidad": "Uruguaya", 46 | "fecha_inscripcion": "2025-03-15 12:53:52", 47 | "instituto": "CoderHouse", 48 | "edad": 26 49 | }, 50 | { 51 | "id_alumno": 15, 52 | "nombre": "Marcelo", 53 | "apellido": "Perez", 54 | "email": "marcelo@gmail.com", 55 | "dni": 55666677, 56 | "telefono": "1254654", 57 | "nacionalidad": "Uruguaya", 58 | "fecha_inscripcion": "2025-03-15 13:28:56", 59 | "instituto": "CoderHouse", 60 | "edad": 29 61 | }, 62 | { 63 | "id_alumno": 16, 64 | "nombre": "Enzo", 65 | "apellido": "Godoy", 66 | "email": "enzo@mail.com", 67 | "dni": 55996677, 68 | "telefono": "1253354", 69 | "nacionalidad": "Brasilero", 70 | "fecha_inscripcion": "2025-03-15 13:28:56", 71 | "instituto": "CoderHouse", 72 | "edad": 22 73 | }, 74 | { 75 | "id_alumno": 17, 76 | "nombre": "Julian", 77 | "apellido": "Alvarez", 78 | "email": "julian@mail.com", 79 | "dni": 55688677, 80 | "telefono": "1251124", 81 | "nacionalidad": "Peruano", 82 | "fecha_inscripcion": "2025-03-15 13:28:56", 83 | "instituto": "CoderHouse", 84 | "edad": 33 85 | }, 86 | { 87 | "id_alumno": 18, 88 | "nombre": "Cristian", 89 | "apellido": "Diaz", 90 | "email": "cris@gmail.com", 91 | "dni": 55222677, 92 | "telefono": "1111654", 93 | "nacionalidad": "Chileno", 94 | "fecha_inscripcion": "2025-03-15 13:28:56", 95 | "instituto": "CoderHouse", 96 | "edad": 21 97 | }, 98 | { 99 | "id_alumno": 19, 100 | "nombre": "Raul", 101 | "apellido": "Leiva", 102 | "email": "raul@mail.com", 103 | "dni": 55446677, 104 | "telefono": "1251654", 105 | "nacionalidad": "Chileno", 106 | "fecha_inscripcion": "2025-03-15 13:28:56", 107 | "instituto": "CoderHouse", 108 | "edad": 31 109 | }, 110 | { 111 | "id_alumno": 20, 112 | "nombre": "Wanda", 113 | "apellido": "Nara", 114 | "email": "wandaylgante@mail.com", 115 | "dni": 22444488, 116 | "telefono": "4545454", 117 | "nacionalidad": "Argentina", 118 | "fecha_inscripcion": "2025-03-15 13:28:56", 119 | "instituto": "CoderHouse", 120 | "edad": 31 121 | }, 122 | { 123 | "id_alumno": 21, 124 | "nombre": "Romina", 125 | "apellido": "Baron", 126 | "email": "romy@mail.com", 127 | "dni": 53333677, 128 | "telefono": "1254154", 129 | "nacionalidad": "Peruano", 130 | "fecha_inscripcion": "2025-03-15 13:28:56", 131 | "instituto": "CoderHouse", 132 | "edad": 27 133 | }, 134 | { 135 | "id_alumno": 22, 136 | "nombre": "China", 137 | "apellido": "Suarez", 138 | "email": "chinaicardi@gmail.com", 139 | "dni": 22686677, 140 | "telefono": "19955666", 141 | "nacionalidad": "Argentina", 142 | "fecha_inscripcion": "2025-03-15 13:29:43", 143 | "instituto": "CoderHouse", 144 | "edad": 35 145 | }, 146 | { 147 | "id_alumno": 23, 148 | "nombre": "Adrian", 149 | "apellido": "Perez", 150 | "email": "Adrian@mail.com", 151 | "dni": 55669997, 152 | "telefono": "12154654", 153 | "nacionalidad": "Uruguaya", 154 | "fecha_inscripcion": "2025-03-22 12:41:18", 155 | "instituto": "CoderHouse", 156 | "edad": 29 157 | }, 158 | { 159 | "id_alumno": 24, 160 | "nombre": "Andres", 161 | "apellido": "Perez", 162 | "email": "Andres@mail.com", 163 | "dni": 57866677, 164 | "telefono": "12541654", 165 | "nacionalidad": "Uruguaya", 166 | "fecha_inscripcion": "2025-03-22 12:41:18", 167 | "instituto": "CoderHouse", 168 | "edad": 29 169 | }, 170 | { 171 | "id_alumno": 25, 172 | "nombre": "Adrian", 173 | "apellido": "Perez", 174 | "email": "Adrian@gmail.com", 175 | "dni": 556699947, 176 | "telefono": "121454654", 177 | "nacionalidad": "Uruguaya", 178 | "fecha_inscripcion": "2025-03-22 12:42:18", 179 | "instituto": "CoderHouse", 180 | "edad": 29 181 | }, 182 | { 183 | "id_alumno": 26, 184 | "nombre": "Andres", 185 | "apellido": "Perez", 186 | "email": "Andres@gmail.com", 187 | "dni": 574866677, 188 | "telefono": "125414654", 189 | "nacionalidad": "Uruguaya", 190 | "fecha_inscripcion": "2025-03-22 12:42:18", 191 | "instituto": "CoderHouse", 192 | "edad": 29 193 | } 194 | ] -------------------------------------------------------------------------------- /clase_08/SQL_Clase_08.sql: -------------------------------------------------------------------------------- 1 | 2 | -- Sintaxis basica de una Funcion 3 | 4 | /* 5 | CREATE FUNCTION nombre_funcion (parametro1 tipo_de_dato, parametro2 tipo_de_dato) 6 | RETURNS tipo_de_dato 7 | DETERMINISTIC 8 | BEGIN 9 | -- lógica 10 | RETURN resultado; 11 | END; 12 | */ 13 | /* 14 | CREATE TABLE notas( 15 | id INT AUTO_INCREMENT PRIMARY KEY, 16 | alumno_id INT, 17 | parcial1 DECIMAL(5,2), 18 | parcial2 DECIMAL(5,2), 19 | final DECIMAL(5,2) 20 | ); 21 | */ 22 | DELIMITER // 23 | 24 | CREATE FUNCTION calcular_promedio( 25 | p1 DECIMAL(5,2), 26 | p2 DECIMAL(5,2), 27 | p3 DECIMAL(5,2) 28 | ) 29 | RETURNS DECIMAL(5,2) 30 | DETERMINISTIC 31 | BEGIN 32 | DECLARE promedio DECIMAL(5,2); 33 | SET promedio = (p1 + p2 + p3) / 3; 34 | RETURN promedio; 35 | END// 36 | 37 | DELIMITER ; 38 | 39 | -- Insertamos Notas en la Tabla Notas 40 | 41 | INSERT INTO notas (alumno_id, parcial1, parcial2, final) 42 | VALUES 43 | (1, 7.50, 8.00, 9.00), 44 | (2, 5.00, 6.50, 7.00), 45 | (3, 9.00, 10.00, 9.50); 46 | 47 | -- Como usamos la Funcion??? 48 | 49 | SELECT 50 | id, 51 | alumno_id, 52 | parcial1, 53 | parcial2, 54 | final, 55 | calcular_promedio(parcial1, parcial2, final) AS promedio 56 | FROM notas; 57 | 58 | -- Usar funcio por fuera de una Tabla 59 | SELECT calcular_promedio(8, 5, 3) AS promedio; 60 | 61 | -- Stored Procedure (Realiza operaciones Complejas) 62 | 63 | -- Sintaxis de un SP 64 | /* 65 | DELIMITER // 66 | 67 | CREATE PROCEDURE nombre_procedimiento( 68 | IN parametro1 tipo_dato, 69 | IN parametro2 tipo_dato 70 | ) 71 | BEGIN 72 | -- Bloque de codigo SQL que quiero que se ejecute en el SP 73 | END // 74 | 75 | DELIMITER ; 76 | */ 77 | 78 | -- Como llamamos a un SP??? 79 | /* 80 | CALL nombre_procedimiento(valor1, valor2); 81 | */ 82 | 83 | DELIMITER // 84 | 85 | CREATE PROCEDURE agregar_alumno ( 86 | IN p_nombre VARCHAR(30), 87 | IN p_apellido VARCHAR(40), 88 | IN p_email VARCHAR(100), 89 | IN p_dni INT, 90 | IN p_telefono VARCHAR(20), 91 | IN p_edad INT 92 | ) 93 | BEGIN 94 | INSERT INTO alumnos ( 95 | nombre, apellido, email, dni, telefono, edad 96 | ) 97 | VALUES ( 98 | p_nombre, p_apellido, p_email, p_dni, p_telefono, p_edad 99 | ); 100 | END // 101 | 102 | DELIMITER ; 103 | 104 | -- Como lo usamos? 105 | 106 | CALL agregar_alumno('Juan', 'Perez', 'juanperez@mail.com', 12345678, '1166665555', 20); 107 | 108 | 109 | -- Crear el mismo SP pero con logica condicional 110 | 111 | 112 | DELIMITER // 113 | 114 | CREATE PROCEDURE AgregarAlumnoSP ( 115 | IN p_nombre VARCHAR(30), 116 | IN p_apellido VARCHAR(40), 117 | IN p_email VARCHAR(100), 118 | IN p_dni INT, 119 | IN p_telefono VARCHAR(20), 120 | IN p_edad INT, 121 | IN p_nacionalidad VARCHAR(30), 122 | IN p_instituto VARCHAR(60) 123 | ) 124 | BEGIN 125 | DECLARE v_nacionalidad VARCHAR(30); 126 | DECLARE v_instituto VARCHAR(60); 127 | 128 | -- Condicional para Nacionalidad 129 | IF p_nacionalidad IS NULL OR p_nacionalidad = '' THEN 130 | SET v_nacionalidad = "Argentina"; 131 | ELSE 132 | SET v_nacionalidad = p_nacionalidad; 133 | END IF; 134 | 135 | -- Condicional para Instituto 136 | IF p_instituto IS NULL OR p_instituto = '' THEN 137 | SET v_instituto = "CoderHouse"; 138 | ELSE 139 | SET v_instituto = p_instituto; 140 | END IF; 141 | 142 | INSERT INTO alumnos ( 143 | nombre, apellido, email, dni, telefono, edad, nacionalidad, instituto 144 | ) 145 | VALUES ( 146 | p_nombre, p_apellido, p_email, p_dni, p_telefono, p_edad, v_nacionalidad, v_instituto 147 | ); 148 | END // 149 | 150 | DELIMITER ; 151 | 152 | -- Como usarlo?? 153 | 154 | CALL AgregarAlumnoSP('Pedro', 'Lopez', 'pedrito@mail.com', 23232323, '1155554444', 30, '', ''); 155 | 156 | CALL AgregarAlumnoSP('Romina', 'Etchegaray', 'romina@mail.com', 66555444, '222555444', 25, NULL, NULL); 157 | 158 | CALL AgregarAlumnoSP('Romina Lorena', 'Garcia', 'romina2@mail.com', 55666333, '335555666', 25, 'Ururguay', 'Mi Instituto'); 159 | 160 | -- SP para cargar notas 161 | 162 | ALTER TABLE notas ADD COLUMN materia VARCHAR(50) NULL; 163 | 164 | DELIMITER // 165 | 166 | CREATE PROCEDURE RegistrarNotasSP ( 167 | IN p_alumno_id INT , 168 | IN p_parcial1 DECIMAL(5,2), 169 | IN p_parcial2 DECIMAL(5,2), 170 | IN p_final DECIMAL(5,2), 171 | IN p_materia VARCHAR(50) 172 | ) 173 | BEGIN 174 | INSERT INTO notas (alumno_id, parcial1, parcial2, final, materia) 175 | VALUES (p_alumno_id, p_parcial1, p_parcial2, p_final, p_materia); 176 | END // 177 | 178 | DELIMITER ; 179 | 180 | -- Lo usamos 181 | 182 | CALL RegistrarNotasSP(7, 7.50, 8.00, 9.00, 'SQL'); 183 | 184 | CALL RegistrarNotasSP(8, 8.50, 8.50, 10.00, 'SQL'); 185 | 186 | -- SP para actualizar el email solo si el alumno existe 187 | DELIMITER // 188 | 189 | CREATE PROCEDURE ActualizarEmailSoloSiElAlumnoExisteSP( 190 | IN p_id_alumno INT, 191 | IN p_nuevo_email VARCHAR(100) 192 | ) 193 | BEGIN 194 | IF EXISTS (SELECT 1 FROM alumnos WHERE id_alumno = p_id_alumno) THEN 195 | UPDATE alumnos 196 | SET email = p_nuevo_email 197 | WHERE id_alumno = p_id_alumno; 198 | ELSE 199 | SELECT 'El Alumno no Existe' AS mensaje; 200 | END IF; 201 | END // 202 | 203 | DELIMITER ; 204 | 205 | -- Lo usamos 206 | CALL ActualizarEmailSoloSiElAlumnoExisteSP(4, 'nuevoemaildealejandro@mail.com'); 207 | 208 | CALL ActualizarEmailSoloSiElAlumnoExisteSP(1, 'nuevoemaildealejandro@mail.com'); -- Devuelve el mensaje 'El Alumno no Existe' 209 | 210 | -- SP usando WHILE 211 | DELIMITER // 212 | 213 | CREATE PROCEDURE ListarAlumnoSP() 214 | BEGIN 215 | DECLARE contador INT DEFAULT 1; 216 | DECLARE max_id INT; 217 | 218 | -- Obtener el ID maximo 219 | SELECT MAX(id_alumno) INTO max_id FROM alumnos; 220 | 221 | -- Buclue para recorrer Alumnos 222 | WHILE contador <= max_id DO 223 | -- Verifico si el alumno existe 224 | IF EXISTS (SELECT 1 FROM alumnos WHERE id_alumno = contador) THEN 225 | SELECT * FROM alumnos WHERE id_alumno = contador; 226 | END IF; 227 | 228 | -- Incrementar contador en cada vuelta 229 | SET contador = contador + 1; 230 | END WHILE; 231 | END // 232 | 233 | DELIMITER ; 234 | 235 | CALL ListarAlumnoSP(); 236 | -------------------------------------------------------------------------------- /clase_09/SQL_Clase_09.sql: -------------------------------------------------------------------------------- 1 | SELECT * FROM coderhouse2.alumnos; 2 | 3 | CREATE TABLE cursos( 4 | id_curso INT AUTO_INCREMENT PRIMARY KEY, 5 | nombre_curso VARCHAR(100), 6 | descripcion TEXT 7 | ); 8 | 9 | CREATE TABLE inscripciones( 10 | id_inscripcion INT AUTO_INCREMENT PRIMARY KEY, 11 | id_alumno INT, 12 | id_curso INT, 13 | fecha_inscripcion DATE, 14 | FOREIGN KEY (id_alumno) REFERENCES alumnos(id_alumno), 15 | FOREIGN KEY (id_curso) REFERENCES cursos(id_curso) 16 | ); 17 | 18 | CREATE TABLE auditoria_inscripciones( 19 | id_auditoria INT AUTO_INCREMENT PRIMARY KEY, 20 | id_inscripcion INT, 21 | accion VARCHAR(10), 22 | fecha_accion DATETIME 23 | ); 24 | 25 | -- Creamos el Trigger para cada vez que se realice una inscripcion 26 | DELIMITER // 27 | 28 | CREATE TRIGGER after_insert_inscription 29 | AFTER INSERT ON inscripciones 30 | FOR EACH ROW 31 | BEGIN 32 | INSERT INTO auditoria_inscripciones(id_inscripcion, accion, fecha_accion) 33 | VALUES (NEW.id_inscripcion, 'INSERT', NOW()); 34 | END // 35 | 36 | DELIMITER ; 37 | 38 | -- Creamos el Trigger para cada vez que se elimine una inscripcion 39 | DELIMITER // 40 | 41 | CREATE TRIGGER before_delete_inscription 42 | BEFORE DELETE ON inscripciones 43 | FOR EACH ROW 44 | BEGIN 45 | INSERT INTO auditoria_inscripciones(id_inscripcion, accion, fecha_accion) 46 | VALUES (OLD.id_inscripcion, 'DELETE', NOW()); 47 | END // 48 | 49 | DELIMITER ; 50 | 51 | -- Creamos un Trigger para evitar que se modifique la fecha de inscripcion despues de ser registrada 52 | DELIMITER // 53 | 54 | CREATE TRIGGER before_update_inscription 55 | BEFORE UPDATE ON inscripciones 56 | FOR EACH ROW 57 | BEGIN 58 | IF NEW.fecha_inscripcion <> OLD.fecha_inscripcion THEN 59 | SIGNAL SQLSTATE '45000' 60 | SET MESSAGE_TEXT = 'No se permite modificar la fecha de Inscripcion'; 61 | END IF; 62 | END // 63 | 64 | DELIMITER ; 65 | 66 | 67 | -- Vamos a probarlo 68 | 69 | -- Creamos cursos 70 | INSERT INTO cursos(nombre_curso, descripcion) 71 | VALUES ('Base de Datos SQL', 'Curso de fundamentos de base de datos relacionales, usando MySQL y Workbench'); 72 | 73 | SELECT * FROM cursos; 74 | 75 | 76 | -- Insertar una Inscripcion 77 | INSERT INTO inscripciones (id_alumno, id_curso, fecha_inscripcion) 78 | VALUES (18, 1, CURDATE()); 79 | 80 | INSERT INTO inscripciones (id_alumno, id_curso, fecha_inscripcion) 81 | VALUES (19, 1, CURDATE()); 82 | 83 | SELECT * FROM inscripciones; 84 | 85 | -- Verifico el Trigger de cada vez que se realice una inscripcion 86 | SELECT * FROM auditoria_inscripciones WHERE accion = 'INSERT'; 87 | 88 | 89 | -- Eliminar una Inscripcion 90 | DELETE FROM inscripciones WHERE id_inscripcion = 1; 91 | 92 | -- Verifico el Trigger de cada vez que se elimine una inscripcion 93 | SELECT * FROM auditoria_inscripciones WHERE accion = 'DELETE'; 94 | 95 | INSERT INTO inscripciones (id_alumno, id_curso, fecha_inscripcion) 96 | VALUES (20, 1, CURDATE()); 97 | 98 | -- Intentaremos actualizar la fecha de inscripcion 99 | UPDATE inscripciones 100 | SET fecha_inscripcion = DATE_ADD(CURDATE(), INTERVAL 1 DAY) 101 | WHERE id_inscripcion = 3; 102 | 103 | 104 | 105 | SELECT * FROM auditoria_inscripciones ORDER BY fecha_accion DESC; 106 | 107 | 108 | --- Sublenguaje DCL (Data Control Language) 109 | /* 110 | Las sentencia principales son: 111 | - GRANT : Para otorgar Privilegios 112 | - REVOKE : Para revocar privilegios 113 | - CREATE USER : Para crear usuarios 114 | - DROP USER : Para eliminar usuarios 115 | */ 116 | 117 | -- Creacion de Usuarios 118 | /* 119 | CREATE USER 'nombre_usuario'@'localhost' IDENTIFIED BY 'password'; 120 | */ 121 | CREATE USER 'profesor1'@'localhost' IDENTIFIED BY 'password123'; 122 | 123 | -- Permitir al profesor1 ver e insertar datos en la tabla inscripciones 124 | GRANT SELECT, INSERT ON coderhouse2.inscripciones TO 'profesor1'@'localhost'; 125 | 126 | -- Permitir a profesor1 que pueda crear Triggers 127 | GRANT TRIGGER ON coderhouse2.* TO 'profesor1'@'localhost'; 128 | 129 | -- Revocar permisos al profesor1, solo que no pueda insertar mas datos 130 | REVOKE INSERT ON coderhouse2.inscripciones FROM 'profesor1'@'localhost'; 131 | 132 | -- Ver los permisos del Usuario 133 | SHOW GRANTS FOR 'profesor1'@'localhost'; 134 | 135 | -- Eliminar a un Usuario 136 | DROP USER 'profesor1'@'localhost'; 137 | 138 | -- -------------------------------------------------------------------------------------------- 139 | 140 | 141 | -- Ejercicio practico 142 | 143 | CREATE USER 'profesor'@'localhost' IDENTIFIED BY 'password123'; 144 | -- Ver los permisos del Usuario 145 | SHOW GRANTS FOR 'profesor'@'localhost'; 146 | 147 | -- Darle permisos para operar en toda la base de datos coderhouse2 148 | GRANT ALL PRIVILEGES ON coderhouse2.* TO 'profesor'@'localhost'; 149 | 150 | -- Ejercicios 151 | /* 152 | Ejercicio 1 153 | Cree una tabla llamada log_alumnos para registrar inserciones en la tabla alumnos. 154 | 155 | Campos: id_log, id_alumno, accion, fecha_accion 156 | Cree un trigger AFTER INSERT que registre en log_alumnos cada vez que se inserta un nuevo alumno. 157 | */ 158 | 159 | CREATE TABLE logs_alumnos ( 160 | id_log INT AUTO_INCREMENT PRIMARY KEY, 161 | id_alumno INT, 162 | accion VARCHAR(20), 163 | fecha_accion DATETIME 164 | ); 165 | 166 | -- Armamos el Trigger 167 | 168 | DELIMITER // 169 | 170 | CREATE TRIGGER after_insert_alumnos 171 | AFTER INSERT ON alumnos 172 | FOR EACH ROW 173 | BEGIN 174 | INSERT INTO logs_alumnos(id_alumno, accion, fecha_accion) 175 | VALUES (NEW.id_alumno, 'INSERT' , NOW()); 176 | END // 177 | 178 | DELIMITER ; 179 | 180 | -- Probamos insertando un Alumno nuevo 181 | INSERT INTO alumnos (nombre, apellido, email, dni, telefono, nacionalidad,fecha_inscripcion,instituto, edad) 182 | VALUES ('Raul', 'Leiva', 'raul2@mail.com', 22111222, '1166665555', 'Argentino', NOW(), 'CoderHouse', 45); 183 | 184 | /* 185 | Ejercicio 2 186 | Cree un trigger BEFORE DELETE sobre la tabla inscripciones que impida eliminar registros 187 | si la fecha de inscripción es anterior al día actual. 188 | */ 189 | DELIMITER // 190 | 191 | CREATE TRIGGER before_delete_inscription_alert_date 192 | BEFORE DELETE ON inscripciones 193 | FOR EACH ROW 194 | BEGIN 195 | IF OLD.fecha_inscripcion < CURDATE() THEN 196 | SIGNAL SQLSTATE '45000' 197 | SET MESSAGE_TEXT = 'No se puede eliminar una inscripcion anterior al dia de hoy'; 198 | END IF; 199 | END // 200 | 201 | DELIMITER ; 202 | 203 | -------------------------------------------------------------------------------- /clase_04/ejercicios/ejercicios.md: -------------------------------------------------------------------------------- 1 | # 📘 100 Ejercicios de MySQL Workbench - Clase 04 2 | 3 | Este documento contiene **100 ejercicios** para practicar **bases de datos en MySQL** con conceptos como **Stored Procedures, Funciones, Triggers, Vistas, Claves, Tablas y más**. 4 | 5 | --- 6 | 7 | ## 🔹 **1. Creación y Manipulación de Tablas** 8 | 9 | ### 📌 **Ejercicios de Tablas y Claves** 10 | 11 | 1. Crea una base de datos llamada `empresa`. 12 | 2. Crea una tabla `empleados` con los campos: `id_empleado`, `nombre`, `apellido`, `email`, `fecha_contratacion`, `salario`. 13 | 3. Agrega una **clave primaria** en `id_empleado`. 14 | 4. Crea una tabla `departamentos` con `id_departamento`, `nombre_departamento`. 15 | 5. Agrega una **clave foránea** en `empleados` para relacionarla con `departamentos`. 16 | 6. Inserta 5 registros en `departamentos`. 17 | 7. Inserta 10 registros en `empleados`, asignando departamentos aleatorios. 18 | 8. Modifica el salario de todos los empleados en un 10%. 19 | 9. Elimina a un empleado específico por `id_empleado`. 20 | 10. Borra la tabla `empleados` sin afectar `departamentos`. 21 | 22 | --- 23 | 24 | ## 🔹 **2. Consultas SQL y Uso de Claves** 25 | 26 | ### 📌 **Ejercicios de Claves e Índices** 27 | 28 | 11. Crea un **índice** en la columna `email` de `empleados` para mejorar la búsqueda. 29 | 12. Crea una **clave candidata** en `email`. 30 | 13. Crea una **clave concatenada** en `id_empleado` y `id_departamento`. 31 | 14. Consulta todos los empleados de un departamento específico. 32 | 15. Cuenta cuántos empleados hay en cada departamento. 33 | 16. Muestra los empleados con salarios superiores a $5000. 34 | 17. Encuentra el salario promedio de todos los empleados. 35 | 18. Busca empleados cuyo apellido comience con "G". 36 | 19. Encuentra el departamento con más empleados. 37 | 20. Muestra los 3 empleados con los salarios más altos. 38 | 39 | --- 40 | 41 | ## 🔹 **3. Vistas en MySQL** 42 | 43 | ### 📌 **Ejercicios de Creación y Uso de Vistas** 44 | 45 | 21. Crea una vista `vista_empleados` que muestre solo `nombre`, `apellido`, `salario`. 46 | 22. Crea una vista `vista_departamentos` que muestre `id_departamento` y `cantidad de empleados`. 47 | 23. Modifica `vista_empleados` para incluir `fecha_contratacion`. 48 | 24. Usa `vista_empleados` para consultar empleados con salario mayor a $4000. 49 | 25. Crea una vista `vista_altos_salarios` que muestre empleados con salario mayor al promedio. 50 | 26. Borra la vista `vista_altos_salarios`. 51 | 27. Crea una vista `vista_activos` que solo muestre empleados con fecha de contratación dentro del último año. 52 | 28. Usa `vista_activos` para obtener el total de empleados recientes. 53 | 29. Crea una vista con un `JOIN` entre `empleados` y `departamentos`. 54 | 30. Verifica si se pueden modificar los datos a través de la vista anterior. 55 | 56 | --- 57 | 58 | ## 🔹 **4. Stored Procedures (Procedimientos Almacenados)** 59 | 60 | ### 📌 **Ejercicios de Procedimientos Almacenados** 61 | 62 | 31. Crea un procedimiento `insertar_empleado(nombre, apellido, salario)`. 63 | 32. Crea un procedimiento `aumentar_salario(id_empleado, porcentaje)`. 64 | 33. Crea un procedimiento `eliminar_empleado(id_empleado)`. 65 | 34. Crea un procedimiento `total_empleados_por_departamento(id_departamento)`. 66 | 35. Crea un procedimiento `mostrar_salario_promedio()`. 67 | 36. Llama a `mostrar_salario_promedio()` para ver el resultado. 68 | 37. Crea un procedimiento `empleados_recientes(fecha_inicio, fecha_fin)`. 69 | 38. Usa `empleados_recientes('2024-01-01', '2024-12-31')`. 70 | 39. Modifica `insertar_empleado` para que valide si el salario es mayor a 1000. 71 | 40. Borra el procedimiento `eliminar_empleado()`. 72 | 73 | --- 74 | 75 | ## 🔹 **5. Funciones en MySQL** 76 | 77 | ### 📌 **Ejercicios de Creación de Funciones** 78 | 79 | 41. Crea una función `calcular_impuesto(salario) RETURNS DECIMAL(10,2)`. 80 | 42. Crea una función `obtener_nombre_completo(id_empleado) RETURNS VARCHAR(255)`. 81 | 43. Usa `obtener_nombre_completo(5)`. 82 | 44. Crea una función `empleado_mas_antiguo()`. 83 | 45. Crea una función `contar_empleados_por_departamento(id_departamento)`. 84 | 46. Usa `contar_empleados_por_departamento(3)`. 85 | 47. Crea una función `bono_anual(salario) RETURNS DECIMAL(10,2)`. 86 | 48. Usa `bono_anual(5000)`. 87 | 49. Crea una función `salario_total(id_empleado)`, que incluya bono e impuestos. 88 | 50. Verifica si una función puede modificar datos en una tabla. 89 | 90 | --- 91 | 92 | ## 🔹 **6. Triggers en MySQL** 93 | 94 | ### 📌 **Ejercicios de Creación de Triggers** 95 | 96 | 51. Crea un trigger `before_insert_empleado` para validar que el salario sea mayor a 1000. 97 | 52. Crea un trigger `after_insert_empleado` que registre inserciones en una tabla `auditoria`. 98 | 53. Inserta un empleado y verifica la auditoría. 99 | 54. Crea un trigger `before_update_salario` que evite reducciones salariales. 100 | 55. Intenta reducir un salario y observa el error. 101 | 56. Crea un trigger `after_delete_empleado` para guardar registros eliminados en `empleados_eliminados`. 102 | 57. Elimina un empleado y verifica en `empleados_eliminados`. 103 | 58. Crea un trigger `before_insert_departamento` que impida nombres duplicados. 104 | 59. Intenta insertar un departamento duplicado. 105 | 60. Crea un trigger `after_update_departamento` para registrar cambios en nombres de departamentos. 106 | 107 | --- 108 | 109 | ## 🔹 **7. Consultas Avanzadas con JOIN y Subconsultas** 110 | 111 | ### 📌 **Ejercicios de Consultas Complejas** 112 | 113 | 61. Encuentra el empleado con el salario más alto. 114 | 62. Muestra todos los empleados junto con el nombre de su departamento. 115 | 63. Encuentra los empleados que no tienen un departamento asignado. 116 | 64. Muestra empleados con salarios superiores al promedio. 117 | 65. Encuentra los empleados que se contrataron en el mismo mes. 118 | 66. Muestra empleados cuyo salario es mayor que el promedio de su departamento. 119 | 67. Encuentra los 3 departamentos con más empleados. 120 | 68. Muestra los empleados que tienen el mismo apellido. 121 | 69. Encuentra empleados que no han recibido aumento en 2 años. 122 | 70. Muestra empleados con los mismos nombres pero diferentes apellidos. 123 | 124 | --- 125 | 126 | ## 🔹 **8. Creación de un Diagrama E-R** 127 | 128 | ### 📌 **Ejercicios de Modelado de Datos** 129 | 130 | 71. Diseña un diagrama E-R con `empleados`, `departamentos` y `proyectos`. 131 | 72. Agrega relaciones entre `empleados` y `proyectos`. 132 | 73. Agrega una tabla intermedia `empleado_proyecto`. 133 | 74. Genera el código SQL desde MySQL Workbench. 134 | 75. Implementa el esquema en MySQL. 135 | 136 | --- 137 | 138 | ## 🧑‍🏫 Profesor 139 | 140 | 👨‍💻 **Alejandro Daniel Di Stefano** 141 | 📌 **Desarrollador Full Stack** 142 | 🔗 **GitHub:** [Drako01](https://github.com/Drako01) 143 | 144 | -------------------------------------------------------------------------------- /clase_03/teoria/teoria1.md: -------------------------------------------------------------------------------- 1 | # **📘 Curso de SQL - MySQL** 2 | 3 | ## **Índice** 4 | 1. [Introducción](#introducción) 5 | 2. [Unión de Tablas (JOIN)](#unión-de-tablas-join) 6 | 3. [Tipos de Datos en SQL](#tipos-de-datos-en-sql) 7 | 4. [Uso de LIKE y Comodines](#uso-de-like-y-comodines) 8 | 5. [Expresiones Regulares](#expresiones-regulares) 9 | 6. [Subconsultas en SQL](#subconsultas-en-sql) 10 | 7. [Combinación de Subconsultas y Funciones](#combinación-de-subconsultas-y-funciones) 11 | 8. [Data Definition Language (DDL)](#data-definition-language-ddl) 12 | 9. [Sentencias de Manipulación de Objetos](#sentencias-de-manipulación-de-objetos) 13 | 10. [Funciones Escalares en MySQL](#funciones-escalares-en-mysql) 14 | 11. [Ejercicios Prácticos](#ejercicios-prácticos) 15 | 12. [Recursos Adicionales](#recursos-adicionales) 16 | 17 | --- 18 | 19 | ## **Introducción** 20 | Este material de apoyo cubre temas avanzados de SQL en MySQL. Aprenderás cómo combinar tablas, manipular datos y usar funciones avanzadas para optimizar consultas. 21 | 22 | --- 23 | 24 | ## **Unión de Tablas (JOIN)** 25 | Las uniones (`JOIN`) permiten combinar registros de dos o más tablas en una sola consulta. 26 | 27 | ### **Tipos de JOIN** 28 | - **`INNER JOIN`** → Devuelve solo los registros que coinciden en ambas tablas. 29 | - **`LEFT JOIN`** → Devuelve todos los registros de la tabla izquierda y los coincidentes de la derecha. 30 | - **`RIGHT JOIN`** → Devuelve todos los registros de la tabla derecha y los coincidentes de la izquierda. 31 | - **`FULL OUTER JOIN`** → Devuelve todos los registros de ambas tablas (se puede simular con `UNION`). 32 | 33 | ### **Ejemplo Práctico** 34 | ```sql 35 | SELECT a.nombre, a.apellido, c.nombre_curso 36 | FROM alumnos a 37 | INNER JOIN inscripciones i ON a.id_alumno = i.id_alumno 38 | INNER JOIN cursos c ON i.id_curso = c.id_curso; 39 | ``` 40 | 41 | --- 42 | 43 | ## **Tipos de Datos en SQL** 44 | SQL soporta distintos tipos de datos: 45 | - **Numéricos:** `INT`, `DECIMAL`, `FLOAT` 46 | - **Texto:** `VARCHAR(n)`, `TEXT`, `CHAR(n)` 47 | - **Fecha/Hora:** `DATE`, `DATETIME`, `TIMESTAMP` 48 | 49 | ### **Ejemplo de Creación de Tabla** 50 | ```sql 51 | CREATE TABLE productos ( 52 | id_producto INT PRIMARY KEY AUTO_INCREMENT, 53 | nombre VARCHAR(50) NOT NULL, 54 | precio DECIMAL(10,2) NOT NULL, 55 | fecha_ingreso DATE DEFAULT CURRENT_DATE 56 | ); 57 | ``` 58 | 59 | --- 60 | 61 | ## **Uso de LIKE y Comodines** 62 | Se usa `LIKE` para realizar búsquedas flexibles. 63 | 64 | | Comodín | Descripción | 65 | |---------|------------| 66 | | `%` | Cualquier cantidad de caracteres | 67 | | `_` | Un solo carácter | 68 | 69 | ### **Ejemplo Práctico** 70 | ```sql 71 | SELECT * FROM alumnos WHERE nombre LIKE 'A%'; -- Nombres que empiezan con "A" 72 | SELECT * FROM alumnos WHERE email LIKE '%@gmail.com'; -- Emails de Gmail 73 | ``` 74 | 75 | --- 76 | 77 | ## **Expresiones Regulares** 78 | En MySQL, `REGEXP` permite hacer búsquedas avanzadas. 79 | 80 | ### **Ejemplo Práctico** 81 | ```sql 82 | SELECT * FROM alumnos WHERE email REGEXP '^[a-z]+@[a-z]+\\.(com|net)$'; 83 | ``` 84 | 85 | --- 86 | 87 | ## **Subconsultas en SQL** 88 | Las subconsultas permiten usar el resultado de una consulta dentro de otra. 89 | 90 | ### **Tipos de Subconsultas** 91 | 1. **Escalar** → Retorna un solo valor. 92 | 2. **Multifila** → Retorna múltiples valores (`IN`, `EXISTS`). 93 | 94 | ### **Ejemplo Práctico** 95 | ```sql 96 | SELECT nombre, apellido 97 | FROM alumnos 98 | WHERE id_alumno IN (SELECT id_alumno FROM inscripciones); 99 | ``` 100 | 101 | --- 102 | 103 | ## **Combinación de Subconsultas y Funciones** 104 | Se pueden usar funciones dentro de subconsultas. 105 | 106 | ### **Ejemplo Práctico** 107 | ```sql 108 | SELECT nombre, apellido, edad 109 | FROM alumnos 110 | WHERE edad = (SELECT MAX(edad) FROM alumnos); 111 | ``` 112 | 113 | --- 114 | 115 | ## **Data Definition Language (DDL)** 116 | Permite modificar la estructura de la base de datos. 117 | 118 | | Comando | Descripción | 119 | |----------|------------| 120 | | `CREATE` | Crea una tabla o base de datos | 121 | | `DROP` | Elimina una tabla o base de datos | 122 | | `ALTER` | Modifica una tabla | 123 | | `TRUNCATE` | Borra todos los datos de una tabla | 124 | 125 | ### **Ejemplo Práctico** 126 | ```sql 127 | ALTER TABLE alumnos ADD COLUMN direccion VARCHAR(100); 128 | ``` 129 | 130 | --- 131 | 132 | ## **Sentencias de Manipulación de Objetos** 133 | Son comandos usados para eliminar o modificar estructuras. 134 | 135 | ### **Ejemplo Práctico** 136 | ```sql 137 | DROP TABLE inscripciones; 138 | TRUNCATE TABLE alumnos; 139 | ``` 140 | 141 | --- 142 | 143 | ## **Funciones Escalares en MySQL** 144 | Las funciones escalares operan sobre un solo valor. 145 | 146 | ### **Funciones de Cadena** 147 | ```sql 148 | SELECT CONCAT(nombre, ' ', apellido) AS nombre_completo FROM alumnos; 149 | SELECT UCASE(nombre) FROM alumnos; 150 | SELECT LCASE(apellido) FROM alumnos; 151 | SELECT REVERSE(nombre) FROM alumnos; 152 | ``` 153 | 154 | ### **Funciones Numéricas** 155 | ```sql 156 | SELECT ROUND(3.14159, 2); -- 3.14 157 | SELECT CEIL(4.2); -- 5 158 | SELECT FLOOR(4.8); -- 4 159 | SELECT ABS(-10); -- 10 160 | ``` 161 | 162 | ### **Funciones de Fecha** 163 | ```sql 164 | SELECT NOW(); -- Fecha y hora actual 165 | SELECT CURDATE(); -- Solo la fecha actual 166 | SELECT YEAR(fecha_inscripcion) FROM alumnos; 167 | ``` 168 | 169 | --- 170 | 171 | ## **Ejercicios Prácticos** 172 | 1. Encuentra el alumno más joven y el más viejo. 173 | ```sql 174 | SELECT MIN(edad) AS "Más Joven", MAX(edad) AS "Más Adulto" FROM alumnos; 175 | ``` 176 | 177 | 2. Calcula la edad promedio de los alumnos argentinos. 178 | ```sql 179 | SELECT AVG(edad) FROM alumnos WHERE nacionalidad = 'Argentina'; 180 | ``` 181 | 182 | 3. Encuentra los alumnos cuyo apellido termina en "z". 183 | ```sql 184 | SELECT nombre, apellido FROM alumnos WHERE apellido LIKE '%z'; 185 | ``` 186 | 187 | 4. Lista los primeros 5 alumnos ordenados por apellido. 188 | ```sql 189 | SELECT nombre, apellido FROM alumnos ORDER BY apellido ASC LIMIT 5; 190 | ``` 191 | 192 | --- 193 | 194 | ## **Recursos Adicionales** 195 | 📚 **Documentación Oficial de MySQL:** 196 | - [https://dev.mysql.com/doc/](https://dev.mysql.com/doc/) 197 | 198 | 📺 **Cursos en Línea:** 199 | - [W3Schools SQL Tutorial](https://www.w3schools.com/sql/) 200 | 201 | --- 202 | 203 | ## **📌 Conclusión** 204 | - Aprendimos a unir tablas con `JOIN`. 205 | - Exploramos tipos de datos y su uso en MySQL. 206 | - Aplicamos `LIKE`, expresiones regulares y subconsultas. 207 | - Manipulamos estructuras con `DDL` (`ALTER`, `DROP`, `TRUNCATE`). 208 | - Implementamos funciones escalares para trabajar con datos. 209 | 210 | --- 211 | 212 | ## 🧑‍🏫 Profesor 213 | 214 | 👨‍💻 **Alejandro Daniel Di Stefano** 215 | 📌 **Desarrollador Full Stack** 216 | 🔗 **GitHub:** [Drako01](https://github.com/Drako01) 217 | -------------------------------------------------------------------------------- /clase_07/teoria/teoria.md: -------------------------------------------------------------------------------- 1 | # 📚 CLASE: **Importación y Gestión de Datos con MySQL** 2 | 3 | ## 🎯 OBJETIVO 4 | 5 | Que el alumno: 6 | 7 | - Sepa importar datos a MySQL por Workbench y consola. 8 | - Sepa exportar datos de MySQL. 9 | - Entienda **qué es la integridad referencial** y **qué son las restricciones**. 10 | - Aprenda **Delete Cascade** y **Update Cascade**. 11 | - Trabaje con archivos CSV y JSON para importar/exportar datos. 12 | 13 | --- 14 | 15 | # 🧩 PARTE 1 — Conceptos Básicos 16 | 17 | ## 1. ¿Qué es importar datos? 18 | > 19 | > **Importar** = Cargar datos a una base de datos desde un archivo externo (ej: CSV, JSON, SQL, etc). 20 | 21 | **Ejemplo real:** 22 | Imagina que te dan una lista de alumnos en Excel y la quieres cargar en tu base de datos MySQL. Eso sería *importar*. 23 | 24 | --- 25 | 26 | ## 2. ¿Qué es exportar datos? 27 | > 28 | > **Exportar** = Sacar datos de una base de datos y guardarlos en un archivo (para backup, mover datos, etc). 29 | 30 | **Ejemplo real:** 31 | Tienes una base de datos con productos. Quieres pasar esa lista a otro sistema. Exportas a un archivo CSV o SQL. 32 | 33 | --- 34 | 35 | # 🧩 PARTE 2 — Procesos de Importación y Exportación 36 | 37 | ## 3. Exportar contenido en MySQL Workbench 38 | 39 | **Ejemplo paso a paso:** 40 | 41 | 1. Ir a **Workbench** > **Server** > **Data Export**. 42 | 2. Seleccionar base de datos o tablas. 43 | 3. Elegir el formato de exportación (`.sql` generalmente). 44 | 4. Clic en **Start Export**. 45 | 46 | **¿Qué hace esto?** 47 | Crea un archivo `.sql` que tiene todos los comandos para reconstruir esa base de datos. 48 | 49 | --- 50 | 51 | ## 4. Importar contenido en MySQL Workbench 52 | 53 | **Ejemplo paso a paso:** 54 | 55 | 1. Ir a **Workbench** > **Server** > **Data Import**. 56 | 2. Seleccionar el archivo `.sql` a importar. 57 | 3. Indicar si se crea una nueva base de datos o se importa en una existente. 58 | 4. Clic en **Start Import**. 59 | 60 | --- 61 | 62 | ## 5. Importar vía Terminal o Consola 63 | 64 | **Ejemplo simple:** 65 | 66 | ```bash 67 | mysql -u usuario -p basededatos < archivo.sql 68 | ``` 69 | 70 | - `-u usuario`: tu usuario de MySQL. 71 | - `-p`: te pedirá la contraseña. 72 | - `basededatos`: el nombre de la base a donde quieres importar. 73 | - `archivo.sql`: el archivo que quieres importar. 74 | 75 | **Ejemplo real:** 76 | 77 | ```bash 78 | mysql -u root -p mi_base < backup.sql 79 | ``` 80 | 81 | --- 82 | 83 | ## 6. Archivos CSV y JSON 84 | 85 | - **CSV** = Comma Separated Values (valores separados por comas). 86 | - **JSON** = JavaScript Object Notation (estructura de objetos). 87 | 88 | **Ejemplo de CSV:** 89 | 90 | ```csv 91 | id,nombre,edad 92 | 1,Juan,20 93 | 2,Ana,22 94 | ``` 95 | 96 | **Ejemplo de JSON:** 97 | 98 | ```json 99 | [ 100 | { "id": 1, "nombre": "Juan", "edad": 20 }, 101 | { "id": 2, "nombre": "Ana", "edad": 22 } 102 | ] 103 | ``` 104 | 105 | **Cómo generar CSV/JSON:** 106 | 107 | - Usando Excel o Google Sheets (Guardar como CSV). 108 | - Usando Notepad, VSCode, etc (para JSON manualmente). 109 | 110 | --- 111 | 112 | # 🧩 PARTE 3 — Integridad Referencial 113 | 114 | ## 7. ¿Qué es la integridad referencial? 115 | 116 | > Las relaciones entre tablas deben tener sentido lógico. 117 | > No puede existir un "detalle" que apunte a algo que no existe en la tabla "principal". 118 | 119 | **Ejemplo sencillo:** 120 | 121 | - Tabla **Clientes**: 122 | - id_cliente = 1 → Juan 123 | - Tabla **Pedidos**: 124 | - id_pedido = 1, id_cliente = 1 (ok) 125 | - id_pedido = 2, id_cliente = 99 (¿cliente 99? error 🚫) 126 | 127 | --- 128 | 129 | ## 8. Restricciones de Integridad Referencial 130 | 131 | Cuando creas relaciones entre tablas, puedes aplicar restricciones como: 132 | 133 | - **ON DELETE CASCADE**: Si borras un cliente, borras sus pedidos. 134 | - **ON UPDATE CASCADE**: Si cambias el id del cliente, también se actualizan sus pedidos. 135 | 136 | --- 137 | 138 | ## 9. Delete Cascade y Update Cascade 139 | 140 | **Ejemplo práctico:** 141 | 142 | ```sql 143 | CREATE TABLE clientes ( 144 | id_cliente INT PRIMARY KEY, 145 | nombre VARCHAR(50) 146 | ); 147 | 148 | CREATE TABLE pedidos ( 149 | id_pedido INT PRIMARY KEY, 150 | id_cliente INT, 151 | FOREIGN KEY (id_cliente) REFERENCES clientes(id_cliente) 152 | ON DELETE CASCADE 153 | ON UPDATE CASCADE 154 | ); 155 | ``` 156 | 157 | --- 158 | 159 | **¿Qué pasa con esto?** 160 | 161 | - Si borro un cliente ➔ también se borran sus pedidos automáticamente. 162 | - Si cambio el id del cliente ➔ también se actualiza el id en pedidos. 163 | 164 | **Demostración:** 165 | 166 | ```sql 167 | DELETE FROM clientes WHERE id_cliente = 1; 168 | -- automáticamente borra todos los pedidos de ese cliente 169 | ``` 170 | 171 | ```sql 172 | UPDATE clientes SET id_cliente = 10 WHERE id_cliente = 1; 173 | -- automáticamente actualiza los pedidos a id_cliente=10 174 | ``` 175 | 176 | --- 177 | 178 | # 🧩 PARTE 4 — Actividades prácticas en clase 179 | 180 | ## 🔥 Actividad 1 181 | 182 | **Crear estas tablas y probar DELETE CASCADE y UPDATE CASCADE:** 183 | 184 | ```sql 185 | CREATE DATABASE tienda; 186 | USE tienda; 187 | 188 | CREATE TABLE categorias ( 189 | id_categoria INT PRIMARY KEY, 190 | nombre VARCHAR(50) 191 | ); 192 | 193 | CREATE TABLE productos ( 194 | id_producto INT PRIMARY KEY, 195 | nombre VARCHAR(50), 196 | id_categoria INT, 197 | FOREIGN KEY (id_categoria) REFERENCES categorias(id_categoria) 198 | ON DELETE CASCADE 199 | ON UPDATE CASCADE 200 | ); 201 | ``` 202 | 203 | **Insertar datos:** 204 | 205 | ```sql 206 | INSERT INTO categorias VALUES (1, 'Electrónica'), (2, 'Ropa'); 207 | 208 | INSERT INTO productos VALUES (1, 'Celular', 1), (2, 'Camiseta', 2); 209 | ``` 210 | 211 | **Probar:** 212 | 213 | - Borrar una categoría (`DELETE FROM categorias WHERE id_categoria = 1;`). 214 | - Actualizar id de categoría (`UPDATE categorias SET id_categoria = 3 WHERE id_categoria = 2;`). 215 | 216 | --- 217 | 218 | ## 🔥 Actividad 2 219 | 220 | **Importar un CSV a MySQL Workbench** 221 | 222 | 1. Crear tabla: 223 | 224 | ```sql 225 | CREATE TABLE alumnos ( 226 | id INT PRIMARY KEY, 227 | nombre VARCHAR(100), 228 | edad INT 229 | ); 230 | ``` 231 | 232 | 2. Crear un archivo `alumnos.csv`: 233 | 234 | ```csv 235 | id,nombre,edad 236 | 1,Lucas,21 237 | 2,Martina,23 238 | 3,Sebastián,20 239 | ``` 240 | 241 | 3. Importar en Workbench: 242 | > Table Data Import Wizard ➔ elegir archivo ➔ configurar columnas ➔ importar. 243 | 244 | 4. Consultar: 245 | 246 | ```sql 247 | SELECT * FROM alumnos; 248 | ``` 249 | 250 | --- 251 | 252 | # 📋 RESUMEN FINAL 253 | 254 | - Importar = cargar datos externos. 255 | - Exportar = sacar datos. 256 | - Integridad referencial = no permitir errores en relaciones. 257 | - Delete Cascade = borrar en cascada. 258 | - Update Cascade = actualizar en cascada. 259 | 260 | --- 261 | 262 | 263 | ## 🧑‍🏫 Profesor 264 | 265 | 👨‍💻 **Alejandro Daniel Di Stefano** 266 | 📌 **Desarrollador Full Stack** 267 | 🔗 **GitHub:** [Drako01](https://github.com/Drako01) 268 | -------------------------------------------------------------------------------- /clase_03/ejercicios/ejercicios.md: -------------------------------------------------------------------------------- 1 | 2 | # **📘 Ejercicios de SQL - MySQL** 3 | 4 | ## **Índice de Ejercicios** 5 | 1. [Unión de Tablas (JOIN)](#ejercicios-de-unión-de-tablas-join) 6 | 2. [Tipos de Datos en SQL](#ejercicios-de-tipos-de-datos) 7 | 3. [Uso de LIKE y Comodines](#ejercicios-de-like-y-comodines) 8 | 4. [Expresiones Regulares](#ejercicios-de-expresiones-regulares) 9 | 5. [Subconsultas en SQL](#ejercicios-de-subconsultas-en-sql) 10 | 6. [Combinación de Subconsultas y Funciones](#ejercicios-de-combinación-de-subconsultas-y-funciones) 11 | 7. [Data Definition Language (DDL)](#ejercicios-de-data-definition-language-ddl) 12 | 8. [Sentencias de Manipulación de Objetos](#ejercicios-de-manipulación-de-objetos) 13 | 9. [Funciones Escalares](#ejercicios-de-funciones-escalares) 14 | 15 | --- 16 | 17 | ## **Ejercicios de Unión de Tablas (JOIN)** 18 | 19 | 1. **Obtener los nombres y apellidos de los alumnos junto con el nombre del curso en el que están inscritos.** 20 | ```sql 21 | SELECT a.nombre, a.apellido, c.nombre_curso 22 | FROM alumnos a 23 | INNER JOIN inscripciones i ON a.id_alumno = i.id_alumno 24 | INNER JOIN cursos c ON i.id_curso = c.id_curso; 25 | ``` 26 | 2. **Listar los alumnos que no están inscritos en ningún curso.** 27 | ```sql 28 | SELECT a.nombre, a.apellido 29 | FROM alumnos a 30 | LEFT JOIN inscripciones i ON a.id_alumno = i.id_alumno 31 | WHERE i.id_inscripcion IS NULL; 32 | ``` 33 | 3. **Obtener el número total de alumnos por curso.** 34 | ```sql 35 | SELECT c.nombre_curso, COUNT(i.id_alumno) AS cantidad_alumnos 36 | FROM cursos c 37 | LEFT JOIN inscripciones i ON c.id_curso = i.id_curso 38 | GROUP BY c.nombre_curso; 39 | ``` 40 | 41 | --- 42 | 43 | ## **Ejercicios de Tipos de Datos** 44 | 45 | 1. **Agregar un nuevo campo `promedio_final` de tipo `DECIMAL(5,2)` a la tabla `alumnos`.** 46 | ```sql 47 | ALTER TABLE alumnos ADD COLUMN promedio_final DECIMAL(5,2); 48 | ``` 49 | 2. **Modificar el campo `telefono` para que acepte solo números enteros de hasta 15 dígitos.** 50 | ```sql 51 | ALTER TABLE alumnos MODIFY COLUMN telefono BIGINT(15); 52 | ``` 53 | 3. **Insertar un nuevo alumno y verificar que los tipos de datos se respeten.** 54 | ```sql 55 | INSERT INTO alumnos (nombre, apellido, email, dni, telefono, edad) 56 | VALUES ('Lucas', 'González', 'lucas@mail.com', 22334455, 1133344556, 22); 57 | ``` 58 | 59 | --- 60 | 61 | ## **Ejercicios de LIKE y Comodines** 62 | 63 | 1. **Encontrar todos los alumnos cuyo nombre comienza con "M".** 64 | ```sql 65 | SELECT * FROM alumnos WHERE nombre LIKE 'M%'; 66 | ``` 67 | 2. **Obtener los alumnos cuyo email contiene "gmail".** 68 | ```sql 69 | SELECT * FROM alumnos WHERE email LIKE '%gmail%'; 70 | ``` 71 | 3. **Buscar los alumnos cuyo apellido termine con "z".** 72 | ```sql 73 | SELECT * FROM alumnos WHERE apellido LIKE '%z'; 74 | ``` 75 | 4. **Listar los alumnos cuyo teléfono empieza con "11".** 76 | ```sql 77 | SELECT * FROM alumnos WHERE telefono LIKE '11%'; 78 | ``` 79 | 80 | --- 81 | 82 | ## **Ejercicios de Expresiones Regulares** 83 | 84 | 1. **Obtener los alumnos con un email válido que termine en `.com` o `.net`.** 85 | ```sql 86 | SELECT * FROM alumnos WHERE email REGEXP '^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.(com|net)$'; 87 | ``` 88 | 2. **Buscar los alumnos cuyos nombres tengan solo letras mayúsculas.** 89 | ```sql 90 | SELECT * FROM alumnos WHERE nombre REGEXP '^[A-Z]+$'; 91 | ``` 92 | 3. **Filtrar alumnos con un DNI de exactamente 8 dígitos.** 93 | ```sql 94 | SELECT * FROM alumnos WHERE dni REGEXP '^[0-9]{8}$'; 95 | ``` 96 | 97 | --- 98 | 99 | ## **Ejercicios de Subconsultas en SQL** 100 | 101 | 1. **Obtener el alumno más joven.** 102 | ```sql 103 | SELECT * FROM alumnos WHERE edad = (SELECT MIN(edad) FROM alumnos); 104 | ``` 105 | 2. **Encontrar los alumnos mayores de edad inscritos en algún curso.** 106 | ```sql 107 | SELECT * FROM alumnos WHERE edad >= 18 AND id_alumno IN (SELECT id_alumno FROM inscripciones); 108 | ``` 109 | 3. **Contar cuántos alumnos tienen más de 25 años.** 110 | ```sql 111 | SELECT COUNT(*) FROM alumnos WHERE edad > 25; 112 | ``` 113 | 114 | --- 115 | 116 | ## **Ejercicios de Combinación de Subconsultas y Funciones** 117 | 118 | 1. **Obtener la edad promedio de los alumnos inscritos en cursos.** 119 | ```sql 120 | SELECT AVG(edad) FROM alumnos WHERE id_alumno IN (SELECT id_alumno FROM inscripciones); 121 | ``` 122 | 2. **Determinar cuántos alumnos argentinos hay en la base de datos.** 123 | ```sql 124 | SELECT COUNT(*) FROM alumnos WHERE nacionalidad = 'Argentina'; 125 | ``` 126 | 3. **Encontrar la edad mínima y máxima por nacionalidad.** 127 | ```sql 128 | SELECT nacionalidad, MIN(edad) AS menor_edad, MAX(edad) AS mayor_edad 129 | FROM alumnos GROUP BY nacionalidad; 130 | ``` 131 | 132 | --- 133 | 134 | ## **Ejercicios de Data Definition Language (DDL)** 135 | 136 | 1. **Crear una tabla `profesores` con las siguientes columnas:** 137 | - `id_profesor` (INT, clave primaria, autoincremental) 138 | - `nombre` (VARCHAR(50)) 139 | - `apellido` (VARCHAR(50)) 140 | - `email` (VARCHAR(100), único) 141 | ```sql 142 | CREATE TABLE profesores ( 143 | id_profesor INT PRIMARY KEY AUTO_INCREMENT, 144 | nombre VARCHAR(50) NOT NULL, 145 | apellido VARCHAR(50) NOT NULL, 146 | email VARCHAR(100) UNIQUE NOT NULL 147 | ); 148 | ``` 149 | 2. **Eliminar la tabla `profesores` si existe.** 150 | ```sql 151 | DROP TABLE IF EXISTS profesores; 152 | ``` 153 | 154 | --- 155 | 156 | ## **Ejercicios de Manipulación de Objetos** 157 | 158 | 1. **Vaciar completamente la tabla `alumnos` sin eliminar su estructura.** 159 | ```sql 160 | TRUNCATE TABLE alumnos; 161 | ``` 162 | 2. **Eliminar todos los alumnos menores de 18 años.** 163 | ```sql 164 | DELETE FROM alumnos WHERE edad < 18; 165 | ``` 166 | 167 | --- 168 | 169 | ## **Ejercicios de Funciones Escalares** 170 | 171 | 1. **Concatenar nombre y apellido en una sola columna llamada `nombre_completo`.** 172 | ```sql 173 | SELECT CONCAT(nombre, ' ', apellido) AS nombre_completo FROM alumnos; 174 | ``` 175 | 2. **Convertir todos los nombres a mayúsculas.** 176 | ```sql 177 | SELECT UCASE(nombre) FROM alumnos; 178 | ``` 179 | 3. **Obtener la fecha actual.** 180 | ```sql 181 | SELECT NOW(); 182 | ``` 183 | 4. **Obtener la suma total de edades de los alumnos.** 184 | ```sql 185 | SELECT SUM(edad) FROM alumnos; 186 | ``` 187 | 5. **Redondear el promedio de edades a 2 decimales.** 188 | ```sql 189 | SELECT ROUND(AVG(edad), 2) FROM alumnos; 190 | ``` 191 | 192 | --- 193 | 194 | 🚀 **¡A practicar y mejorar tus habilidades en SQL!** 195 | 196 | --- 197 | 198 | ## 🧑‍🏫 Profesor 199 | 200 | 👨‍💻 **Alejandro Daniel Di Stefano** 201 | 📌 **Desarrollador Full Stack** 202 | 🔗 **GitHub:** [Drako01](https://github.com/Drako01) -------------------------------------------------------------------------------- /clase_10/backup/coderhouse_inscripciones.sql: -------------------------------------------------------------------------------- 1 | -- MySQL dump 10.13 Distrib 8.0.41, for Win64 (x86_64) 2 | -- 3 | -- Host: 127.0.0.1 Database: coderhouse 4 | -- ------------------------------------------------------ 5 | -- Server version 8.0.41 6 | 7 | /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; 8 | /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; 9 | /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; 10 | /*!50503 SET NAMES utf8 */; 11 | /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; 12 | /*!40103 SET TIME_ZONE='+00:00' */; 13 | /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; 14 | /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; 15 | /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; 16 | /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; 17 | 18 | -- 19 | -- Table structure for table `inscripciones` 20 | -- 21 | 22 | DROP TABLE IF EXISTS `inscripciones`; 23 | /*!40101 SET @saved_cs_client = @@character_set_client */; 24 | /*!50503 SET character_set_client = utf8mb4 */; 25 | CREATE TABLE `inscripciones` ( 26 | `id_alumno` int NOT NULL, 27 | `id_curso` int NOT NULL, 28 | `inscription_at` datetime DEFAULT CURRENT_TIMESTAMP, 29 | PRIMARY KEY (`id_alumno`,`id_curso`), 30 | KEY `id_curso` (`id_curso`), 31 | CONSTRAINT `inscripciones_ibfk_1` FOREIGN KEY (`id_alumno`) REFERENCES `alumnos` (`id_alumno`), 32 | CONSTRAINT `inscripciones_ibfk_2` FOREIGN KEY (`id_curso`) REFERENCES `cursos` (`id_curso`) 33 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; 34 | /*!40101 SET character_set_client = @saved_cs_client */; 35 | 36 | -- 37 | -- Dumping data for table `inscripciones` 38 | -- 39 | 40 | LOCK TABLES `inscripciones` WRITE; 41 | /*!40000 ALTER TABLE `inscripciones` DISABLE KEYS */; 42 | INSERT INTO `inscripciones` VALUES (4,1,'2023-03-22 13:10:38'),(4,2,'2025-03-29 13:13:26'),(4,3,'2025-03-22 13:10:38'),(4,7,'2025-04-05 13:22:02'),(4,12,'2025-04-05 13:22:02'),(8,1,'2023-03-22 13:10:38'),(8,2,'2025-03-22 13:10:38'),(19,1,'2025-03-22 13:10:38'),(21,1,'2023-03-22 13:10:38'),(21,4,'2025-03-22 13:10:38'),(22,1,'2023-03-22 13:10:38'),(22,2,'2025-03-29 13:14:56'),(22,3,'2025-03-29 13:14:56'); 43 | /*!40000 ALTER TABLE `inscripciones` ENABLE KEYS */; 44 | UNLOCK TABLES; 45 | /*!50003 SET @saved_cs_client = @@character_set_client */ ; 46 | /*!50003 SET @saved_cs_results = @@character_set_results */ ; 47 | /*!50003 SET @saved_col_connection = @@collation_connection */ ; 48 | /*!50003 SET character_set_client = utf8mb4 */ ; 49 | /*!50003 SET character_set_results = utf8mb4 */ ; 50 | /*!50003 SET collation_connection = utf8mb4_0900_ai_ci */ ; 51 | /*!50003 SET @saved_sql_mode = @@sql_mode */ ; 52 | /*!50003 SET sql_mode = 'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION' */ ; 53 | DELIMITER ;; 54 | /*!50003 CREATE*/ /*!50017 DEFINER=`root`@`localhost`*/ /*!50003 TRIGGER `before_inscription_insert` BEFORE INSERT ON `inscripciones` FOR EACH ROW BEGIN 55 | DECLARE existe INT; 56 | 57 | SELECT COUNT(*) INTO existe 58 | FROM inscripciones 59 | WHERE id_alumno = NEW.id_alumno AND id_curso = NEW.id_curso; 60 | 61 | -- Si ya existe 62 | IF existe > 0 THEN 63 | SIGNAL SQLSTATE '45000' 64 | SET MESSAGE_TEXT = 'El Alumno ya esta inscripto a este curso'; 65 | END IF; 66 | END */;; 67 | DELIMITER ; 68 | /*!50003 SET sql_mode = @saved_sql_mode */ ; 69 | /*!50003 SET character_set_client = @saved_cs_client */ ; 70 | /*!50003 SET character_set_results = @saved_cs_results */ ; 71 | /*!50003 SET collation_connection = @saved_col_connection */ ; 72 | /*!50003 SET @saved_cs_client = @@character_set_client */ ; 73 | /*!50003 SET @saved_cs_results = @@character_set_results */ ; 74 | /*!50003 SET @saved_col_connection = @@collation_connection */ ; 75 | /*!50003 SET character_set_client = utf8mb4 */ ; 76 | /*!50003 SET character_set_results = utf8mb4 */ ; 77 | /*!50003 SET collation_connection = utf8mb4_0900_ai_ci */ ; 78 | /*!50003 SET @saved_sql_mode = @@sql_mode */ ; 79 | /*!50003 SET sql_mode = 'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION' */ ; 80 | DELIMITER ;; 81 | /*!50003 CREATE*/ /*!50017 DEFINER=`root`@`localhost`*/ /*!50003 TRIGGER `after_inscription_insert` AFTER INSERT ON `inscripciones` FOR EACH ROW BEGIN 82 | DECLARE curso_count INT; 83 | SELECT cantidad_inscripciones INTO curso_count 84 | FROM cursos_inscripciones_count 85 | WHERE id_curso = NEW.id_curso; 86 | 87 | -- Validamos si existen los valores 88 | IF curso_count IS NULL THEN 89 | INSERT INTO cursos_inscripciones_count (id_curso, cantidad_inscripciones) 90 | VALUES (NEW.id_curso, 1); 91 | ELSE 92 | UPDATE cursos_inscripciones_count 93 | SET cantidad_inscripciones = cantidad_inscripciones + 1 94 | WHERE id_curso = NEW.id_curso; 95 | END IF; 96 | END */;; 97 | DELIMITER ; 98 | /*!50003 SET sql_mode = @saved_sql_mode */ ; 99 | /*!50003 SET character_set_client = @saved_cs_client */ ; 100 | /*!50003 SET character_set_results = @saved_cs_results */ ; 101 | /*!50003 SET collation_connection = @saved_col_connection */ ; 102 | /*!50003 SET @saved_cs_client = @@character_set_client */ ; 103 | /*!50003 SET @saved_cs_results = @@character_set_results */ ; 104 | /*!50003 SET @saved_col_connection = @@collation_connection */ ; 105 | /*!50003 SET character_set_client = utf8mb4 */ ; 106 | /*!50003 SET character_set_results = utf8mb4 */ ; 107 | /*!50003 SET collation_connection = utf8mb4_0900_ai_ci */ ; 108 | /*!50003 SET @saved_sql_mode = @@sql_mode */ ; 109 | /*!50003 SET sql_mode = 'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION' */ ; 110 | DELIMITER ;; 111 | /*!50003 CREATE*/ /*!50017 DEFINER=`root`@`localhost`*/ /*!50003 TRIGGER `tr_log_inscriptios` AFTER INSERT ON `inscripciones` FOR EACH ROW BEGIN 112 | INSERT INTO log_inscripciones (id_alumno, id_curso, fecha_inscripcion) 113 | VALUES (NEW.id_alumno, NEW.id_curso, NEW.inscription_at); 114 | END */;; 115 | DELIMITER ; 116 | /*!50003 SET sql_mode = @saved_sql_mode */ ; 117 | /*!50003 SET character_set_client = @saved_cs_client */ ; 118 | /*!50003 SET character_set_results = @saved_cs_results */ ; 119 | /*!50003 SET collation_connection = @saved_col_connection */ ; 120 | /*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; 121 | 122 | /*!40101 SET SQL_MODE=@OLD_SQL_MODE */; 123 | /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; 124 | /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; 125 | /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; 126 | /*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; 127 | /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; 128 | /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; 129 | 130 | -- Dump completed on 2025-05-24 12:48:48 131 | -------------------------------------------------------------------------------- /clase_06/ejercicios/ejercicios.md: -------------------------------------------------------------------------------- 1 | # Ejercicios de DDL y Subconsultas: 2 | 3 | 4 | - **DDL (Data Definition Language)**: `CREATE`, `ALTER`, `DROP`, etc. 5 | - **DML (Data Manipulation Language)**: `INSERT`, `UPDATE`, `DELETE`, `SELECT` 6 | - **Subconsultas** 7 | - **Inserciones parciales** 8 | - **Errores comunes al eliminar registros (por restricciones de integridad referencial)** 9 | 10 | Voy a dividirlos en secciones temáticas para que estén organizados: 11 | 12 | --- 13 | 14 | ### 🏗️ **SECCIÓN 1: DDL - Crear estructuras (20 ejercicios)** 15 | 16 | 1. Crear una tabla `usuarios` con `id`, `nombre`, `email`, `fecha_nacimiento`. 17 | 2. Crear una tabla `productos` con `id`, `nombre`, `precio`, `stock`. 18 | 3. Crear una tabla `pedidos` con `id`, `usuario_id`, `fecha`. 19 | 4. Crear una tabla `detalle_pedidos` con `id`, `pedido_id`, `producto_id`, `cantidad`, `precio_unitario`. 20 | 5. Crear una tabla `categorias` y relacionarla con `productos`. 21 | 6. Agregar una columna `telefono` a `usuarios`. 22 | 7. Modificar el tipo de dato de `precio` en `productos` a `DECIMAL(10,2)`. 23 | 8. Agregar una restricción `UNIQUE` sobre `email` en `usuarios`. 24 | 9. Crear una clave foránea en `pedidos` hacia `usuarios`. 25 | 10. Crear una clave foránea en `detalle_pedidos` hacia `productos`. 26 | 11. Crear una clave foránea en `detalle_pedidos` hacia `pedidos`. 27 | 12. Crear una tabla `comentarios` con relación a `usuarios` y `productos`. 28 | 13. Crear una tabla intermedia `usuarios_roles` para una relación N:N entre `usuarios` y `roles`. 29 | 14. Eliminar la columna `telefono` de `usuarios`. 30 | 15. Eliminar la tabla `comentarios`. 31 | 16. Crear una tabla `direcciones` con una restricción `CHECK` para que el país sea “AR” o “UY”. 32 | 17. Usar `AUTO_INCREMENT` en una tabla `envios`. 33 | 18. Crear una vista `vista_usuarios_activos`. 34 | 19. Crear un índice en `productos(nombre)`. 35 | 20. Crear una tabla `logs` con una columna `timestamp` por defecto. 36 | 37 | --- 38 | 39 | ### 📝 **SECCIÓN 2: DML - Manipular datos (25 ejercicios)** 40 | 41 | 21. Insertar 3 usuarios. 42 | 22. Insertar 5 productos con diferentes precios. 43 | 23. Insertar parcialmente un usuario (solo nombre y email). 44 | 24. Insertar parcialmente un producto (nombre y stock). 45 | 25. Insertar un pedido con su detalle. 46 | 26. Actualizar el precio de todos los productos aumentando un 10%. 47 | 27. Cambiar el email de un usuario específico. 48 | 28. Eliminar un producto por ID. 49 | 29. Eliminar un usuario que tiene pedidos (¡provoca error!). 50 | 30. Insertar un producto con `NULL` en precio (probar si está permitido). 51 | 31. Insertar un detalle de pedido con cantidad `0` (con `CHECK` activado). 52 | 32. Insertar varios usuarios con `INSERT INTO ... VALUES (...), (...), (...);` 53 | 33. Insertar una dirección para un usuario existente. 54 | 34. Actualizar todos los usuarios nacidos antes del 2000. 55 | 35. Incrementar el stock de un producto en 20 unidades. 56 | 36. Eliminar todos los pedidos anteriores a una fecha. 57 | 37. Insertar un comentario sobre un producto. 58 | 38. Insertar un log con la fecha actual por defecto. 59 | 39. Eliminar un producto que tiene detalles de pedido (¡provoca error!). 60 | 40. Insertar una fila con clave foránea que no existe (¡provoca error!). 61 | 41. Insertar datos con funciones como `NOW()`, `UUID()`. 62 | 42. Copiar todos los productos caros a una tabla `productos_premium`. 63 | 43. Insertar un producto sin nombre (¡provoca error! si es `NOT NULL`). 64 | 44. Insertar un usuario con un email duplicado (¡provoca error!). 65 | 45. Actualizar el `stock` de un producto basado en una subconsulta de ventas. 66 | 67 | --- 68 | 69 | ### 🔎 **SECCIÓN 3: SELECT y Subconsultas (25 ejercicios)** 70 | 71 | 46. Listar todos los usuarios. 72 | 47. Listar productos cuyo precio es mayor al promedio. 73 | 48. Listar usuarios que han hecho pedidos. 74 | 49. Listar productos con menos de 10 en stock. 75 | 50. Obtener los 3 productos más caros. 76 | 51. Obtener el total de pedidos por usuario. 77 | 52. Obtener el total facturado por pedido. 78 | 53. Obtener la suma total facturada por usuario. 79 | 54. Listar los productos de un pedido usando JOIN. 80 | 55. Listar pedidos con sus usuarios y totales. 81 | 56. Usar subconsulta correlacionada para obtener el último pedido de cada usuario. 82 | 57. Listar usuarios que no han hecho pedidos. 83 | 58. Mostrar productos que nunca se han vendido. 84 | 59. Obtener la media de precio por categoría. 85 | 60. Listar los productos que están en más de 1 pedido. 86 | 61. Mostrar la fecha del primer pedido. 87 | 62. Mostrar la cantidad total de ventas por producto. 88 | 63. Mostrar el producto más vendido. 89 | 64. Mostrar los 5 usuarios con más compras. 90 | 65. Listar productos con stock mayor al promedio. 91 | 66. Listar todos los pedidos hechos en los últimos 30 días. 92 | 67. Obtener los pedidos con más de 3 productos. 93 | 68. Obtener usuarios que hayan comprado productos de la categoría "Electrónica". 94 | 69. Subconsulta para traer usuarios con más de 2 pedidos. 95 | 70. Subconsulta para traer productos que tienen precio igual al más caro. 96 | 97 | --- 98 | 99 | ### 🧩 **SECCIÓN 4: Subconsultas en `INSERT`, `UPDATE`, `DELETE` (15 ejercicios)** 100 | 101 | 71. Insertar en `logs` todos los usuarios con pedidos. 102 | 72. Actualizar `stock` de productos restando lo vendido (usando subconsulta). 103 | 73. Eliminar productos que nunca se han vendido (subconsulta `NOT IN`). 104 | 74. Insertar en `productos_backup` todos los productos caros (subconsulta). 105 | 75. Insertar en `clientes_vip` los usuarios con más de 5 pedidos. 106 | 76. Eliminar usuarios sin pedidos (subconsulta). 107 | 77. Actualizar a “descontinuado” los productos sin ventas recientes. 108 | 78. Insertar en `usuarios_mayores` todos los usuarios mayores de 30 años. 109 | 79. Insertar con `SELECT` productos con stock > 100. 110 | 80. Eliminar direcciones sin usuarios asociados. 111 | 81. Insertar en `comentarios_backup` los comentarios de productos eliminados. 112 | 82. Actualizar emails de prueba con dominio “@test.com”. 113 | 83. Eliminar pedidos sin detalles (usando `NOT EXISTS`). 114 | 84. Insertar en `usuarios_sin_telefono` aquellos con `telefono IS NULL`. 115 | 85. Insertar en `envios` todos los pedidos con fecha de hoy. 116 | 117 | --- 118 | 119 | ### 🧨 **SECCIÓN 5: Errores comunes y manejo (15 ejercicios)** 120 | 121 | 86. Eliminar un usuario con pedidos (viola FK). 122 | 87. Insertar un pedido con `usuario_id` inexistente (viola FK). 123 | 88. Insertar producto sin nombre (`NOT NULL`). 124 | 89. Insertar usuario con email duplicado (`UNIQUE`). 125 | 90. Eliminar producto con detalles en `detalle_pedidos` (viola FK). 126 | 91. Insertar detalle de pedido con cantidad negativa (viola `CHECK`). 127 | 92. Eliminar un pedido sin detalles (debería funcionar). 128 | 93. Insertar pedido con `NULL` en `fecha` (si no es `NOT NULL`, pasa). 129 | 94. Eliminar `categoria` que tiene productos asociados (viola FK). 130 | 95. Insertar dirección con país inválido (viola `CHECK`). 131 | 96. Eliminar `usuario` con comentarios (viola FK). 132 | 97. Eliminar `producto` que aparece en `comentarios`. 133 | 98. Eliminar todos los datos de una tabla sin `DELETE CASCADE`. 134 | 99. Crear tabla con tipo de dato inválido (`VARCHAR(-5)`). 135 | 100. Insertar `fecha_nacimiento` con formato incorrecto (`"31-02-2024"`). 136 | 137 | 138 | --- 139 | 140 | 141 | ## 🧑‍🏫 Profesor 142 | 143 | 👨‍💻 **Alejandro Daniel Di Stefano** 144 | 📌 **Desarrollador Full Stack** 145 | 🔗 **GitHub:** [Drako01](https://github.com/Drako01) 146 | -------------------------------------------------------------------------------- /clase_11/teoria.md: -------------------------------------------------------------------------------- 1 | # Clase 11 2 | 3 | ## 📘 1. Introducción al Data Warehouse (DW) 4 | 5 | ### ¿Qué es un Data Warehouse? 6 | 7 | Un Data Warehouse es un sistema que centraliza y consolida grandes volúmenes de datos provenientes de múltiples fuentes, permitiendo su análisis y consulta eficiente. Se caracteriza por ser: 8 | 9 | * **Orientado a temas**: Organiza los datos por áreas de interés (ventas, clientes, etc.). 10 | * **Integrado**: Combina datos de diferentes fuentes en un formato coherente. 11 | * **No volátil**: Una vez almacenados, los datos no se modifican. 12 | * **Variable en el tiempo**: Almacena datos históricos para análisis a lo largo del tiempo. 13 | 14 | ### Componentes principales de un DW 15 | 16 | 1. **Fuentes de datos**: Sistemas operacionales, archivos planos, APIs, etc. 17 | 2. **Proceso ETL (Extract, Transform, Load)**: Extrae datos de las fuentes, los transforma y los carga en el DW. 18 | 3. **Almacén de datos**: Base de datos centralizada (en este caso, MySQL). 19 | 4. **Metadatos**: Información sobre la estructura y el significado de los datos. 20 | 5. **Herramientas de acceso**: Aplicaciones para consulta y análisis de datos. 21 | 22 | ### Ejemplo práctico en MySQL Workbench 23 | 24 | Utilizando MySQL Workbench, puedes diseñar un esquema de estrella (star schema) que incluye:([Stack Overflow][1]) 25 | 26 | * **Tabla de hechos**: Contiene datos cuantitativos (por ejemplo, ventas). 27 | * **Tablas de dimensiones**: Contienen datos descriptivos relacionados (por ejemplo, clientes, productos, tiempo). 28 | 29 | Este enfoque facilita la realización de consultas analíticas eficientes.([Tableau][2]) 30 | 31 | --- 32 | 33 | ## 📊 2. Introducción al Business Intelligence (BI) 34 | 35 | ### ¿Qué es Business Intelligence? 36 | 37 | Business Intelligence es un conjunto de estrategias y herramientas que transforman datos en información útil para la toma de decisiones empresariales. 38 | 39 | ### Componentes del BI 40 | 41 | 1. **Fuentes de datos**: Internas (CRM, ERP) y externas (redes sociales, datos de mercado). 42 | 2. **Integración de datos**: Procesos ETL para consolidar y limpiar los datos. 43 | 3. **Almacenamiento de datos**: Data Warehouse o Data Marts. 44 | 4. **Análisis de datos**: Herramientas que permiten explorar y modelar los datos. 45 | 5. **Visualización de datos**: Dashboards, informes y gráficos interactivos. 46 | 6. **Toma de decisiones**: Uso de la información analizada para estrategias empresariales. 47 | 48 | ### Ejemplo práctico en MySQL 49 | 50 | Puedes crear vistas o consultas que agreguen información relevante, como ventas por región o análisis de tendencias temporales. Estas consultas pueden integrarse con herramientas de visualización para generar dashboards interactivos. 51 | 52 | --- 53 | 54 | ## 🧠 3. Rol del Data Warehouse y del Business Intelligence 55 | 56 | * **Data Warehouse**: Actúa como el repositorio centralizado que almacena datos históricos y consolidados, sirviendo como la base para el análisis.([Atlan][3]) 57 | 58 | * **Business Intelligence**: Utiliza los datos del DW para generar insights, identificar patrones y apoyar la toma de decisiones estratégicas. 59 | 60 | 61 | 62 | --- 63 | 64 | ## 📚 Recursos adicionales 65 | 66 | Para profundizar en los temas tratados, te recomiendo los siguientes recursos: 67 | 68 | * **Componentes de un Data Warehouse**: Una guía detallada sobre los elementos que conforman un DW. 69 | 70 | * **Conceptos y aplicaciones del Business Intelligence**: Explora los fundamentos y aplicaciones prácticas del BI. 71 | 72 | * **Diseño de un Data Warehouse con MySQL Workbench**: Tutorial paso a paso para crear un DW utilizando MySQL. 73 | 74 | * **Video tutorial sobre diseño de Data Warehouse en MySQL**: Una guía visual para comprender el proceso de diseño. 75 | 76 | --- 77 | 78 | [1]: https://stackoverflow.com/questions/42494115/creating-a-dwh-like-star-schema-in-mysql?utm_source=chatgpt.com "Creating a \"DWH like\" Star Schema in MySQL - Stack Overflow" 79 | [2]: https://www.tableau.com/business-intelligence/what-is-business-intelligence?utm_source=chatgpt.com "Business intelligence: A complete overview | Tableau" 80 | [3]: https://atlan.com/data-warehouse-101/?utm_source=chatgpt.com "What is a Data Warehouse? Purpose, Components & Future - Atlan" 81 | 82 | --- 83 | 84 | ## 🎯 Tema del ejemplo: Ventas de productos 85 | 86 | ### 🧱 1. Crear Base de Datos 87 | 88 | ```sql 89 | CREATE DATABASE IF NOT EXISTS datawarehouse_demo; 90 | USE datawarehouse_demo; 91 | ``` 92 | 93 | --- 94 | 95 | ### 📐 2. Crear tablas de dimensiones 96 | 97 | ```sql 98 | -- Dimensión Tiempo 99 | CREATE TABLE dim_tiempo ( 100 | id_tiempo INT PRIMARY KEY, 101 | fecha DATE, 102 | anio INT, 103 | mes INT, 104 | dia INT, 105 | trimestre INT 106 | ); 107 | 108 | -- Dimensión Producto 109 | CREATE TABLE dim_producto ( 110 | id_producto INT PRIMARY KEY, 111 | nombre_producto VARCHAR(100), 112 | categoria VARCHAR(50), 113 | marca VARCHAR(50) 114 | ); 115 | 116 | -- Dimensión Cliente 117 | CREATE TABLE dim_cliente ( 118 | id_cliente INT PRIMARY KEY, 119 | nombre_cliente VARCHAR(100), 120 | region VARCHAR(50), 121 | genero VARCHAR(10) 122 | ); 123 | ``` 124 | 125 | --- 126 | 127 | ### 📊 3. Crear tabla de hechos 128 | 129 | ```sql 130 | -- Tabla de Hechos: Ventas 131 | CREATE TABLE hecho_ventas ( 132 | id_venta INT PRIMARY KEY AUTO_INCREMENT, 133 | id_tiempo INT, 134 | id_producto INT, 135 | id_cliente INT, 136 | cantidad INT, 137 | total DECIMAL(10, 2), 138 | FOREIGN KEY (id_tiempo) REFERENCES dim_tiempo(id_tiempo), 139 | FOREIGN KEY (id_producto) REFERENCES dim_producto(id_producto), 140 | FOREIGN KEY (id_cliente) REFERENCES dim_cliente(id_cliente) 141 | ); 142 | ``` 143 | 144 | --- 145 | 146 | ### 🧪 4. Insertar datos de prueba 147 | 148 | ```sql 149 | -- Tiempos 150 | INSERT INTO dim_tiempo VALUES 151 | (1, '2024-01-15', 2024, 1, 15, 1), 152 | (2, '2024-02-20', 2024, 2, 20, 1); 153 | 154 | -- Productos 155 | INSERT INTO dim_producto VALUES 156 | (1, 'Notebook Acer', 'Electrónica', 'Acer'), 157 | (2, 'Mouse Logitech', 'Accesorios', 'Logitech'); 158 | 159 | -- Clientes 160 | INSERT INTO dim_cliente VALUES 161 | (1, 'Juan Pérez', 'CABA', 'Masculino'), 162 | (2, 'Laura Gómez', 'Buenos Aires', 'Femenino'); 163 | 164 | -- Ventas 165 | INSERT INTO hecho_ventas (id_tiempo, id_producto, id_cliente, cantidad, total) VALUES 166 | (1, 1, 1, 2, 2000.00), 167 | (2, 2, 2, 1, 500.00); 168 | ``` 169 | 170 | --- 171 | 172 | ### 📈 5. Consultas típicas de BI 173 | 174 | **Ventas totales por categoría de producto:** 175 | 176 | ```sql 177 | SELECT dp.categoria, SUM(hv.total) AS total_ventas 178 | FROM hecho_ventas hv 179 | JOIN dim_producto dp ON hv.id_producto = dp.id_producto 180 | GROUP BY dp.categoria; 181 | ``` 182 | 183 | **Ventas por mes y región:** 184 | 185 | ```sql 186 | SELECT dt.mes, dc.region, SUM(hv.total) AS total_ventas 187 | FROM hecho_ventas hv 188 | JOIN dim_tiempo dt ON hv.id_tiempo = dt.id_tiempo 189 | JOIN dim_cliente dc ON hv.id_cliente = dc.id_cliente 190 | GROUP BY dt.mes, dc.region 191 | ORDER BY dt.mes; 192 | ``` 193 | 194 | **Clientes que compraron más de una vez:** 195 | 196 | ```sql 197 | SELECT dc.nombre_cliente, COUNT(*) AS cantidad_compras 198 | FROM hecho_ventas hv 199 | JOIN dim_cliente dc ON hv.id_cliente = dc.id_cliente 200 | GROUP BY dc.id_cliente 201 | HAVING COUNT(*) > 1; 202 | ``` 203 | 204 | --- 205 | 206 | ### ✅ Resultado 207 | 208 | Con este esquema y estos scripts, vas a tener un entorno básico pero funcional para: 209 | 210 | * Explicar cómo funciona un Data Warehouse. 211 | * Ejecutar consultas analíticas. 212 | * Mostrar la relación entre tablas de dimensiones y hechos. 213 | 214 | --- 215 | 216 | ## 🧑‍🏫 Profesor 217 | 218 | 👨‍💻 **Alejandro Daniel Di Stefano** 219 | 📌 **Desarrollador Full Stack** 220 | 🔗 **GitHub:** [Drako01](https://github.com/Drako01) 221 | 222 | -------------------------------------------------------------------------------- /clase_06/ejercicios/soluciones.sql: -------------------------------------------------------------------------------- 1 | /* 2 | DDL (Data Definition Language) – Crear estructuras (1–20) 3 | 4 | Crear una tabla usuarios con id, nombre, email, fecha_nacimiento. 5 | Crear una tabla productos con id, nombre, precio, stock. 6 | Crear una tabla pedidos con id, usuario_id, fecha. 7 | Crear una tabla detalle_pedidos con id, pedido_id, producto_id, cantidad, precio_unitario. 8 | Crear una tabla categorias y relacionarla con productos. 9 | Agregar una columna telefono a usuarios. 10 | Modificar el tipo de dato de precio en productos a DECIMAL(10,2). 11 | Agregar una restricción UNIQUE sobre email en usuarios. 12 | Crear una clave foránea en pedidos hacia usuarios. 13 | Crear una clave foránea en detalle_pedidos hacia productos. 14 | Crear una clave foránea en detalle_pedidos hacia pedidos. 15 | Crear una tabla comentarios con relación a usuarios y productos. 16 | Crear una tabla intermedia usuarios_roles para una relación N:N entre usuarios y roles. 17 | 18 | -- Hasta aca -- 19 | Eliminar la columna telefono de usuarios. 20 | Eliminar la tabla comentarios. 21 | Crear una tabla direcciones con una restricción CHECK para que el país sea “AR” o “UY”. 22 | Usar AUTO_INCREMENT en una tabla envios. 23 | Crear una vista vista_usuarios_activos. 24 | Crear un índice en productos(nombre). 25 | Crear una tabla logs con una columna timestamp por defecto. 26 | */ 27 | 28 | CREATE DATABASE IF NOT EXISTS sql_flex; 29 | USE sql_flex; 30 | 31 | -- Crear tabla usuarios 32 | CREATE TABLE usuarios ( 33 | id INT AUTO_INCREMENT PRIMARY KEY, 34 | nombre VARCHAR(100) NOT NULL, 35 | email VARCHAR(120) NOT NULL, 36 | fecha_nacimiento DATE NOT NULL 37 | ); 38 | 39 | -- Crear tabla productos 40 | CREATE TABLE productos ( 41 | id INT AUTO_INCREMENT PRIMARY KEY, 42 | nombre VARCHAR(150) NOT NULL, 43 | precio DECIMAL(10,2) NOT NULL, 44 | stock INT NOT NULL 45 | ); 46 | 47 | -- Crear tabla Pedidos 48 | CREATE TABLE pedidos ( 49 | id INT AUTO_INCREMENT PRIMARY KEY, 50 | usuario_id INT NOT NULL, 51 | fecha DATE NOT NULL, 52 | FOREIGN KEY (usuario_id) REFERENCES usuarios(id) 53 | ); 54 | 55 | -- Crear tabla Detalle Pedido 56 | CREATE TABLE detalle_pedido ( 57 | id INT AUTO_INCREMENT PRIMARY KEY, 58 | pedido_id INT NOT NULL, 59 | producto_id INT NOT NULL, 60 | cantidad INT NOT NULL, 61 | precio_unitario DECIMAL(10,2) NOT NULL, 62 | FOREIGN KEY (pedido_id) REFERENCES pedidos(id), 63 | FOREIGN KEY (producto_id) REFERENCES productos(id) 64 | ); 65 | 66 | -- Crear tabla Categorias 67 | CREATE TABLE categorias ( 68 | id INT AUTO_INCREMENT PRIMARY KEY, 69 | nombre VARCHAR(100) NOT NULL 70 | ); 71 | 72 | -- Relacionar productos con categorias 73 | ALTER TABLE productos ADD COLUMN categoria_id INT; 74 | ALTER TABLE productos ADD FOREIGN KEY (categoria_id) REFERENCES categorias(id); 75 | 76 | -- Agregar columna telefono a usuarios 77 | ALTER TABLE usuarios ADD COLUMN telefono VARCHAR (20) UNIQUE; 78 | 79 | -- Agregar restriccion UNIQUE al email del usuario 80 | ALTER TABLE usuarios ADD CONSTRAINT uc_email UNIQUE (email); 81 | 82 | -- Crear una tabla comentarios con relación a usuarios y productos. 83 | CREATE TABLE comentarios ( 84 | id INT AUTO_INCREMENT PRIMARY KEY, 85 | usuario_id INT NOT NULL, 86 | producto_id INT NOT NULL, 87 | comentario TEXT, 88 | fecha DATETIME DEFAULT CURRENT_TIMESTAMP, 89 | FOREIGN KEY (usuario_id) REFERENCES usuarios(id), 90 | FOREIGN KEY (producto_id) REFERENCES productos(id) 91 | ); 92 | 93 | -- Crear tabla usuarios_roles 94 | CREATE TABLE roles( 95 | id INT AUTO_INCREMENT PRIMARY KEY, 96 | nombre VARCHAR(100) NOT NULL 97 | ); 98 | 99 | CREATE TABLE usuarios_roles( 100 | usuario_id INT NOT NULL, 101 | rol_id INT NOT NULL, 102 | PRIMARY KEY (usuario_id, rol_id), 103 | FOREIGN KEY (usuario_id) REFERENCES usuarios(id), 104 | FOREIGN KEY (rol_id) REFERENCES roles(id) 105 | ); 106 | 107 | -- 2da Parte 108 | /* 109 | SECCIÓN 2: DML - Manipular datos (25 ejercicios) 110 | Insertar 3 usuarios. 111 | Insertar 5 productos con diferentes precios. 112 | Insertar parcialmente un usuario (solo nombre y email). 113 | Insertar parcialmente un producto (nombre y stock). 114 | Insertar un pedido con su detalle. 115 | Actualizar el precio de todos los productos aumentando un 10%. 116 | Cambiar el email de un usuario específico. 117 | Eliminar un producto por ID. 118 | Eliminar un usuario que tiene pedidos (¡provoca error!). 119 | Insertar un producto con NULL en precio (probar si está permitido). 120 | Insertar un detalle de pedido con cantidad 0 (con CHECK activado). 121 | Insertar varios usuarios con INSERT INTO ... VALUES (...), (...), (...); 122 | Insertar una dirección para un usuario existente. 123 | Actualizar todos los usuarios nacidos antes del 2000. 124 | Incrementar el stock de un producto en 20 unidades. 125 | Eliminar todos los pedidos anteriores a una fecha. 126 | Insertar un comentario sobre un producto. 127 | Insertar un log con la fecha actual por defecto. 128 | Eliminar un producto que tiene detalles de pedido (¡provoca error!). 129 | Insertar una fila con clave foránea que no existe (¡provoca error!). 130 | Insertar datos con funciones como NOW(), UUID(). 131 | Copiar todos los productos caros a una tabla productos_premium. 132 | Insertar un producto sin nombre (¡provoca error! si es NOT NULL). 133 | Insertar un usuario con un email duplicado (¡provoca error!). 134 | Actualizar el stock de un producto basado en una subconsulta de ventas. 135 | */ 136 | 137 | -- Isertar 3 usuarios 138 | INSERT INTO usuarios (nombre, email,fecha_nacimiento, telefono) 139 | VALUES 140 | ("Pablo Goytia", "pablito@gmail.com", "1994-08-17", "+5491155556666"), 141 | ("Ignacio Chobanian", "ignacio@gmail.com", "2007-02-09", "+5491155557777"), 142 | ("Laura Calbette", "laura@gmail.com", "2000-05-02", "+5491155558888"); 143 | 144 | SELECT * FROM usuarios; 145 | 146 | -- Isertar 5 Productos de diferentes precios 147 | INSERT INTO categorias (nombre) 148 | VALUES 149 | ("Almacen"), -- 1 150 | ("Limpieza"), -- 2 151 | ("Indumentaria"), -- 3 152 | ("Insumos"), -- 4 153 | ("Bebidas"); -- 5 154 | SELECT * FROM categorias; 155 | INSERT INTO productos (nombre, precio, stock, categoria_id) 156 | VALUES 157 | ("Harina", 1500.50, 2000, 1), 158 | ("Shampoo", 4950.80, 1500, 2), 159 | ("Remera Blanca", 25000, 10, 3), 160 | ("Resma de Hojas A4", 40000.50, 200, 4), 161 | ("Coca Cola", 3500.50, 15000, 5); 162 | 163 | SELECT * FROM productos; 164 | 165 | INSERT INTO usuarios (nombre, email, fecha_nacimiento) 166 | VALUES 167 | ("Sara Rionda", "sara@gmail.com", "2006-05-25"); 168 | 169 | SELECT * FROM usuarios; 170 | 171 | -- Insertar un pedido con su detalle. 172 | INSERT INTO pedidos (usuario_id, fecha) 173 | VALUES (1, CURDATE()); -- ID 1 174 | -- Insertar detalle 175 | INSERT INTO detalle_pedido (pedido_id, producto_id, cantidad, precio_unitario) 176 | VALUES 177 | (LAST_INSERT_ID(), 1, 5, 1500.50), 178 | (LAST_INSERT_ID(), 5, 2, 3500.50), 179 | (LAST_INSERT_ID(), 2, 1, 4950.80); 180 | 181 | SELECT * FROM detalle_pedido; 182 | 183 | -- Actualizar el precio de todos los productos aumentando un 10%. 184 | UPDATE productos SET precio = precio * 1.10; 185 | 186 | /* 187 | 13:21:37 UPDATE productos SET precio = precio * 1.10 Error Code: 1175. 188 | You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column. 189 | To disable safe mode, toggle the option in Preferences -> SQL Editor and reconnect. 0.000 sec 190 | */ 191 | 192 | SET SQL_SAFE_UPDATES = 0; 193 | UPDATE productos SET precio = precio * 1.10; 194 | SET SQL_SAFE_UPDATES = 1; 195 | 196 | -- Crear una funcion para cargar un Pedido con detalle 197 | 198 | DELIMITER // 199 | 200 | CREATE PROCEDURE insertar_pedido_con_detalle( 201 | IN p_usuario_id INT, 202 | IN p_producto_id INT, 203 | IN p_cantidad INT, 204 | IN p_precio_unitario DECIMAL(10,2) 205 | ) 206 | 207 | BEGIN 208 | -- Insertar Pedido 209 | INSERT INTO pedidos (usuario_id, fecha) 210 | VALUES (p_usuario_id, CURDATE()); 211 | 212 | -- Obtener el ID del pedido 213 | SET @ultimo_pedido_id = LAST_INSERT_ID(); 214 | 215 | -- Insertar detalle 216 | INSERT INTO detalle_pedido (pedido_id, producto_id, cantidad, precio_unitario) 217 | VALUES (@ultimo_pedido_id, p_producto_id, p_cantidad, p_precio_unitario); 218 | END // 219 | 220 | DELIMITER ; 221 | 222 | CALL insertar_pedido_con_detalle(2,2,3,27500.00); -------------------------------------------------------------------------------- /clase_09/teoria/teoria.md: -------------------------------------------------------------------------------- 1 | # Unidad 9: Triggers y Sublenguaje DCL 2 | 3 | ## 🧠 Objetivos de la clase 4 | 5 | - Conocer el concepto general de un Trigger 6 | - Familiarizarse con los tipos de Triggers 7 | - Conocer la sintaxis e implementación de un Trigger 8 | - Reconocer el implementar las sentencias del sublenguaje DCL 9 | - Identificar en qué situación usar cada sentencia 10 | 11 | --- 12 | 13 | ## 📘 Parte 1: Material Teórico 14 | 15 | ### ¿Qué es un Trigger? 16 | 17 | Un **Trigger** (o disparador) es un objeto de la base de datos que se asocia a una tabla y se ejecuta automáticamente en respuesta a ciertos eventos como `INSERT`, `UPDATE` o `DELETE`. Se utiliza para automatizar tareas, mantener la integridad de los datos y aplicar reglas de negocio directamente en la base de datos. 18 | 19 | ### Tipos de Triggers en MySQL 20 | 21 | - **BEFORE INSERT**: Se ejecuta antes de insertar un nuevo registro. 22 | - **AFTER INSERT**: Se ejecuta después de insertar un nuevo registro. 23 | - **BEFORE UPDATE**: Se ejecuta antes de actualizar un registro existente. 24 | - **AFTER UPDATE**: Se ejecuta después de actualizar un registro existente. 25 | - **BEFORE DELETE**: Se ejecuta antes de eliminar un registro. 26 | - **AFTER DELETE**: Se ejecuta después de eliminar un registro. 27 | 28 | ### Sintaxis General 29 | 30 | ```sql 31 | DELIMITER // 32 | CREATE TRIGGER nombre_del_trigger 33 | {BEFORE | AFTER} {INSERT | UPDATE | DELETE} 34 | ON nombre_de_la_tabla 35 | FOR EACH ROW 36 | BEGIN 37 | -- Instrucciones SQL 38 | END; 39 | // 40 | DELIMITER ; 41 | ``` 42 | 43 | ### ¿Cuándo usar Triggers? 44 | 45 | - Para validar o modificar datos antes de que se realicen cambios en la base de datos. 46 | - Para mantener registros de auditoría de cambios. 47 | - Para aplicar reglas de negocio automáticamente. 48 | - Para sincronizar datos entre tablas relacionadas. 49 | 50 | --- 51 | 52 | ## 🏫 Parte 2: Caso Práctico - Base de Datos de una Institución Educativa 53 | 54 | ### Estructura de la Base de Datos 55 | 56 | Vamos a trabajar con las siguientes tablas: 57 | 58 | - **estudiantes**: Información de los estudiantes. 59 | - **cursos**: Información de los cursos ofrecidos. 60 | - **inscripciones**: Registro de inscripciones de estudiantes en cursos. 61 | - **auditoria\_inscripciones**: Registro de auditoría de las inscripciones. 62 | 63 | ### Creación de las Tablas 64 | 65 | ```sql 66 | CREATE TABLE estudiantes ( 67 | id_estudiante INT AUTO_INCREMENT PRIMARY KEY, 68 | nombre VARCHAR(100), 69 | apellido VARCHAR(100), 70 | fecha_nacimiento DATE 71 | ); 72 | 73 | CREATE TABLE cursos ( 74 | id_curso INT AUTO_INCREMENT PRIMARY KEY, 75 | nombre_curso VARCHAR(100), 76 | descripcion TEXT 77 | ); 78 | 79 | CREATE TABLE inscripciones ( 80 | id_inscripcion INT AUTO_INCREMENT PRIMARY KEY, 81 | id_estudiante INT, 82 | id_curso INT, 83 | fecha_inscripcion DATE, 84 | FOREIGN KEY (id_estudiante) REFERENCES estudiantes(id_estudiante), 85 | FOREIGN KEY (id_curso) REFERENCES cursos(id_curso) 86 | ); 87 | 88 | CREATE TABLE auditoria_inscripciones ( 89 | id_auditoria INT AUTO_INCREMENT PRIMARY KEY, 90 | id_inscripcion INT, 91 | accion VARCHAR(10), 92 | fecha_accion DATETIME 93 | ); 94 | ``` 95 | 96 | ### Ejemplo 1: Trigger AFTER INSERT 97 | 98 | Registrar en la tabla de auditoría cada vez que se realice una nueva inscripción. 99 | 100 | ```sql 101 | DELIMITER // 102 | CREATE TRIGGER after_insert_inscripcion 103 | AFTER INSERT ON inscripciones 104 | FOR EACH ROW 105 | BEGIN 106 | INSERT INTO auditoria_inscripciones (id_inscripcion, accion, fecha_accion) 107 | VALUES (NEW.id_inscripcion, 'INSERT', NOW()); 108 | END; 109 | // 110 | DELIMITER ; 111 | ``` 112 | 113 | ### Ejemplo 2: Trigger BEFORE DELETE 114 | 115 | Registrar en la tabla de auditoría antes de eliminar una inscripción. 116 | 117 | ```sql 118 | DELIMITER // 119 | CREATE TRIGGER before_delete_inscripcion 120 | BEFORE DELETE ON inscripciones 121 | FOR EACH ROW 122 | BEGIN 123 | INSERT INTO auditoria_inscripciones (id_inscripcion, accion, fecha_accion) 124 | VALUES (OLD.id_inscripcion, 'DELETE', NOW()); 125 | END; 126 | // 127 | DELIMITER ; 128 | ``` 129 | 130 | ### Ejemplo 3: Trigger BEFORE UPDATE 131 | 132 | Evitar que se modifique la fecha de inscripción después de ser registrada. 133 | 134 | ```sql 135 | DELIMITER // 136 | CREATE TRIGGER before_update_inscripcion 137 | BEFORE UPDATE ON inscripciones 138 | FOR EACH ROW 139 | BEGIN 140 | IF NEW.fecha_inscripcion <> OLD.fecha_inscripcion THEN 141 | SIGNAL SQLSTATE '45000' 142 | SET MESSAGE_TEXT = 'No se permite modificar la fecha de inscripción.'; 143 | END IF; 144 | END; 145 | // 146 | DELIMITER ; 147 | ``` 148 | 149 | --- 150 | 151 | ## 🛠️ Parte 3: Implementación en MySQL Workbench 152 | 153 | ### Pasos para Crear un Trigger 154 | 155 | 1. Abre MySQL Workbench y conecta con tu servidor MySQL. 156 | 2. En el panel izquierdo, expande la base de datos y selecciona la tabla deseada. 157 | 3. Haz clic derecho en la tabla y selecciona **"Create Trigger..."**. 158 | 4. Se abrirá una nueva pestaña para definir el trigger: 159 | 160 | - **Trigger Name**: Nombre del trigger. 161 | - **Timing**: BEFORE o AFTER. 162 | - **Event**: INSERT, UPDATE o DELETE. 163 | - **Statement**: Código SQL que se ejecutará. 164 | 5. Escribe el código del trigger en la sección correspondiente. 165 | 6. Haz clic en **"Apply"** para crear el trigger. 166 | 167 | Para una guía visual paso a paso, puedes consultar el siguiente tutorial: 168 | 169 | [Crear Triggers en MySQL Workbench: Guía Paso a Paso](https://mysqlya.com.ar/tutoriales/crear-trigger-mysql-workbench/) 170 | 171 | --- 172 | 173 | ## 📚 Parte 4: Sentencias DCL (Data Control Language) 174 | 175 | Las sentencias DCL se utilizan para controlar los permisos y la seguridad en la base de datos. 176 | 177 | ## 🔐 Parte Complementaria: DCL - Control de Acceso en MySQL 178 | 179 | ### ¿Qué es DCL? 180 | 181 | **DCL (Data Control Language)** es el subconjunto del lenguaje SQL que se utiliza para definir permisos y controlar el acceso a los datos en una base de datos. 182 | 183 | Las sentencias principales son: 184 | 185 | - `GRANT`: Para otorgar privilegios. 186 | - `REVOKE`: Para revocar privilegios. 187 | - `CREATE USER`: Para crear nuevos usuarios. 188 | - `DROP USER`: Para eliminar usuarios existentes. 189 | 190 | --- 191 | 192 | ## 👤 Creación de Usuarios 193 | 194 | ```sql 195 | CREATE USER 'nombre_usuario'@'localhost' IDENTIFIED BY 'contraseña'; 196 | ``` 197 | 198 | **Ejemplo:** 199 | 200 | ```sql 201 | CREATE USER 'profesor1'@'localhost' IDENTIFIED BY 'segura123'; 202 | ``` 203 | 204 | Esto crea un usuario que solo puede conectarse desde la misma máquina del servidor MySQL. 205 | 206 | --- 207 | 208 | ## 🔑 Asignación de Permisos 209 | 210 | ### GRANT 211 | 212 | Otorga privilegios al usuario para acceder a ciertos objetos. 213 | 214 | ```sql 215 | GRANT privilegios ON base_datos.tabla TO 'usuario'@'host'; 216 | ``` 217 | 218 | **Privilegios comunes:** 219 | 220 | - `SELECT`, `INSERT`, `UPDATE`, `DELETE`: Acciones sobre datos. 221 | - `ALL PRIVILEGES`: Otorga todos los permisos. 222 | - `TRIGGER`: Permiso para crear triggers. 223 | 224 | **Ejemplos:** 225 | 226 | ```sql 227 | -- Permitir a profesor1 ver e insertar datos en la tabla inscripciones 228 | GRANT SELECT, INSERT ON institucion.inscripciones TO 'profesor1'@'localhost'; 229 | 230 | -- Permitir a profesor1 crear triggers 231 | GRANT TRIGGER ON institucion.* TO 'profesor1'@'localhost'; 232 | ``` 233 | 234 | --- 235 | 236 | ## ❌ Revocación de Permisos 237 | 238 | ### REVOKE 239 | 240 | Quita privilegios otorgados anteriormente. 241 | 242 | ```sql 243 | REVOKE privilegios ON base_datos.tabla FROM 'usuario'@'host'; 244 | ``` 245 | 246 | **Ejemplo:** 247 | 248 | ```sql 249 | REVOKE INSERT ON institucion.inscripciones FROM 'profesor1'@'localhost'; 250 | ``` 251 | 252 | --- 253 | 254 | ## 🔄 Visualización de Permisos 255 | 256 | Puedes revisar qué privilegios tiene un usuario con: 257 | 258 | ```sql 259 | SHOW GRANTS FOR 'profesor1'@'localhost'; 260 | ``` 261 | 262 | --- 263 | 264 | ## 🧽 Eliminación de Usuarios 265 | 266 | ```sql 267 | DROP USER 'profesor1'@'localhost'; 268 | ``` 269 | 270 | --- 271 | 272 | ## 🛠 Cómo hacerlo en MySQL Workbench 273 | 274 | 1. Abre **MySQL Workbench** y conecta a tu servidor. 275 | 2. Ve a **Server > Users and Privileges**. 276 | 3. En la pestaña **Users**, haz clic en **Add Account**. 277 | 4. Completa: 278 | 279 | - Username 280 | - Host: localhost o % 281 | - Password 282 | 5. En la pestaña **Administrative Roles** y **Schema Privileges**, selecciona los permisos deseados. 283 | 6. Haz clic en **Apply** para crear y configurar el usuario. 284 | 285 | --- 286 | 287 | ## ✅ Buenas Prácticas 288 | 289 | - Usa `localhost` para usuarios internos del servidor. 290 | - Asigna solo los privilegios estrictamente necesarios (principio de menor privilegio). 291 | - Usa contraseñas fuertes. 292 | - Evita usar la cuenta `root` para tareas diarias. 293 | - Crea cuentas específicas para tareas automatizadas (como triggers). 294 | 295 | --- 296 | 297 | ## 📘 Ejercicio para la Clase 298 | 299 | 1. Crear el usuario `coordinador@localhost` con permisos para leer y escribir en las tablas `estudiantes`, `cursos` e `inscripciones`. 300 | 2. Crear el usuario `auditor@localhost` con acceso solo de lectura a toda la base. 301 | 3. Quitarle a `coordinador` el permiso de insertar en `cursos`. 302 | 303 | --- 304 | 305 | ## Manejo de permisos volviendo al ejemplo anterior 306 | 307 | ### GRANT 308 | 309 | Otorga permisos a un usuario. 310 | 311 | ```sql 312 | GRANT SELECT, INSERT ON nombre_base_datos.* TO 'usuario'@'localhost'; 313 | ``` 314 | 315 | ### REVOKE 316 | 317 | Revoca permisos previamente otorgados. 318 | 319 | ```sql 320 | REVOKE INSERT ON nombre_base_datos.* FROM 'usuario'@'localhost'; 321 | ``` 322 | 323 | ### Uso de DCL en el Contexto de Triggers 324 | 325 | Es importante asegurarse de que los usuarios que crean o modifican triggers tengan los permisos adecuados. Por ejemplo, para crear un trigger, el usuario debe tener el privilegio `TRIGGER` en la base de datos. 326 | 327 | ```sql 328 | GRANT TRIGGER ON nombre_base_datos.* TO 'usuario'@'localhost'; 329 | ``` 330 | 331 | --- 332 | 333 | ## 🧩 Parte 5: Actividades Prácticas 334 | 335 | 1. **Crear un Trigger AFTER INSERT**: Que registre en una tabla de auditoría cada vez que se inscribe un estudiante en un curso. 336 | 2. **Crear un Trigger BEFORE DELETE**: Que impida eliminar una inscripción si la fecha de inscripción es anterior a la fecha actual. 337 | 3. **Modificar Permisos con DCL**: Otorgar y revocar permisos a un usuario para que pueda crear triggers en la base de datos. 338 | 339 | --- 340 | 341 | ## 🎥 Recursos Adicionales 342 | 343 | - [Tutorial en Video: Cómo crear un TRIGGER en MySQL Workbench](https://www.youtube.com/watch?v=C2s-qbcyIS8) 344 | - [Implementación de Triggers en SQL: Caso de Estudio de una Base de Datos Estudiantil](https://www.entredata.org/fundamentos-de-sql/implementacion-de-triggers-en-sql-caso-de-estudio-de-una-base-de-datos-estudiantil) 345 | 346 | --- 347 | 348 | ## 🧑‍🏫 Profesor 349 | 350 | 👨‍💻 **Alejandro Daniel Di Stefano** 351 | 📌 **Desarrollador Full Stack** 352 | 🔗 **GitHub:** [Drako01](https://github.com/Drako01) 353 | -------------------------------------------------------------------------------- /clase_06/README_SQL_DML_Subconsultas.md: -------------------------------------------------------------------------------- 1 | 2 | # 📚 SQL DML + Subconsultas (MySQL) — Clase de 2 horas 3 | 4 | > **Objetivo:** que el alumno maneje **INSERT, UPDATE, DELETE** (DML) y sepa aplicar **subconsultas** dentro de DML (INSERT/UPDATE/DELETE), con criterio y sin romper la base. Cero humo, 100% práctico. 5 | 6 | --- 7 | 8 | ## ⏱️ Agenda sugerida (2 hs) 9 | 10 | 1. **(10')** Set up rápido + repaso de tablas 11 | 2. **(25')** DML básico: `INSERT`, `UPDATE`, `DELETE` (todas las variantes útiles) 12 | 3. **(35')** Subconsultas en DML: `INSERT ... SELECT`, `UPDATE ... WHERE/SET (subquery)`, `DELETE ... WHERE (subquery)` 13 | 4. **(20')** Transacciones + restricciones + “anti-multas” (FK, UNIQUE, IGNORE, upsert) 14 | 5. **(20')** Ejercicios guiados 15 | 6. **(10')** Desafíos + Q&A 16 | 17 | --- 18 | 19 | ## 🧱 Setup (usar tal cual) 20 | 21 | > MySQL 8.x. Copiar/pegar en tu cliente y ejecutar por bloques. 22 | > **Nota**: si ya existe, borra la DB para un arranque limpio (opcional). 23 | 24 | ```sql 25 | DROP DATABASE IF EXISTS coderhouse; 26 | CREATE DATABASE IF NOT EXISTS coderhouse; 27 | USE coderhouse; 28 | 29 | CREATE TABLE IF NOT EXISTS alumnos( 30 | id_alumno INT PRIMARY KEY AUTO_INCREMENT, 31 | nombre VARCHAR(50) NOT NULL, 32 | apellido VARCHAR(80) NOT NULL, 33 | email VARCHAR(150) UNIQUE DEFAULT NULL, 34 | dni INT UNIQUE NOT NULL, 35 | edad INT UNSIGNED DEFAULT NULL, 36 | telefono VARCHAR(20) UNIQUE DEFAULT NULL, 37 | nacionalidad VARCHAR(30) DEFAULT 'Argentina' 38 | ); 39 | 40 | CREATE TABLE IF NOT EXISTS categoria ( 41 | id_categoria INT AUTO_INCREMENT PRIMARY KEY, 42 | nombre_categoria VARCHAR(100) NOT NULL 43 | ); 44 | 45 | CREATE TABLE IF NOT EXISTS cursos( 46 | id_curso INT PRIMARY KEY AUTO_INCREMENT, 47 | nombre_curso VARCHAR(50) NOT NULL, 48 | id_categoria INT, 49 | CONSTRAINT fk_curso_categoria 50 | FOREIGN KEY (id_categoria) REFERENCES categoria (id_categoria) 51 | ); 52 | 53 | CREATE TABLE IF NOT EXISTS inscripciones ( 54 | idx_alumno INT, 55 | idx_curso INT, 56 | inscription_at DATETIME DEFAULT CURRENT_TIMESTAMP, 57 | PRIMARY KEY (idx_alumno, idx_curso), 58 | FOREIGN KEY (idx_alumno) REFERENCES alumnos(id_alumno), 59 | FOREIGN KEY (idx_curso) REFERENCES cursos(id_curso) 60 | ); 61 | ``` 62 | 63 | ### 📦 Datos de ejemplo (semilla) 64 | 65 | ```sql 66 | -- Categorías 67 | INSERT INTO categoria (nombre_categoria) VALUES 68 | ('Programación'), ('Datos'), ('Cloud'), ('UX'); 69 | 70 | -- Cursos 71 | INSERT INTO cursos (nombre_curso, id_categoria) VALUES 72 | ('SQL Inicial', (SELECT id_categoria FROM categoria WHERE nombre_categoria='Datos')), 73 | ('TypeScript', (SELECT id_categoria FROM categoria WHERE nombre_categoria='Programación')), 74 | ('Docker', (SELECT id_categoria FROM categoria WHERE nombre_categoria='Cloud')), 75 | ('Figma', (SELECT id_categoria FROM categoria WHERE nombre_categoria='UX')), 76 | ('PostgreSQL', (SELECT id_categoria FROM categoria WHERE nombre_categoria='Datos')); 77 | 78 | -- Alumnos 79 | INSERT INTO alumnos (nombre, apellido, email, dni, edad, telefono, nacionalidad) VALUES 80 | ('Ana', 'Gómez', 'ana.gomez@example.com', 30111222, 25, '1130000001', 'Argentina'), 81 | ('Luis', 'Pérez', 'luis.perez@example.com', 28999888, 30, '1130000002', 'Uruguay'), 82 | ('Mara', 'Suárez', 'mara.suarez@example.com', 31222333, 22, '1130000003', 'Chile'), 83 | ('Diego', 'Ramos', NULL, 29888777, 28, NULL, 'Argentina'), 84 | ('Juan', 'López', 'juan.lopez@example.com', 27123456, 35, '1130000004', 'Paraguay'); 85 | 86 | -- Inscripciones 87 | INSERT INTO inscripciones (idx_alumno, idx_curso) 88 | SELECT a.id_alumno, c.id_curso 89 | FROM alumnos a 90 | JOIN cursos c ON c.nombre_curso IN ('SQL Inicial','TypeScript') 91 | WHERE a.nombre IN ('Ana','Luis','Mara'); 92 | 93 | -- Validaciones rápidas 94 | SELECT * FROM alumnos; 95 | SELECT * FROM cursos; 96 | SELECT * FROM inscripciones; 97 | ``` 98 | 99 | --- 100 | 101 | ## 🎯 DML Básico — Lo imprescindible 102 | 103 | ### 1) `INSERT` 104 | 105 | **A. Insert simple (todas las columnas requeridas):** 106 | 107 | ```sql 108 | INSERT INTO alumnos (nombre, apellido, email, dni, edad, telefono, nacionalidad) 109 | VALUES ('Carla','Domínguez','carla.dominguez@example.com', 32777888, 27, '1130000010', 'Argentina'); 110 | ``` 111 | 112 | **B. Insert múltiple (bulk):** 113 | 114 | ```sql 115 | INSERT INTO cursos (nombre_curso, id_categoria) VALUES 116 | ('MySQL Avanzado', (SELECT id_categoria FROM categoria WHERE nombre_categoria='Datos')), 117 | ('Kubernetes', (SELECT id_categoria FROM categoria WHERE nombre_categoria='Cloud')); 118 | ``` 119 | 120 | **C. Insert con `DEFAULT` y `NULL`:** 121 | 122 | ```sql 123 | INSERT INTO alumnos (nombre, apellido, email, dni, edad, telefono, nacionalidad) 124 | VALUES ('Sofía','Rivas', NULL, 33444555, NULL, NULL, DEFAULT); 125 | ``` 126 | 127 | **D. `INSERT ... SELECT` (sin subconsulta compleja todavía):** 128 | 129 | ```sql 130 | -- Inscribir a todos los alumnos con email en el curso 'Docker' 131 | INSERT INTO inscripciones (idx_alumno, idx_curso) 132 | SELECT id_alumno, (SELECT id_curso FROM cursos WHERE nombre_curso='Docker') 133 | FROM alumnos 134 | WHERE email IS NOT NULL; 135 | ``` 136 | 137 | **E. `INSERT IGNORE` (omite errores por UNIQUE):** 138 | 139 | ```sql 140 | INSERT IGNORE INTO alumnos (nombre, apellido, email, dni) 141 | VALUES ('Ana','Gómez','ana.gomez@example.com', 30111222); -- ya existe 142 | ``` 143 | 144 | **F. UPSERT: `ON DUPLICATE KEY UPDATE`** 145 | 146 | ```sql 147 | INSERT INTO alumnos (nombre, apellido, email, dni) 148 | VALUES ('Ana','Gómez','ana.gomez@nuevo.com', 30111222) 149 | ON DUPLICATE KEY UPDATE email = VALUES(email); 150 | ``` 151 | 152 | --- 153 | 154 | ### 2) `UPDATE` 155 | 156 | **A. Update básico con `WHERE`:** 157 | 158 | ```sql 159 | UPDATE alumnos 160 | SET telefono = '1139999999' 161 | WHERE email = 'luis.perez@example.com'; 162 | ``` 163 | 164 | **B. Update múltiple de columnas:** 165 | 166 | ```sql 167 | UPDATE alumnos 168 | SET nacionalidad = 'Argentina', edad = edad + 1 169 | WHERE nacionalidad IN ('Chile','Uruguay'); 170 | ``` 171 | 172 | **C. `ORDER BY ... LIMIT` (MySQL):** 173 | 174 | ```sql 175 | -- Subimos 1 año a los 2 alumnos más jóvenes 176 | UPDATE alumnos 177 | SET edad = edad + 1 178 | ORDER BY edad ASC 179 | LIMIT 2; 180 | ``` 181 | 182 | **D. Update con JOIN (alternativa a subconsulta):** 183 | 184 | ```sql 185 | UPDATE alumnos a 186 | JOIN inscripciones i ON i.idx_alumno = a.id_alumno 187 | JOIN cursos c ON c.id_curso = i.idx_curso 188 | SET a.nacionalidad = 'Argentina' 189 | WHERE c.nombre_curso = 'SQL Inicial' AND a.nacionalidad <> 'Argentina'; 190 | ``` 191 | 192 | --- 193 | 194 | ### 3) `DELETE` 195 | 196 | **A. Delete básico:** 197 | 198 | ```sql 199 | DELETE FROM inscripciones 200 | WHERE idx_alumno = (SELECT id_alumno FROM alumnos WHERE email='mara.suarez@example.com') 201 | AND idx_curso = (SELECT id_curso FROM cursos WHERE nombre_curso='TypeScript'); 202 | ``` 203 | 204 | **B. `ORDER BY ... LIMIT` (MySQL):** 205 | 206 | ```sql 207 | -- Borrar la inscripción más antigua 208 | DELETE FROM inscripciones 209 | ORDER BY inscription_at ASC 210 | LIMIT 1; 211 | ``` 212 | 213 | **C. Respeto a FK (el orden importa):** 214 | 215 | ```sql 216 | -- ❌ Esto fallará si hay inscripciones que referencian el curso 217 | DELETE FROM cursos WHERE nombre_curso = 'SQL Inicial'; 218 | 219 | -- ✅ Primero borro las inscripciones del curso, luego el curso 220 | DELETE FROM inscripciones 221 | WHERE idx_curso = (SELECT id_curso FROM cursos WHERE nombre_curso='SQL Inicial'); 222 | 223 | DELETE FROM cursos WHERE nombre_curso = 'SQL Inicial'; 224 | ``` 225 | 226 | > **Tip:** tu schema no tiene `ON DELETE CASCADE`. Por eso, **primero** borra en tablas hijas. 227 | 228 | --- 229 | 230 | ## 🧠 Subconsultas en DML (el plato fuerte) 231 | 232 | ### 1) `INSERT ... SELECT` (subconsultas en SELECT) 233 | 234 | ```sql 235 | -- Inscribir a todos los alumnos NO inscriptos aún a 'PostgreSQL' si tienen email 236 | INSERT INTO inscripciones (idx_alumno, idx_curso) 237 | SELECT a.id_alumno, c.id_curso 238 | FROM alumnos a 239 | CROSS JOIN (SELECT id_curso FROM cursos WHERE nombre_curso='PostgreSQL') c 240 | WHERE a.email IS NOT NULL 241 | AND NOT EXISTS ( 242 | SELECT 1 FROM inscripciones i 243 | WHERE i.idx_alumno = a.id_alumno AND i.idx_curso = c.id_curso 244 | ); 245 | ``` 246 | 247 | ### 2) `UPDATE` con subconsulta en `SET` 248 | 249 | ```sql 250 | -- Setear id_categoria correcto en cursos, basado en su nombre 251 | UPDATE cursos c 252 | SET c.id_categoria = ( 253 | SELECT id_categoria FROM categoria cat 254 | WHERE (cat.nombre_categoria = 'Datos' AND c.nombre_curso IN ('SQL Inicial','PostgreSQL','MySQL Avanzado')) 255 | OR (cat.nombre_categoria = 'Programación' AND c.nombre_curso = 'TypeScript') 256 | OR (cat.nombre_categoria = 'Cloud' AND c.nombre_curso IN ('Docker','Kubernetes')) 257 | OR (cat.nombre_categoria = 'UX' AND c.nombre_curso = 'Figma') 258 | LIMIT 1 259 | ); 260 | ``` 261 | 262 | ### 3) `UPDATE` con subconsulta en `WHERE` (IN / EXISTS) 263 | 264 | ```sql 265 | -- Marcar como 'Argentina' a alumnos inscriptos en al menos un curso de la categoría 'Datos' 266 | UPDATE alumnos a 267 | SET nacionalidad = 'Argentina' 268 | WHERE EXISTS ( 269 | SELECT 1 270 | FROM inscripciones i 271 | JOIN cursos c ON c.id_curso = i.idx_curso 272 | JOIN categoria cat ON cat.id_categoria = c.id_categoria 273 | WHERE i.idx_alumno = a.id_alumno 274 | AND cat.nombre_categoria = 'Datos' 275 | ); 276 | ``` 277 | 278 | ### 4) `DELETE` con subconsulta 279 | 280 | ```sql 281 | -- Borrar inscripciones de cursos de la categoría 'UX' 282 | DELETE FROM inscripciones 283 | WHERE idx_curso IN ( 284 | SELECT id_curso FROM cursos 285 | WHERE id_categoria = (SELECT id_categoria FROM categoria WHERE nombre_categoria='UX') 286 | ); 287 | 288 | -- Borrar alumnos sin ninguna inscripción 289 | DELETE FROM alumnos a 290 | WHERE NOT EXISTS (SELECT 1 FROM inscripciones i WHERE i.idx_alumno = a.id_alumno); 291 | ``` 292 | 293 | ### 5) Subconsulta correlacionada (patrón clásico) 294 | 295 | ```sql 296 | -- Poner teléfono NULL a alumnos que solo estén inscriptos en un único curso 297 | UPDATE alumnos a 298 | SET telefono = NULL 299 | WHERE 1 = ( 300 | SELECT COUNT(*) FROM inscripciones i 301 | WHERE i.idx_alumno = a.id_alumno 302 | ); 303 | ``` 304 | 305 | ### 6) CTE (`WITH`) en MySQL 8 aplicadas a DML 306 | 307 | ```sql 308 | WITH cursos_datos AS ( 309 | SELECT id_curso FROM cursos c 310 | JOIN categoria cat ON cat.id_categoria = c.id_categoria 311 | WHERE cat.nombre_categoria = 'Datos' 312 | ) 313 | UPDATE inscripciones i 314 | JOIN cursos_datos cd ON cd.id_curso = i.idx_curso 315 | SET inscription_at = CURRENT_TIMESTAMP; 316 | ``` 317 | 318 | > **Nota:** MySQL permite `WITH` antes de `SELECT/UPDATE/DELETE`. Útil para legibilidad en DML más complejos. 319 | 320 | --- 321 | 322 | ## 🧯 Transacciones, seguridad y trucos anti-drama 323 | 324 | ```sql 325 | -- Siempre prueba cambios grandes dentro de una transacción 326 | START TRANSACTION; 327 | 328 | -- Ejemplo: subir edad +1 a inscriptos en 'TypeScript' 329 | UPDATE alumnos a 330 | JOIN inscripciones i ON i.idx_alumno = a.id_alumno 331 | JOIN cursos c ON c.id_curso = i.idx_curso 332 | SET a.edad = a.edad + 1 333 | WHERE c.nombre_curso = 'TypeScript'; 334 | 335 | -- Revisión rápida 336 | SELECT a.id_alumno, a.nombre, a.edad FROM alumnos a 337 | WHERE a.id_alumno IN (SELECT idx_alumno FROM inscripciones WHERE idx_curso = (SELECT id_curso FROM cursos WHERE nombre_curso='TypeScript')); 338 | 339 | -- Si todo OK: 340 | COMMIT; 341 | -- Si encontraste un problema: 342 | -- ROLLBACK; 343 | ``` 344 | 345 | **Buenas prácticas rápidas:** 346 | 347 | - Siempre usar `WHERE` en `UPDATE/DELETE` (o transacción + `SELECT` de control). 348 | - Validar cardinalidad de subconsultas escalar (que devuelva 0/1 fila). 349 | - Para upsert, preferir `ON DUPLICATE KEY UPDATE` sobre `INSERT IGNORE`. 350 | - Documentar supuestos (sin `ON DELETE CASCADE`, borrar hijos primero). 351 | 352 | --- 353 | 354 | ## 🧪 Ejercicios guiados (con solución) 355 | 356 | > **Antes de empezar**: vuelve a correr el _Setup_ si destrozaste datos. 😉 357 | 358 | ### Ejercicio 1 — Insert masivo inteligente 359 | 360 | **Enunciado:** Inscribí a todos los alumnos **argentinos** en el curso **'Docker'**, pero solo si **no están ya inscriptos**. 361 | 362 | **Solución:** 363 | 364 | ```sql 365 | INSERT INTO inscripciones (idx_alumno, idx_curso) 366 | SELECT a.id_alumno, c.id_curso 367 | FROM alumnos a 368 | JOIN cursos c ON c.nombre_curso='Docker' 369 | WHERE a.nacionalidad='Argentina' 370 | AND NOT EXISTS ( 371 | SELECT 1 FROM inscripciones i WHERE i.idx_alumno=a.id_alumno AND i.idx_curso=c.id_curso 372 | ); 373 | ``` 374 | 375 | --- 376 | 377 | ### Ejercicio 2 — Update con subconsulta correlacionada 378 | 379 | **Enunciado:** Seteá `nacionalidad='Argentina'` a cualquier alumno cuya **única** inscripción sea a un curso de la categoría **'Datos'**. 380 | 381 | **Solución:** 382 | 383 | ```sql 384 | UPDATE alumnos a 385 | SET nacionalidad='Argentina' 386 | WHERE EXISTS ( 387 | SELECT 1 388 | FROM inscripciones i 389 | JOIN cursos c ON c.id_curso = i.idx_curso 390 | JOIN categoria cat ON cat.id_categoria = c.id_categoria 391 | WHERE i.idx_alumno = a.id_alumno AND cat.nombre_categoria='Datos' 392 | ) 393 | AND 1 = ( 394 | SELECT COUNT(*) FROM inscripciones i2 WHERE i2.idx_alumno = a.id_alumno 395 | ); 396 | ``` 397 | 398 | --- 399 | 400 | ### Ejercicio 3 — Delete con `NOT EXISTS` 401 | 402 | **Enunciado:** Borrá **solo** las inscripciones de alumnos que **no tengan email** (pero mantené los alumnos). 403 | 404 | **Solución:** 405 | 406 | ```sql 407 | DELETE FROM inscripciones i 408 | WHERE NOT EXISTS ( 409 | SELECT 1 FROM alumnos a 410 | WHERE a.id_alumno = i.idx_alumno AND a.email IS NOT NULL 411 | ); 412 | ``` 413 | 414 | --- 415 | 416 | ### Ejercicio 4 — UPSERT ordenado 417 | 418 | **Enunciado:** Insertá o actualizá el email de `dni = 29888777` a `diego.ramos@coder.com`. 419 | 420 | **Solución:** 421 | 422 | ```sql 423 | INSERT INTO alumnos (nombre, apellido, email, dni) 424 | VALUES ('Diego','Ramos','diego.ramos@coder.com', 29888777) 425 | ON DUPLICATE KEY UPDATE email = VALUES(email); 426 | ``` 427 | 428 | --- 429 | 430 | ### Ejercicio 5 — CTE en `DELETE` 431 | 432 | **Enunciado:** Eliminá todas las inscripciones de cursos de **'Cloud'** usando CTE. 433 | 434 | **Solución:** 435 | 436 | ```sql 437 | WITH cursos_cloud AS ( 438 | SELECT c.id_curso 439 | FROM cursos c 440 | JOIN categoria cat ON cat.id_categoria = c.id_categoria 441 | WHERE cat.nombre_categoria = 'Cloud' 442 | ) 443 | DELETE i FROM inscripciones i 444 | JOIN cursos_cloud cc ON cc.id_curso = i.idx_curso; 445 | ``` 446 | 447 | --- 448 | 449 | ## 🔍 Chequeos útiles para el profe (y para no pisar el palito) 450 | 451 | ```sql 452 | -- Ver alumnos sin inscripciones 453 | SELECT a.* 454 | FROM alumnos a 455 | LEFT JOIN inscripciones i ON i.idx_alumno = a.id_alumno 456 | WHERE i.idx_alumno IS NULL; 457 | 458 | -- Top cursos por cantidad de inscriptos 459 | SELECT c.nombre_curso, COUNT(*) AS cantidad 460 | FROM inscripciones i 461 | JOIN cursos c ON c.id_curso = i.idx_curso 462 | GROUP BY c.id_curso 463 | ORDER BY cantidad DESC; 464 | 465 | -- Duplicidad potencial por email o dni (debería ser 1 siempre) 466 | SELECT email, COUNT(*) FROM alumnos GROUP BY email HAVING COUNT(*) > 1; 467 | SELECT dni, COUNT(*) FROM alumnos GROUP BY dni HAVING COUNT(*) > 1; 468 | ``` 469 | 470 | --- 471 | 472 | ## 🧩 Bonus de comparación: JOIN vs Subconsulta 473 | > 474 | > Mismo resultado, dos enfoques. Que el alumno compare **legibilidad** y **rendimiento** según el caso. 475 | 476 | **Con subconsulta:** 477 | 478 | ```sql 479 | UPDATE alumnos 480 | SET edad = edad + 1 481 | WHERE id_alumno IN ( 482 | SELECT i.idx_alumno 483 | FROM inscripciones i 484 | JOIN cursos c ON c.id_curso = i.idx_curso 485 | WHERE c.nombre_curso = 'TypeScript' 486 | ); 487 | ``` 488 | 489 | **Con JOIN:** 490 | 491 | ```sql 492 | UPDATE alumnos a 493 | JOIN inscripciones i ON i.idx_alumno = a.id_alumno 494 | JOIN cursos c ON c.id_curso = i.idx_curso 495 | SET a.edad = a.edad + 1 496 | WHERE c.nombre_curso = 'TypeScript'; 497 | ``` 498 | 499 | --- 500 | 501 | ## ✅ Cierre (mensaje para el alumno) 502 | 503 | - Dominar **DML** te da control total de los datos. 504 | - Las **subconsultas** son tu navaja suiza para escribir operaciones expresivas sin perder atomicidad. 505 | - Si la operación es grande o sensible: **transacción + verificación + commit**. 506 | - Y si algo falla: **ROLLBACK** y a iterar. 507 | 508 | > Si esto te gustó, la próxima clase metemos índices, planes de ejecución y bloqueos… para que tu SQL vuele sin humo 🚀 509 | --------------------------------------------------------------------------------