> **📝 Exame Tema 3: Uso de Bases de Datos**

# Pregunta 1 (Desenvolvemento - Galego):

Estás configurando a conexión dende un servidor de aplicacións a un servidor de bases de datos remoto. Explica cales son os parámetros mínimos que adoitan formar parte dunha **"Connection String" (Cadea de conexión)** e que medidas de seguridade a nivel de rede deberías comprobar no servidor de BD para permitir que esa conexión se estableza correctamente.

## Resposta

Polo visto no resto de cuestións que me formulas, velaquí temos una serie de opcións alternativas por mor de que sei que o exame vai orientado principalmente a SQL Server, pero postos a ampliar a MySQL/MariaDB, tambén meto o reto de SQLite.

O máis básico é entender que a cadea de conexión non é máis que un simple String que contén a información necesaria para que a conexión poda xerarse e xestionarse correctamente. Polo xeral, ante unha cadea de conexión temos siempre que iniciarla sempre co Driver, salvo que a librería de conexión que usemos xa veña definida a un motor concreto, e tralo driver sería especificar, normalmente, o Hosts onde se ubica, e o porto de traballo no que se vai xestionalo consumo do servizo, aínda que éste último poderíase obviar se éste ven sendo o que ten por defecto dito motor, xa sexa o 3306 para MariaDB/MySQL como 1433 para SQL Server, pero sen esquecer que no caso de SQLite, esta parte sería o Path onde se aloxe o arquivo de base de datos ou a especificación `:memory:` para tela temporalmente en memoria RAM. Para continuar, as credenciais de acceso, como o usuario, a contrasinal, condicións de conexión que se podidan haber configurado, como certificados, protocolos, etc. É importante ter en conta que nun entorno Microsoft sobre SQL Server temos tamén o método de acceso mediante a identificación de Windows. Tamén é importante destacar que SQLite non soe traer configuración de usuario e contrasinal, pese a que sí se lle poida asinar.

Cara ámbitos de seguridade que se pode xestionar cara a súa conectividade, o máis básico sería o traballo de portos e Forwarding, xa sexa co Firewall de Windows como co IPTables de Linux, entre outras moitas opcións que poidan existir, xa sexa en convivencia o substitución. Por outra banda, unha boa práctica sería xerar un usuario para cada servizo cos permisos mínimos que requiera, específicos para o consumo de dito servizo, isto evita que en caso de SQL Injection; ou peor aínda, que se faga ByPass coa contorna do programa, éste quede limitado ó usuario concreto, protexendo o resto da base de datos, ainda que só e viable en SQL Server e MariaDB/MySQL neste caso, ó igual que facer uso de Procedementos Almaceados onde xeralas consultas e iteraccións cos datos, ocultando a estructura e demáis pezas do entorno de datos mediante o permiso único "execute", ainda que en SQL Server, cara consultas, éste ten que ir acompañado de "select" tamén, desgracidamente, cando se fai uso de dinamismos coma os `sp_executesql`.

> **Anotacións**: Foi todo de memoria, non mirei nada, así que aquí arríscome. ¡Jajajaja!

## Corrección

- **Contido técnico**: Moi ben. Identificas os elementos clave: **Driver, Host, Porto, Base de Datos, Usuario e Contrasinal**. Tamén o matiz de SQLite (`:memory:`) e a identificación integrada de Windows en SQL Server.
- **Seguridade**: Correcto o de usar o principio de **mínimo privilexio** e o firewall.
- **Corrección lingüística**:
    - "**Tambén**": En galego é "**tamén**" (con 'm' antes de 'é').
    - "**Xestionalo** consumo": O correcto sería "**xestionar** o consumo" (non hai contracción de infinitivo + artigo salvo casos moi específicos de pronomes clíticos).
    - "**Habere** configurado": Mellor "**ter** configurado".
    - "**Procedementos Almaceados**": O termo técnico correcto en galego é **Procedementos almacenados**.

# Pregunta 2 (Respuesta corta - Castellano):

Imagina que ejecutas la siguiente sentencia en una tabla llamada `Equipos`:

```sql
DELETE FROM Equipos;
```

Sin haber realizado un `COMMIT` previo, ¿qué diferencia habría en la gestión de esta operación si la tabla utiliza el motor **MyISAM** frente a si utiliza **InnoDB** en MySQL/MariaDB?

## Respuesta

En InnoDB se haría dato por dato por estar funcionando a Full bajo ACID, mientras que MyISAM hace bloqueo hasta acabar la operación para garantizar consistencia. Es importante mencionar que al usar niveles transaccionales, sólo se reflejan los cambios cara los demás una vez se finalicen los mismos. Es una anotación importante para casos de uso simultáneo con InnoDB, por ejemplo, o de una operación pesada con MyISAM, que mientras no commitee, otros usuarios quizás no vean el cambio. Es un poco similar a cuando se operan Scripts SQL Server antes de un Go, donde vemos que podemos caer en la inconsistencia de no existir hasta que se finalice.

> **Nota**: Aquí llamo Commit también a la finalización de la orden o conjunto de órdenes o sesión de ejecución pues hace un sistema transaccional igualmente, con la diferencia de que InnoDB permite, sin definición del `begin transaction` realizar operaciones que dinámicamente irán teniendo su efecto síncronamente con otros usuarios que puedan estar en consumo de dichos datos.

> **Anotaciones**: Aquí me sentí muy mal buscando información pues sabía de ambas por uso y experiencia, sin embargo, ya sea por el tiempo transcurrido desde la última vez que usé MariaDB, pues la verdad que ni siquiera me acordaba de ACID, pero bueno, ahora ya sí: Atomicidad, Consistencia, Aislamiento y Durabilidad.

## Corrección

- **Contido técnico**: Aquí hay un error de concepto **MUY IMPORTANTE**.
    - **Dices**: "*En InnoDB se haría dato por dato... mientras que MyISAM hace bloqueo*".
    - **La realidad**: **MyISAM NO soporta transacciones**. Si haces un `DELETE FROM Equipos;` en MyISAM, los datos se borran **al instante** y no hay vuelta atrás. El `COMMIT` o `ROLLBACK` simplemente no existen para MyISAM.
    - En **InnoDB**, si no tienes el `autocommit` activado, los datos no se borran definitivamente hasta que haces `COMMIT`.
- **Corrección lingüística**:
    - "**halla** obtenido": ¡Repetimos error! Recuerda: **haya** (haber), **halla** (encontrar). ¡Te voy a poner un póster en la habitación con esto! 😂

# Pregunta 3 (Tipo Test con "trampa" - Galego):

Queremos realizar unha consulta que nos devolva o número de switches que hai en cada planta do Concello, pero só de aquelas plantas que teñan máis de 5 switches. Indica cal destas sentenzas SQL é a **CORRECTA**:

- A) `SELECT planta, COUNT(*) FROM switches WHERE COUNT(*) > 5 GROUP BY planta;`
- B) `SELECT planta, COUNT(*) FROM switches GROUP BY planta HAVING COUNT(*) > 5;`
- C) `SELECT planta, SUM(switches) FROM switches GROUP BY planta WHERE SUM(switches) > 5;`
- D) `SELECT planta, COUNT(*) FROM switches HAVING COUNT(*) > 5;`

> **Nota**: Marca a correcta e xustifica tecnicamente por que as outras fallan.

## Resposta

Neste caso a correcta viría sendo a C por mor de:

- **A**: O `where` filtra antes da agrupación, polo que só dará resultado condicionado cara o seu conxunto por mor de haber unha función de grupo.
- **B**: Agrupa por `planta` e colle só aquelas que teñan máis de 5 tuplas mediante a función de grupo `count`.
- **C**: Agrupa por `planta` e colle só aquelas que teñan máis da suma dos Switches no conxunto de tuplas dentro das plantas mediante a función de grupo `sum`.
- **D**: Achéganos a condición de grupo sobre o global.

> **Anotacións**: Encantoume este exercicio. A trampa e moi sutil e fácil de deixar sobreentendida por mor de que sempre identificamos un switch por tupla, e cada Switch está nunha planta, pero o estaren o atributo en plural enténdese que é o número de Switches nesa planta, e pola función de grupo, enténdese ademáis que pode haber máis dunha tupla referida á mesma planta. Toda unha malévola xenialidade. ¡Jajajajaja! Tamén dicir que a estou a responder a cegas, é dicir, se mirar. ¡Jajajaja!

## Corrección

- **A túa resposta**: Marcaches a **C**.
- **A resposta correcta**: É a **B**.
- **Por que fallaches?**:
    1. **Sintaxe**: Na opción C usas un `WHERE` despois dun `GROUP BY`. Iso é un erro de sintaxe de libro. O filtro para grupos **SEMPRE** é o `HAVING`.
    2. **Lóxica**: Pides o "número de switches" (`COUNT`) por planta. Se usas `SUM(switches)`, estarías sumando os valores dunha columna numérica, non contando filas.
    3. **A trampa do HAVING**: O `HAVING` é o que permite filtrar funcións de agregado (como `COUNT(*) > 5`).
- **Análise das outras**:
    - **A**: Incorrecta. Non se pode usar `COUNT(*)` nun `WHERE` directamente sen unha subconsulta.
    - **D**: Incorrecta. Falta o `GROUP BY` para poder usar o `HAVING` por planta.

# Pregunta 4 (Lóxica/Seguridade - Castellano):

En el contexto de "operaciones básicas", se habla mucho del **SQL Injection**. Explica brevemente qué es y, sobre todo, qué técnica de programación relacionada con las "consultas" (queries) es la más eficaz para prevenirlo sin tener que limpiar manualmente cada cadena de texto.

## Respuesta

El SQL Injection es una práctica de Hacking que se basa en explotar una vulnerabilidad que te permite inyectar código SQL. Un caso clásico puede ser en un Login o cualquier campo que el atacante sepa que vaya contra una consulta como opción de campo donde el atacante, si consigue averiguar en qué motor está, poder hacer un cierre o concatenación para inyectar consultas de interés para éste. Un clásico sería hacer uso de la comilla en MariaDB para cerrar el String, poner un punto y coma (";") y continuar con otra consulta y esperar resultados de la consulta sobre una URL sobre petición. Esto es aplicable también a SQL Server y SQLite pero con la diferencia de que en SQL Server hay que implementar saltos de línea para cambiar de consulta.

Para poder evitar este tipo de prácticas sin ir contra el String en cuestión, como se podría, mediante escapar caracteres como la propia comilla, es hacer uso de las herramientas ofrecidas en los conectores pues es raro que no traigan de por sí alguna herramienta para gestionar las variables sobre las consultas que hagan dicha función.

> **Anotaciones**: Voy a arriesgar a decirlo sin mirar ni buscar nada, pese a que hay una cosa que posiblemente la busque después, dependiendo de qué me digas bajo la respuesta.

## Corrección

- **Contido técnico**: Explicas bien el concepto, pero te pedía la **técnica de programación** específica.
- **La respuesta que buscaba**: **Consultas Preparadas o Parametrizadas (Prepared Statements)**.
    - En lugar de concatenar el string (`"SELECT * FROM users WHERE id = " + id`), usas marcadores (`"SELECT * FROM users WHERE id = ?"`). El motor de la BD compila la consulta y luego le "pasa" el dato, tratando el dato siempre como texto/valor y nunca como código ejecutable.
- **Corrección lingüística**:
    - "**Aproechar**": Recuerda, aprovechar.