252 lines
6.8 KiB
Markdown
252 lines
6.8 KiB
Markdown
> *A REVANCHA: EXAME TÉCNICO (BLOQUE 2)*
|
|
|
|
# I. DESENVOLVEMENTO E LÓXICA (C# / Python)
|
|
|
|
## 1. O Filtro de Seguridade (Tema 1 e 5):
|
|
|
|
Imagina que recibes una lista de "IDs de empleados" como un array de strings. Algunos pueden ser nulos o estar vacíos.
|
|
|
|
- Escribe una función/método que recorra la lista y solo imprima los IDs que tengan exactamente 5 caracteres y no sean nulos.
|
|
- Reto Extra: Usa un bloque try-catch (C#) o try-except (Python) para evitar que el programa explote si algún elemento de la lista da problemas.
|
|
|
|
### Respuesta
|
|
|
|
En C#:
|
|
|
|
```cs
|
|
using System.Collections.Generic;
|
|
using System;
|
|
|
|
namespace Examen{
|
|
class Empleado{
|
|
|
|
public string? id;
|
|
|
|
public Empleado(string? id = null){
|
|
this.id = id;
|
|
}
|
|
|
|
public static List<string> filtrar(List<Empleado> empleados){
|
|
|
|
List<Empleado> filtrados = new List<Empleado>();
|
|
|
|
foreach(Empleado empleado in empleados)
|
|
if(empleado.id != null && empleado.id.Length == 5){
|
|
Console.WriteLine(empleado.id);
|
|
filtrados.Add(empleado);
|
|
}
|
|
|
|
return filtrados;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
```
|
|
|
|
En Python:
|
|
|
|
```py
|
|
from typing import Self, Optional, Sequence
|
|
|
|
class Empleado:
|
|
|
|
def __init__(self:Self, id:Optional[str] = None) -> None:
|
|
self.id:str|None = id
|
|
|
|
@staticmethod
|
|
def filtrar(empleados:Sequence[type[Self]]) -> list[type[Self]]:
|
|
|
|
filtrados:list[Empleado] = []
|
|
empleado:Empleado
|
|
|
|
for empleado in empleados:
|
|
if empleado.id is not None and len(empleado.id) == 5:
|
|
print(empleado.id)
|
|
filtrados.append(empleado)
|
|
|
|
return filtrados
|
|
```
|
|
|
|
Para los SQL hay que hacer uso de Procedimientos y no de funciones pues las funciones pueden retornar un valor, pero no pueden alterar ni mostrar selecciones.
|
|
|
|
En SQL Server:
|
|
|
|
```sql
|
|
use Examen
|
|
|
|
if object_id(N'dbo.crear_tablas', N'P') is not null drop procedure dbo.crear_tablas
|
|
go
|
|
create procedure dbo.crear_tablas as begin
|
|
|
|
set nocount on
|
|
|
|
if object_id(N'dbo.Empleados', N'U') is null create table dbo.Empleados(
|
|
id varchar(16) not null,
|
|
constraint empleados_id primary key(id),
|
|
constraint empleados_uq_id index unique(id)
|
|
)
|
|
|
|
end
|
|
go
|
|
|
|
if object_id(N'dbo.filtrar_empleados', N'P') is not null drop procedure dbo.filtrar_empleados
|
|
go
|
|
create procedure dbo.filtrar_empleados
|
|
@filtrados varchar(max) output
|
|
as begin
|
|
|
|
set nocount on
|
|
|
|
select id from dbo.Empleados where id is not null and len(id) = 5
|
|
set @filtrados = (select top 1 stuff((select ',' + id from dbo.Empleados where id is not null and len(id) = 5), 1, 1, '') as ids)
|
|
|
|
end
|
|
go
|
|
|
|
```
|
|
|
|
En MySQL/MariaDB:
|
|
|
|
```sql
|
|
use Examen;
|
|
|
|
delimiter ;^
|
|
|
|
drop procedure if exists crear_tablas;^
|
|
create procedure crear_tablas() begin
|
|
|
|
create table if not exists Empleados(
|
|
id varchar(16) not null,
|
|
constraint empleados_id primary key(id)
|
|
);
|
|
|
|
end;^
|
|
|
|
drop procedure if exists dbo.filtrar_empleados;^
|
|
create procedure dbo.filtrar_empleados(
|
|
out $filtrados text
|
|
) begin
|
|
select id from Empleados where id is not null and lenght(id) = 5;
|
|
set $filtrados := (select substring(ids, 1, length(ids)) as ids from (
|
|
select group_concat(',', id) from Empleados where id is not null and lenght(id) = 5 as ids
|
|
) limit 1);
|
|
end;^
|
|
|
|
delimiter ;
|
|
|
|
```
|
|
|
|
En SQLite no se puede de forma nativa, requerirías de estructuras que lo acompañen en otros lenguajes.
|
|
|
|
### Corrección
|
|
|
|
- **C#**: Muy buena implementación. Solo un detalle de "profesor tiquismiquis": en la clase `TicketUrxente` del ejercicio siguiente intentas acceder a `this.id`, pero en la clase base `Ticket` lo definimos como `private`. Para que la clase hija lo vea, debería ser `protected`.
|
|
- **Python**: Perfecto el uso de `@staticmethod` y `Optional`.
|
|
- **SQL Pro**: Me has dejado loco con el procedimiento de filtrado. Usar `STUFF` para quitar la primera coma es de nivel experto en oposiciones de sistemas.
|
|
|
|
## 2. Herdanza e Métodos (Tema 4):
|
|
|
|
Si la clase Ticket de antes era la base, ahora crea una clase TicketUrxente que herede de Ticket.
|
|
|
|
- Esta clase hija debe tener un constructor que pase el id a la clase padre (base).
|
|
- Sobreescribe o añade un método para que, además de lo anterior, devuelva un mensaje que diga: "Prioridade Máxima asignada ao Ticket [ID]".
|
|
|
|
### Respuesta
|
|
|
|
En C#:
|
|
|
|
```cs
|
|
using Examen;
|
|
|
|
namespace Examen{
|
|
class TicketUrxente:Ticket{
|
|
|
|
public TicketUrxente(int id):base(id){}
|
|
|
|
public string coger_mensaje_completo(){
|
|
return "Prioridade Máxima asinada ao Ticket [" + this.id + "]";
|
|
}
|
|
|
|
}
|
|
}
|
|
```
|
|
|
|
En Python:
|
|
|
|
```py
|
|
from typing import Self
|
|
from Examen import Ticket
|
|
|
|
class TicketUrxente(Ticket):
|
|
|
|
def __init__(self:Self, id:int) -> None:
|
|
super().__init__(id)
|
|
|
|
def coger_mensaje_completo(self:Self) -> str:
|
|
return "Prioridade Máxima asinada ao Ticket [" + str(self.id) + "]"
|
|
|
|
```
|
|
|
|
### Correción
|
|
|
|
- **C#**: Como te decía arriba, solo recuerda cambiar `private int id` por `protected int id` en la base para que el `TicketUrxente` pueda hacer el `+ this.id`.
|
|
- **Python**: Uso de `super().__init__(id)` perfecto.
|
|
|
|
# II. SQL SERVER: O RETORNO DO "FROM" (Tema 7)
|
|
|
|
3. A Consulta de Equipos:
|
|
|
|
Tenemos dos tablas:
|
|
|
|
- Equipos (id_equipo, nome_equipo, id_responsable)
|
|
- Responsables (id_responsable, nome_persona)
|
|
|
|
Escribe una consulta SQL que devuelva:
|
|
|
|
- El nome_equipo y el nome_persona del responsable.
|
|
- Pista: Necesitarás un JOIN. No te olvides del FROM.
|
|
|
|
## Respuesta
|
|
|
|
En SQL Server:
|
|
|
|
```sql
|
|
select
|
|
equipos.nome_equipo as equipo,
|
|
responsables.nome_persoa as responsable
|
|
from dbo.Equipos equipos
|
|
join dbo.Responsables resonsables on equipos.id_responsable = responsables.id_responsable
|
|
```
|
|
|
|
En MySQL/MariaDB y SQLite:
|
|
|
|
```sql
|
|
select
|
|
equipos.nome_equipo as equipo,
|
|
responsables.nome_persoa as responsable
|
|
from Equipos equipos
|
|
join Responsables resonsables on equipos.id_responsable = responsables.id_responsable
|
|
```
|
|
|
|
## Corrección
|
|
|
|
- **¡Objetivo cumplido!** El `FROM` está donde debe estar.
|
|
- **Ojo con los alias**: En el `JOIN` de SQL Server escribiste `resonsables` (te faltó la 'p') pero luego llamaste a `responsables.id_responsable`. Es un error de escritura (typo) típico del cansancio, pero la lógica del `ON` es impecable.
|
|
|
|
# III. PREGUNTA TRAMPA DE SISTEMAS (Tema 27)
|
|
|
|
4. Scripting en Bash:
|
|
|
|
Tienes que crear un script de una sola línea (o muy breve) que verifique si un archivo llamado backup_diario.sql existe en la carpeta actual. Si existe, que imprima "Ficheiro atopado".
|
|
|
|
## Respuesta
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
[ -f backup_diario.sql ] && echo "Fichero atopado"
|
|
```
|
|
|
|
## Corrección
|
|
|
|
- **Perfecto**. El uso del operador AND lógico `&&` es la forma más profesional y rápida de hacer un "one-liner" en Bash para oposiciones. |