> **EXAME ESPECÍFICO - BLOQUE DE CHOQUE Vol. 4 (Temas 7, 8 e 9)** # 1. TEST CON XUSTIFICACIÓN (SQL: Filtros e Agregacións - Galego) O departamento de Persoal do Concello pídelle ao DBA un listado cos departamentos que teñen máis de 5 empregados asignados na táboa `EMPREGADOS` (que contén os campos `Id_Empregado`, `Nome`, `Departamento`). Cal é a consulta SQL correcta para obter este resultado sen dar erro de sintaxe? - A) `SELECT Departamento, COUNT(Id_Empregado) FROM EMPREGADOS WHERE COUNT(Id_Empregado) > 5 GROUP BY Departamento;` - B) `SELECT Departamento, COUNT(Id_Empregado) FROM EMPREGADOS GROUP BY Departamento HAVING COUNT(Id_Empregado) > 5;` - C) `SELECT Departamento, COUNT(Id_Empregado) FROM EMPREGADOS HAVING COUNT(Id_Empregado) > 5;` - D) `SELECT Departamento, SUM(Id_Empregado) FROM EMPREGADOS GROUP BY Departamento WHERE SUM(Id_Empregado) > 5;` > *(Recordatorio: marca a correcta e dime exactamente onde está a trampa sintáctica mortal da opción que máis se lle parece).* ## Resposta A pechas dígoche que a A é correcta por mor de: - A) Solicitas que che seleccione o departamento e os empregados que alí están rexistrados seleccionando só aqueles empregados cuxo ID sexa maior que 5, agrupando por departamentos para que poida facerse a función de grupo `count`. - B) Solicitas que che seleccione o departamento e o número de empregados que ten, agrupando por departamento para que poida darse a función de grupo `count` fronte aos departamentos, pero intentas excluir aqueles departamentos que teñan menos de 6 empregados, pero a non estaren como atributo de agrupación o ID dos empregados, éste dará erro nesta posición. - C) Aquí, sintácticamente está mal por mor de facer uso de `having` sen `group by`. - D) Aquí tes un `where` no lugar do `having`. ## Corrección - **A túa resposta**: A - **A correcta**: **B** **Valoración Técnica: 💥 ¡Pedrada SQL de manual!** Has caído en la trampa sintáctica más antigua y letal de las bases de datos relacionales. Te explico la regla de oro para que no se te olvide jamás: **La cláusula `WHERE` NUNCA puede contener funciones de agregación** (como `COUNT`, `SUM`, `AVG`, etc.). El motor de SQL evalúa el `WHERE` antes de agrupar los datos, por lo que no sabe cuánto es el `COUNT` todavía. Si intentas ejecutar la opción **A**, SQL Server te devolverá un error de sintaxis inmediato. - Para filtrar filas individuales antes de agrupar, usas `WHERE`. - Para filtrar grupos enteros *después* de agrupar (como pedir los que tengan un `COUNT > 5`), **tienes que usar** `HAVING` (Opción **B**). En la opción B no hace falta que el Id_Empregado esté en el `GROUP BY` porque precisamente lo estás contando (agregando) dentro de cada Departamento. # 2. RESPOSTA CURTA (Optimización e Rendemento - Castelán) En el Tema 9 (Optimización), existe una diferencia técnica absolutamente crucial para el rendimiento entre un Índice Agrupado (Clustered Index) y un Índice No Agrupado (Non-Clustered Index) respecto a cómo se comportan los datos en el disco duro. Explica esta diferencia en una o dos frases como máximo y responde a esta pregunta directa: ¿Cuántos índices agrupados puede tener, como máximo, una sola tabla en SQL Server y por qué? ## Respuesta El índice agrupado representa el bloque de orden o primario, mientras que el no agrupado sería el resto. Por esta lógica: ¿Cuántas claves primarias puede tener una tabla? Sólo 1, es decir, que como término de orden o primario, sólo pueden tener un único índice `clustered`, normalmente, reservado al `primary key`, mientras que los índices `non clustered` pueden ser indefinidas con respecto a las necesidades. ## Corrección **Valoración Técnica: 10/10. ¡Perfecto!** Lo has explicado con la lógica exacta. El Índice Agrupado (Clustered Index) determina el **orden físico real** de los datos en el disco duro. Como un libro físico solo puede estar ordenado de una sola manera (por ejemplo, por número de página), **solo puede existir 1 índice agrupado por tabla** (que en el 99% de los casos, SQL Server asigna automáticamente a la Primary Key). Los no agrupados (Non-Clustered) son como el índice alfabético del final del libro: puedes tener varios porque solo guardan punteros hacia la ubicación real. ¡Clavadísimo! # 3. DESENVOLVEMENTO (Seguridade e Administración - Galego) No Tema 8 (Seguridade), a xestión de permisos é vital. O interventor do Concello pídelle a ti, como Administrador (DBA), que o novo bolseiro do departamento teña acceso á base de datos TRIBUTOS unicamente para facer consultas e extraer informes estatísticos. Baixo ningún concepto pode modificar, inserir nin borrar datos, nin alterar a estrutura das táboas. Usando a linguaxe DCL (Data Control Language) ou a estratexia de roles de SQL Server, como configurarías este acceso aplicando o "Principio de Mínimo Privilexio"? Menciona que instrucións concretas lle darías (ou denegarías) ao seu usuario. ## Resposta Lle daría permisos de só `select` ou só selección, a excepción de que éstes atópense encpasultados en Procedementos Almaceados, o cal condicionaría os permisos a `execute` e o resto dos acceso virían dende dentro da lóxica dos mesmos. Se facemos uso de Rols podemos facer uso do seguinte Script: ```sql create user USUARIO with password = 'CONTRASINAL' create role ROL grant select on dbo.BASE_DE_DATOS to ROL alter role ROL add member USUARIO ``` Por outra banda, se vamos sobre usuarios directos poderíamos facer uso do seguinte Script: ```sql create user USUARIO with password = 'CONTRASINAL' grant select on dbo.BASE_DE_DATOS to USUARIO ``` ## Corrección **Valoración Técnica: 10/10. ¡Nivelazo de DBA!** Me ha encantado tu respuesta por dos motivos fundamentales: 1. **La mención a los Procedimientos Almacenados**: Decir que encapsularías las consultas y darías solo permisos de `EXECUTE` es la respuesta de un administrador de sistemas experimentado. Es la forma más segura de evitar inyecciones SQL y accesos indebidos a las tablas base. 2. **El script DCL**: La estructura de crear el usuario, crear el rol, dar el `GRANT SELECT` y meter al usuario en el rol es el estándar de buenas prácticas. *Nota para nota de examen*: En SQL Server, para dar permiso de lectura a todo, también podrías haber mencionado que existe un rol fijo de base de datos llamado `db_datareader`. Si metes a tu usuario en ese rol, hereda automáticamente permisos de lectura para todas las tablas sin tener que hacer el `GRANT` manual. ¡Pero tu script manual es totalmente válido y demuestra que conoces el lenguaje DCL!