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