cambiada nomenclatura de las páginas y añadidos posts de documentacion-robeasir.surge.sh
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 41 KiB After Width: | Height: | Size: 41 KiB |
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 25 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 31 KiB |
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 40 KiB |
Before Width: | Height: | Size: 109 KiB After Width: | Height: | Size: 109 KiB |
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 26 KiB |
Before Width: | Height: | Size: 416 KiB After Width: | Height: | Size: 416 KiB |
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 26 KiB |
Before Width: | Height: | Size: 51 KiB After Width: | Height: | Size: 51 KiB |
Before Width: | Height: | Size: 45 KiB After Width: | Height: | Size: 45 KiB |
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 24 KiB |
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 197 KiB After Width: | Height: | Size: 197 KiB |
Before Width: | Height: | Size: 122 KiB After Width: | Height: | Size: 122 KiB |
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 46 KiB |
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
Before Width: | Height: | Size: 83 KiB After Width: | Height: | Size: 83 KiB |
Before Width: | Height: | Size: 63 KiB After Width: | Height: | Size: 63 KiB |
Before Width: | Height: | Size: 214 KiB After Width: | Height: | Size: 214 KiB |
Before Width: | Height: | Size: 70 KiB After Width: | Height: | Size: 70 KiB |
Before Width: | Height: | Size: 131 KiB After Width: | Height: | Size: 131 KiB |
Before Width: | Height: | Size: 63 KiB After Width: | Height: | Size: 63 KiB |
Before Width: | Height: | Size: 148 KiB After Width: | Height: | Size: 148 KiB |
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 34 KiB |
Before Width: | Height: | Size: 131 KiB After Width: | Height: | Size: 131 KiB |
After Width: | Height: | Size: 168 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 39 KiB |
Before Width: | Height: | Size: 53 KiB After Width: | Height: | Size: 53 KiB |
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 35 KiB |
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 28 KiB |
After Width: | Height: | Size: 168 KiB |
Before Width: | Height: | Size: 99 KiB After Width: | Height: | Size: 99 KiB |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 126 KiB After Width: | Height: | Size: 126 KiB |
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 46 KiB |
Before Width: | Height: | Size: 123 KiB After Width: | Height: | Size: 123 KiB |
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 88 KiB After Width: | Height: | Size: 88 KiB |
Before Width: | Height: | Size: 3.5 MiB After Width: | Height: | Size: 3.5 MiB |
Before Width: | Height: | Size: 84 KiB After Width: | Height: | Size: 84 KiB |
Before Width: | Height: | Size: 85 KiB After Width: | Height: | Size: 85 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
After Width: | Height: | Size: 168 KiB |
@ -0,0 +1,303 @@
|
||||
---
|
||||
title: "Práctica 2: Interconexión de Servidores de Bases de Datos"
|
||||
date: 2022-11-27T14:23:15+01:00
|
||||
draft: false
|
||||
image: featured.png
|
||||
categories:
|
||||
- práctica
|
||||
- Administración de Bases de Datos
|
||||
tags:
|
||||
- Oracle
|
||||
- Práctica 2 ABD
|
||||
---
|
||||
|
||||
Las interconexiones de servidores de bases de datos son operaciones que pueden ser muy útiles en
|
||||
diferentes contextos. Básicamente, se trata de acceder a datos que no están almacenados en nuestra base
|
||||
de datos, pudiendo combinarlos con los que ya tenemos.
|
||||
En esta práctica veremos varias formas de crear un enlace entre distintos servidores de bases de datos.
|
||||
Se pide:
|
||||
|
||||
* Realizar un enlace entre dos servidores de bases de datos ORACLE, explicando la configuración
|
||||
necesaria en ambos extremos y demostrando su funcionamiento.
|
||||
* Realizar un enlace entre dos servidores de bases de datos Postgres, explicando la configuración
|
||||
necesaria en ambos extremos y demostrando su funcionamiento.
|
||||
* Realizar un enlace entre un servidor ORACLE y otro Postgres o MySQL empleando Heterogeneus
|
||||
Services
|
||||
|
||||
## Enlace entre dos servidores ORACLE
|
||||
|
||||
En mi caso, las dos máquinas tienen la configuración siguiente; Tienen instalado Rocky 8 Oracle Database 19c Enterprise Edition, y tienen los siguientes nombres e IPs:
|
||||
|
||||
* oracle-maquina1: 192.168.122.204
|
||||
* oracle-maquina2: 192.168.122.80
|
||||
|
||||
En ambas bases de datos existe el usuario roberto y están configuradas para el acceso remoto. Para comprobar que pueden acceder se utiliza el comando tnsping:
|
||||
|
||||
![1](https://i.imgur.com/gbnsKsB.png)
|
||||
|
||||
Ahora, para que los servidores puedan conectarse entre ellos, tenemos que añadir los datos de las máquinas al fichero `/opt/oracle/product/19c/dbhome_1/network/admin/tnsnames.ora`, dejándolos de la siguiente manera:
|
||||
|
||||
* En el fichero dentro de la máquina 1:
|
||||
|
||||
```ora
|
||||
MAQUINA2 =
|
||||
(DESCRIPTION =
|
||||
(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.122.80)(PORT = 1521))
|
||||
(CONNECT_DATA =
|
||||
(SERVER = DEDICATED)
|
||||
(SERVICE_NAME = ORCLCDB)
|
||||
)
|
||||
)
|
||||
```
|
||||
|
||||
* En el fichero dentro de la máquina 2:
|
||||
|
||||
```ora
|
||||
MAQUINA1 =
|
||||
(DESCRIPTION =
|
||||
(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.122.80)(PORT = 1521))
|
||||
(CONNECT_DATA =
|
||||
(SERVER = DEDICATED)
|
||||
(SERVICE_NAME = ORCLCDB)
|
||||
)
|
||||
)
|
||||
```
|
||||
|
||||
Tras eso hay que crear los enlaces haciendo referencia al usuario (roberto). los comandos se ejecutan dentro de oracle:
|
||||
|
||||
* En la máquina 1:
|
||||
|
||||
```sql
|
||||
create database link enlace2 connect to roberto identified by roberto using 'maquina2';
|
||||
```
|
||||
|
||||
* En la máquina 2:
|
||||
|
||||
```sql
|
||||
create database link enlace1 connect to roberto identified by roberto using 'maquina1';
|
||||
```
|
||||
|
||||
Podemos comprobar que se puede acceder remotamente a las tablas:
|
||||
|
||||
![2](https://i.imgur.com/iYYIaiL.png)
|
||||
![3](https://i.imgur.com/2Cu5V0W.png)
|
||||
|
||||
## Enlace entre dos servidores Postgres
|
||||
|
||||
En mi caso, las dos máquinas tienen la configuración siguiente; Tienen instalado Debian 11,MariaDB y PostgreSQL, y tienen los siguientes nombres e IPs:
|
||||
|
||||
* mariadb-maquina1: 192.168.122.97
|
||||
* mariadb-maquina2: 192.168.122.90
|
||||
|
||||
En ambas bases de datos existe el usuario roberto y están configuradas para el acceso remoto.
|
||||
|
||||
Ahora vamos a crear el enlace:
|
||||
|
||||
```bash
|
||||
apt install postgresql-contrib
|
||||
psql -d scott
|
||||
create extension dblink;
|
||||
```
|
||||
|
||||
Una vez hecho eso, tenemos que ejecutar los siguientes comandos:
|
||||
|
||||
* Máquina 1:
|
||||
|
||||
```sql
|
||||
SELECT dblink_connect('dblink2','dbname=scott host=192.168.122.90 user=roberto password=roberto');
|
||||
```
|
||||
|
||||
* Máquina 2:
|
||||
|
||||
```sql
|
||||
SELECT dblink_connect('dblink1','dbname=scott host=192.168.122.97 user=roberto password=roberto');
|
||||
```
|
||||
|
||||
Tras eso, podemos realizar consultas entre máquinas:
|
||||
|
||||
![4](https://i.imgur.com/qzn6uGb.png)
|
||||
|
||||
---
|
||||
|
||||
## Enlace entre un servidor ORACLE y uno Postgres
|
||||
|
||||
En este caso las máquinas que voy a conectar son oracle-maquina1 y mariadb-maquina2, por lo que las direcciones IP son las siguientes:
|
||||
|
||||
* oracle-maquina1: 192.168.122.204
|
||||
* mariadb-maquina2: 192.168.122.90
|
||||
|
||||
### Conexión desde Postgres a ORACLE
|
||||
|
||||
Primero descargamos los siguientes paquetes:
|
||||
|
||||
```bash
|
||||
apt install libaio1 postgresql-server-dev-all build-essential git alien -y
|
||||
```
|
||||
|
||||
Ahora tenemos que descargar el instantclient de oracle, se hace con los siguientes comandos:
|
||||
|
||||
```bash
|
||||
wget https://download.oracle.com/otn_software/linux/instantclient/218000/oracle-instantclient-basic-21.8.0.0.0-1.el8.x86_64.rpm
|
||||
wget https://download.oracle.com/otn_software/linux/instantclient/218000/oracle-instantclient-devel-21.8.0.0.0-1.el8.x86_64.rpm
|
||||
wget https://download.oracle.com/otn_software/linux/instantclient/218000/oracle-instantclient-sqlplus-21.8.0.0.0-1.el8.x86_64.rpm
|
||||
|
||||
sudo alien -i --scripts oracle-instantclient-*
|
||||
```
|
||||
|
||||
Una vez instalado, con el siguiente comando podemos conectarnos a la base de datos de oracle-maquina1:
|
||||
|
||||
```bash
|
||||
sqlplus roberto/roberto@192.168.122.204:1521/ORCLCDB
|
||||
```
|
||||
|
||||
Ahora tenemos que descargar y compilar `oracle_fdw`:
|
||||
|
||||
```bash
|
||||
wget https://github.com/laurenz/oracle_fdw/archive/refs/tags/ORACLE_FDW_2_5_0.zip
|
||||
unzip ORACLE_FDW_2_5_0.zip
|
||||
```
|
||||
|
||||
Renombramos la carpeta:
|
||||
|
||||
```bash
|
||||
mv oracle_fdw-ORACLE_FDW_2_5_0/ oracle_fdw
|
||||
```
|
||||
|
||||
Finalmente compilamos el programa:
|
||||
|
||||
```bash
|
||||
cd oracle_fdw
|
||||
make
|
||||
make install
|
||||
```
|
||||
|
||||
Ahora, dentro de psql (y de la base de datos scott) creamos el enlace. Podemos comprobar que se ha creado con \dx:
|
||||
|
||||
```sql
|
||||
CREATE EXTENSION oracle_fdw;
|
||||
```
|
||||
|
||||
Creamos el schema en el que se van a importar las bases de datos de Oracle:
|
||||
|
||||
```sql
|
||||
create schema oracle;
|
||||
```
|
||||
|
||||
Configuramos un servidor foráneo que haga referencia a la base de datos Oracle en la otra máquina:
|
||||
|
||||
```sql
|
||||
create server oracle foreign data wrapper oracle_fdw options (dbserver '//192.168.122.204/ORCLCDB');
|
||||
```
|
||||
|
||||
Ahora creamos una equivalencia entre un usuario local y el del servidor (aunque en este caso se llaman igual):
|
||||
|
||||
```bash
|
||||
create user mapping for roberto server oracle options (user 'roberto', password 'roberto');
|
||||
```
|
||||
|
||||
Le damos permisos al usuario local sobre el schema de oracle:
|
||||
|
||||
```bash
|
||||
grant all privileges on schema oracle to roberto;
|
||||
grant all privileges on foreign server oracle to roberto;
|
||||
```
|
||||
|
||||
Iniciamos sesión en psql con el usuario que hemos indicado en los pasos anteriores, e importamos el esquema remoto:
|
||||
|
||||
```bash
|
||||
psql -U roberto -W -d scott
|
||||
```
|
||||
|
||||
```bash
|
||||
import foreign schema "ROBERTO" from server oracle into oracle;
|
||||
```
|
||||
|
||||
![5](https://i.imgur.com/EypaWU0.png)
|
||||
|
||||
### Conexión desde Oracle a Postgres
|
||||
|
||||
Para realizar la conexión vamos a utilizar ODBC (Open Database Conectivity); y en este caso ya que vamos a realizar la conexión con PostgreSQL, también tenemos que descargar el paquete específico:
|
||||
|
||||
```bash
|
||||
dnf install unixODBC postgresql-odbc
|
||||
```
|
||||
|
||||
Ahora en el fichero de configuración `/etc/odbcinst.ini` comentamos todas las líneas menos las referentes a postgresql, quedando el fichero de la siguiente manera:
|
||||
|
||||
```bash
|
||||
[PostgreSQL]
|
||||
Description = ODBC for PostgreSQL
|
||||
Driver = /usr/lib/psqlodbcw.so
|
||||
Setup = /usr/lib/libodbcpsqlS.so
|
||||
Driver64 = /usr/lib64/psqlodbcw.so
|
||||
Setup64 = /usr/lib64/libodbcpsqlS.so
|
||||
FileUsage = 1
|
||||
```
|
||||
|
||||
Para configurar el acceso a la máquina con postgres tenemos que crear en el fichero `/etc/odbc.ini` la siguiente entrada:
|
||||
|
||||
```bash
|
||||
[PSQLU]
|
||||
|
||||
Debug = 0
|
||||
CommLog = 0
|
||||
ReadOnly = 0
|
||||
Driver = PostgreSQL
|
||||
Servername = 192.168.122.90
|
||||
Username = roberto
|
||||
Password = roberto
|
||||
Port = 5432
|
||||
Database = scott
|
||||
Trace = 0
|
||||
TraceFile = /tmp/sql.log
|
||||
```
|
||||
|
||||
Podemos comprobar que funciona con isql PSQLU.
|
||||
|
||||
Ahora hay que crear la configuración para que Oracle pueda hacer uso del driver. Para ello tenemos que crear el fichero `/opt/oracle/product/19c/dbhome_1/hs/admin/initPSQLU.ora` con el siguiente contenido:
|
||||
|
||||
```bash
|
||||
HS_FDS_CONNECT_INFO = PSQLU
|
||||
HS_FDS_TRACE_LEVEL = DEBUG
|
||||
HS_FDS_SHAREABLE_NAME = /usr/lib64/psqlodbcw.so
|
||||
HS_LANGUAGE = AMERICAN_AMERICA.WE8ISO8859P1
|
||||
set ODBCINI=/etc/odbc.ini
|
||||
```
|
||||
|
||||
También hay que configurar el listener `/opt/oracle/product/19c/dbhome_1/network/admin/listener.ora`, añadiendo lo siguiente al final:
|
||||
|
||||
```bash
|
||||
SID_LIST_LISTENER =
|
||||
(SID_LIST =
|
||||
(SID_DESC =
|
||||
(SID_NAME = PSQLU)
|
||||
(ORACLE_HOME=/opt/oracle/product/19c/dbhome_1)
|
||||
(PROGRAM=dg4odbc)
|
||||
)
|
||||
)
|
||||
```
|
||||
|
||||
Y añadimos una entrada de conexión a `/opt/oracle/product/19c/dbhome_1/network/admin/tnsnames.ora`:
|
||||
|
||||
```bash
|
||||
PSQLU =
|
||||
(DESCRIPTION=
|
||||
(ADDRESS=(PROTOCOL=tcp)(HOST=localhost)(PORT=1521))
|
||||
(CONNECT_DATA=(SID=PSQLU))
|
||||
(HS=OK)
|
||||
)
|
||||
```
|
||||
|
||||
Ahora reiniciamos el listener y creamos el enlace dentro de oracle.
|
||||
|
||||
```sql
|
||||
create database link postgreslink connect to "roberto" identified by"roberto" using 'PSQLU';
|
||||
```
|
||||
|
||||
Ya está creado el enlace. Ahora para comprobar que funciona, podemos hacer una consulta:
|
||||
|
||||
```sql
|
||||
SELECT "ename" FROM "emp"@postgreslink;
|
||||
```
|
||||
|
||||
![6](https://i.imgur.com/rSga9bn.png)
|
After Width: | Height: | Size: 198 KiB |
@ -0,0 +1,64 @@
|
||||
---
|
||||
title: "Compilación Kernel"
|
||||
date: 2022-12-07T21:18:17+01:00
|
||||
draft: false
|
||||
image: featured.png
|
||||
categories:
|
||||
- documentación
|
||||
- Administración de Sistemas Operativos
|
||||
tags:
|
||||
- Compilación
|
||||
- Debian
|
||||
---
|
||||
|
||||
## Compilación de un Kernel linux a medida
|
||||
|
||||
Al ser linux un kérnel libre, es posible descargar el código fuente, configurarlo y comprimirlo. Además, esta tarea a priori compleja, es más sencilla de lo que parece gracias a las herramientas disponibles.
|
||||
En esta tarea debes tratar de compilar un kérnel completamente funcional que reconozca todo el hardware básico de tu equipo y que sea a la vez lo más pequeño posible, es decir que incluya un vmlinuz lo más pequeño posible y que incorpore sólo los módulos imprescindibles. Para ello utiliza el método explicado en clase y entrega finalmente el fichero deb con el kérnel compilado por ti.
|
||||
El hardware básico incluye como mínimo el teclado, la interfaz de red y la consola gráfica (texto).
|
||||
|
||||
## Descarga
|
||||
|
||||
En este caso vamos a descargar el último kernel de linux de la [página oficial](https://kernel.org/):
|
||||
|
||||
```bash
|
||||
wget https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.0.7.tar.xz
|
||||
tar xf linux-6.0.7.tar.xz
|
||||
cd linux-6.0.7
|
||||
```
|
||||
|
||||
## Compilación del kernel
|
||||
|
||||
Para configurar los módulos que tenemos cargados actualmente en el sistema tenemos que introducir losa siguientes comandos:
|
||||
|
||||
```bash
|
||||
make oldconfig
|
||||
make localyesconfig
|
||||
```
|
||||
|
||||
Con lo siguiente podemos comprobar el número de módulos estáticos y dinámicos que tenemos actualmente:
|
||||
|
||||
```bash
|
||||
egrep '=y' .config | wc -l
|
||||
egrep '=m' .config | wc -l
|
||||
```
|
||||
|
||||
Para compilar el kernel, tenemos que ejecutar el siguiente comando, que aprovecha el número de núcleos que tenemos para reducir al máximo el tiempo de compilación:
|
||||
|
||||
```bash
|
||||
time make -j $(nproc) bindeb-pkg
|
||||
```
|
||||
|
||||
## Reducir el kernel
|
||||
|
||||
Para reducir el tamaño del kernel tenemos que desactivar módulos. Éstos se desactivan ejecutando el siguiente comando:
|
||||
|
||||
```bash
|
||||
make clean
|
||||
make xconfig
|
||||
```
|
||||
|
||||
que abre una interfaz gráfica en la que podemos seleccionar los módulos quq queremos activar o desactivar:
|
||||
|
||||
![https://i.imgur.com/cndWKk6.png](https://i.imgur.com/cndWKk6.png)
|
||||
|
After Width: | Height: | Size: 1.2 MiB |
After Width: | Height: | Size: 168 KiB |
@ -0,0 +1,421 @@
|
||||
---
|
||||
title: "Práctica PL/SQL individual"
|
||||
date: 2022-12-07T13:37:02+01:00
|
||||
draft: false
|
||||
image: featured.png
|
||||
categories:
|
||||
- documentación
|
||||
- Administración de Bases de Datos
|
||||
tags:
|
||||
- Oracle
|
||||
- PL/SQL
|
||||
---
|
||||
|
||||
## Hacer un procedimiento que muestre el nombre y el salario del empleado cuyo código es 7782
|
||||
|
||||
```sql
|
||||
CREATE OR REPLACE PROCEDURE mostrarnombresalario
|
||||
is
|
||||
v_nombre emp.ename%type;
|
||||
v_salario emp.sal%type;
|
||||
begin
|
||||
select ename,sal into v_nombre,v_salario from emp where empno=7782;
|
||||
dbms_output.put_line('El nombre del empleado es ' || v_nombre || ' y su salario es: ' || v_salario);
|
||||
end;
|
||||
/
|
||||
```
|
||||
|
||||
![p1](https://i.imgur.com/CscMTfL.png)
|
||||
|
||||
## Hacer un procedimiento que reciba como parámetro un código de empleado y devuelva su nombre
|
||||
|
||||
```sql
|
||||
CREATE OR REPLACE PROCEDURE mostrarnombresalario2 (p_empno emp.empno%TYPE)
|
||||
is
|
||||
v_nombre emp.ename%type;
|
||||
v_salario emp.sal%type;
|
||||
begin
|
||||
select ename,sal into v_nombre,v_salario from emp where empno=p_empno;
|
||||
dbms_output.put_line('El nombre del empleado es ' || v_nombre || ' y su salario es: ' || v_salario);
|
||||
end;
|
||||
/
|
||||
```
|
||||
|
||||
![p2](https://i.imgur.com/o2tqMaP.png)
|
||||
|
||||
## Hacer un procedimiento que devuelva los nombres de los tres empleados más antiguos
|
||||
|
||||
```sql
|
||||
CREATE OR REPLACE PROCEDURE topantiguos
|
||||
is
|
||||
cursor c_top is
|
||||
select ename
|
||||
from emp
|
||||
order by hiredate asc
|
||||
fetch first 3 rows only;
|
||||
begin
|
||||
dbms_output.put_line('Los 3 empleados mas antiguos son: ');
|
||||
for v_empleado in c_top loop
|
||||
dbms_output.put_line(v_empleado.ename);
|
||||
end loop;
|
||||
end;
|
||||
/
|
||||
```
|
||||
|
||||
![p3](https://i.imgur.com/FOSjg5a.png)
|
||||
|
||||
## Hacer un procedimiento que reciba el nombre de un tablespace y muestre los nombres de los usuarios que lo tienen como tablespace por defecto (Vista DBA_USERS)
|
||||
|
||||
```sql
|
||||
CREATE OR REPLACE PROCEDURE verusuarios (p_tablespace dba_users.default_tablespace%type)
|
||||
is
|
||||
cursor c_usuarios is
|
||||
SELECT username
|
||||
from dba_users
|
||||
where default_tablespace=p_tablespace;
|
||||
begin
|
||||
dbms_output.put_line('El tablespace ' || p_tablespace || ' es el predeterminado de los siguientes usuarios:');
|
||||
for v_usuario in c_usuarios loop
|
||||
dbms_output.put_line(v_usuario.username);
|
||||
end loop;
|
||||
end;
|
||||
/
|
||||
```
|
||||
|
||||
![p4](https://i.imgur.com/U3oRByX.png)
|
||||
|
||||
## Modificar el procedimiento anterior para que haga lo mismo pero devolviendo el número de usuarios que tienen ese tablespace como tablespace por defecto. Nota: Hay que convertir el procedimiento en función
|
||||
|
||||
```sql
|
||||
CREATE OR REPLACE function f_numusuarios (p_tablespace dba_users.default_tablespace%type)
|
||||
return number
|
||||
is
|
||||
v_num number;
|
||||
begin
|
||||
select count(username) into v_num from dba_users where default_tablespace=p_tablespace;
|
||||
return v_num;
|
||||
end;
|
||||
/
|
||||
```
|
||||
|
||||
## Hacer un procedimiento llamado mostrar_usuarios_por_tablespace que muestre por pantalla un listado de los tablespaces existentes con la lista de usuarios de cada uno y el número de los mismos, así: (Vistas DBA_TABLESPACES y DBA_USERS)
|
||||
|
||||
```sql
|
||||
Tablespace xxxx:
|
||||
|
||||
Usr1
|
||||
Usr2
|
||||
...
|
||||
|
||||
Total Usuarios Tablespace xxxx: n1
|
||||
|
||||
Tablespace yyyy:
|
||||
|
||||
Usr1
|
||||
Usr2
|
||||
...
|
||||
|
||||
Total Usuarios Tablespace yyyy: n2
|
||||
....
|
||||
Total Usuarios BD: nn
|
||||
```
|
||||
|
||||
He modificado el procedimiento del ejercicio 4:
|
||||
|
||||
```sql
|
||||
CREATE OR REPLACE PROCEDURE verusuarios (p_tablespace dba_users.default_tablespace%type)
|
||||
is
|
||||
cursor c_usuarios is
|
||||
SELECT username
|
||||
from dba_users
|
||||
where default_tablespace=p_tablespace;
|
||||
begin
|
||||
for v_usuario in c_usuarios loop
|
||||
dbms_output.put_line(CHR(9)|| v_usuario.username);
|
||||
end loop;
|
||||
end;
|
||||
/
|
||||
```
|
||||
|
||||
Y el procedimiento nuevo es:
|
||||
|
||||
```sql
|
||||
CREATE OR REPLACE PROCEDURE mostrar_usuarios_por_tablespace
|
||||
is
|
||||
cursor c_tablespaces is
|
||||
SELECT tablespace_name
|
||||
from dba_tablespaces;
|
||||
v_total_usuario number;
|
||||
v_total number:=0;
|
||||
begin
|
||||
for v_tablespace in c_tablespaces loop
|
||||
dbms_output.put_line('Tablespace ' || v_tablespace.tablespace_name);
|
||||
verusuarios(v_tablespace.tablespace_name);
|
||||
v_total_usuario:=f_numusuarios(v_tablespace.tablespace_name);
|
||||
v_total:=v_total+v_total_usuario;
|
||||
dbms_output.put_line('Total Usuarios tablespace ' || v_tablespace.tablespace_name || ': ' || v_total_usuario);
|
||||
end loop;
|
||||
dbms_output.put_line('Total Usuarios BD : ' || v_total);
|
||||
end;
|
||||
/
|
||||
```
|
||||
|
||||
![p5](https://i.imgur.com/1sCHBpU.png)
|
||||
|
||||
[...]
|
||||
|
||||
![p6](https://i.imgur.com/pbjFtsP.png)
|
||||
|
||||
## Hacer un procedimiento llamado mostrar_codigo_fuente que reciba el nombre de otro procedimiento y muestre su código fuente. (DBA_SOURCE)
|
||||
|
||||
```sql
|
||||
CREATE OR REPLACE PROCEDURE mostrar_codigo_fuente (p_nombre dba_source.name%type)
|
||||
is
|
||||
cursor c_codigo is
|
||||
SELECT text
|
||||
from dba_source
|
||||
where name=p_nombre;
|
||||
begin
|
||||
for v_codigo in c_codigo loop
|
||||
dbms_output.put_line(v_codigo.text);
|
||||
end loop;
|
||||
end;
|
||||
/
|
||||
```
|
||||
|
||||
![p7](https://i.imgur.com/zx9BQyp.png)
|
||||
|
||||
## Hacer un procedimiento llamado mostrar_privilegios_usuario que reciba el nombre de un usuario y muestre sus privilegios de sistema y sus privilegios sobre objetos. (DBA_SYS_PRIVS y DBA_TAB_PRIVS)
|
||||
|
||||
```sql
|
||||
CREATE OR REPLACE PROCEDURE mostrar_privilegios_usuario (p_nombre dba_source.name%type)
|
||||
is
|
||||
cursor c_sistema is
|
||||
SELECT privilege
|
||||
from dba_sys_privs
|
||||
where grantee=p_nombre
|
||||
and ADMIN_OPTION='YES'
|
||||
OR INHERITED='YES';
|
||||
cursor c_objetos is
|
||||
SELECT privilege,table_name
|
||||
from dba_tab_privs
|
||||
where grantee=p_nombre;
|
||||
begin
|
||||
dbms_output.put_line('Privilegios del usuario '|| p_nombre || ' de sistema');
|
||||
for v_sistema in c_sistema loop
|
||||
dbms_output.put_line(CHR(9)||v_sistema.privilege);
|
||||
end loop;
|
||||
dbms_output.put_line('Privilegios del usuario '|| p_nombre || ' sobre objetos');
|
||||
for v_objeto in c_objetos loop
|
||||
dbms_output.put_line(CHR(9)||v_objeto.privilege || '---' || v_objeto.table_name);
|
||||
end loop;
|
||||
end;
|
||||
/
|
||||
```
|
||||
|
||||
![p8](https://i.imgur.com/V9bkArM.png)
|
||||
|
||||
## Realiza un procedimiento llamado listar_comisiones que nos muestre por pantalla un listado de las comisiones de los empleados agrupados según la localidad donde está ubicado su departamento con el siguiente formato:
|
||||
|
||||
```sql
|
||||
Localidad NombreLocalidad
|
||||
|
||||
Departamento: NombreDepartamento
|
||||
|
||||
Empleado1 ……. Comisión 1
|
||||
Empleado2 ……. Comisión 2
|
||||
.
|
||||
.
|
||||
.
|
||||
Empleadon ……. Comision n
|
||||
|
||||
Total Comisiones en el Departamento NombreDepartamento: SumaComisiones
|
||||
|
||||
Departamento: NombreDepartamento
|
||||
|
||||
Empleado1 ……. Comisión 1
|
||||
Empleado2 ……. Comisión 2
|
||||
.
|
||||
.
|
||||
.
|
||||
Empleadon ……. Comision n
|
||||
|
||||
Total Comisiones en el Departamento NombreDepartamento: SumaComisiones
|
||||
.
|
||||
.
|
||||
Total Comisiones en la Localidad NombreLocalidad: SumaComisionesLocalidad
|
||||
|
||||
Localidad NombreLocalidad
|
||||
.
|
||||
.
|
||||
|
||||
Total Comisiones en la Empresa: TotalComisiones
|
||||
```
|
||||
|
||||
Nota: Los nombres de localidades, departamentos y empleados deben aparecer por orden alfabético.
|
||||
|
||||
Si alguno de los departamentos no tiene ningún empleado con comisiones, aparecerá un mensaje informando de ello en lugar de la lista de empleados.
|
||||
|
||||
El procedimiento debe gestionar adecuadamente las siguientes excepciones:
|
||||
|
||||
a) La tabla Empleados está vacía.
|
||||
b) Alguna comisión es mayor que 10000.
|
||||
|
||||
He creado dos funciones y un procedimiento:
|
||||
|
||||
```sql
|
||||
CREATE OR REPLACE FUNCTION listar_empleados(p_deptno dept.deptno%type)
|
||||
return number
|
||||
is
|
||||
cursor c_empleados is
|
||||
SELECT ename,comm
|
||||
from emp
|
||||
where deptno=p_deptno
|
||||
order by ename;
|
||||
v_vacio number;
|
||||
v_suma number:=0;
|
||||
v_valor number;
|
||||
begin
|
||||
select sum(comm) into v_vacio from emp where deptno=p_deptno;
|
||||
if v_vacio>0 then
|
||||
for v_empleado in c_empleados loop
|
||||
IF v_empleado.comm is NULL THEN
|
||||
v_valor:=0;
|
||||
ELSE
|
||||
v_suma:=v_suma+v_empleado.comm;
|
||||
v_valor:=v_empleado.comm;
|
||||
END IF;
|
||||
dbms_output.put_line(CHR(9)||CHR(9)|| v_empleado.ename || ' ... ' || v_valor);
|
||||
end loop;
|
||||
else
|
||||
dbms_output.put_line(CHR(9)||CHR(9)|| 'El departamento no tiene comisiones');
|
||||
end if;
|
||||
return v_suma;
|
||||
EXCEPTION
|
||||
WHEN NO_DATA_FOUND then
|
||||
dbms_output.put_line('La tabla empleados está vacía');
|
||||
return 0;
|
||||
end;
|
||||
/
|
||||
|
||||
CREATE OR REPLACE FUNCTION listar_departamentos(p_loc dept.loc%type)
|
||||
return number
|
||||
is
|
||||
cursor c_departamentos is
|
||||
SELECT dname,deptno
|
||||
from dept
|
||||
where loc=p_loc
|
||||
order by dname;
|
||||
v_total number;
|
||||
v_suma number:=0;
|
||||
begin
|
||||
for v_departamento in c_departamentos loop
|
||||
dbms_output.put_line(CHR(9)|| 'Departamento: ' || v_departamento.dname);
|
||||
v_total:=listar_empleados(v_departamento.deptno);
|
||||
dbms_output.put_line(CHR(9)|| 'Total Comisiones en el Departamento ' || v_departamento.dname || ': ' || v_total);
|
||||
v_suma:=v_suma+v_total;
|
||||
end loop;
|
||||
return v_suma;
|
||||
end;
|
||||
/
|
||||
|
||||
CREATE OR REPLACE PROCEDURE listar_comisiones
|
||||
is
|
||||
cursor c_localidades is
|
||||
SELECT loc
|
||||
from dept
|
||||
order by loc;
|
||||
v_total number;
|
||||
v_suma number:=0;
|
||||
begin
|
||||
for v_localidad in c_localidades loop
|
||||
dbms_output.put_line('Localidad ' || v_localidad.loc);
|
||||
v_total:=listar_departamentos(v_localidad.loc);
|
||||
dbms_output.put_line('Total Comisiones en la Localidad ' || v_localidad.loc || ': ' || v_total);
|
||||
v_suma:=v_suma+v_total;
|
||||
end loop;
|
||||
dbms_output.put_line('Total Comisiones de la Empresa ' || v_suma);
|
||||
end;
|
||||
/
|
||||
```
|
||||
|
||||
![p9](https://i.imgur.com/DGWQS1b.png)
|
||||
|
||||
## . Realiza un procedimiento que reciba el nombre de una tabla y muestre los nombres de las restricciones que tiene, a qué columna afectan y en qué consisten exactamente. (DBA_TABLES, DBA_CONSTRAINTS, DBA_CONS_COLUMNS)
|
||||
|
||||
He realizado los siguientes procedimientos:
|
||||
|
||||
```sql
|
||||
CREATE OR REPLACE PROCEDURE listar_restriccion(p_nombre user_constraints.table_name%type,p_tabla user_constraints.table_name%type)
|
||||
is
|
||||
v_tipo user_constraints.constraint_type%type;
|
||||
v_nombre user_constraints.constraint_name%type;
|
||||
v_referencia user_constraints.r_constraint_name%type;
|
||||
v_condicion user_constraints.search_condition%type;
|
||||
begin
|
||||
select constraint_name,constraint_type,r_constraint_name,search_condition into v_nombre,v_tipo,v_referencia,v_condicion
|
||||
from user_constraints
|
||||
where table_name = p_tabla
|
||||
and constraint_name=p_nombre;
|
||||
if v_tipo='P' then
|
||||
dbms_output.put_line(p_nombre || ' ... es de tipo CLAVE PRIMARIA');
|
||||
elsif v_tipo='R' then
|
||||
dbms_output.put_line(p_nombre || ' ... es de tipo CLAVE EXTERNA y hace referencia a: ' || v_nombre);
|
||||
elsif v_tipo='C' then
|
||||
dbms_output.put_line(p_nombre || ' ... es de tipo CHECK y contiene la siguiente comprobacion: ' || v_condicion);
|
||||
end if;
|
||||
end;
|
||||
/
|
||||
|
||||
CREATE OR REPLACE PROCEDURE listar_restricciones(p_tabla user_constraints.table_name%type)
|
||||
is
|
||||
cursor c_columnas is
|
||||
SELECT constraint_name,column_name
|
||||
from user_cons_columns
|
||||
where table_name=p_tabla;
|
||||
begin
|
||||
dbms_output.put_line('Restricciones de la tabla ' || p_tabla);
|
||||
for v_columna in c_columnas loop
|
||||
listar_restriccion(v_columna.constraint_name,p_tabla);
|
||||
dbms_output.put_line(CHR(9)||'Hace referencia a la columna -> ' || v_columna.column_name);
|
||||
end loop;
|
||||
end;
|
||||
/
|
||||
```
|
||||
|
||||
En la comprobación introduzco una tabla diferente al esquema SCOTT ya que tiene más restricciones:
|
||||
|
||||
![p10](https://i.imgur.com/OMoSRQz.png)
|
||||
|
||||
## Realiza al menos dos de los ejercicios anteriores en Postgres usando PL/pgSQL.
|
||||
|
||||
## Ejercicio 1
|
||||
|
||||
```sql
|
||||
CREATE or replace PROCEDURE mostrarnombresalario() AS $$
|
||||
DECLARE
|
||||
v_nombre emp.ename%type;
|
||||
v_salario emp.sal%type;
|
||||
BEGIN
|
||||
select ename,sal into v_nombre,v_salario from emp where empno=7782;
|
||||
RAISE NOTICE 'El nombre del empleado es %, y su salario es %', v_nombre,v_salario;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
```
|
||||
|
||||
![p11](https://i.imgur.com/GifaOGt.png)
|
||||
|
||||
## Ejercicio 2
|
||||
|
||||
```sql
|
||||
CREATE or replace PROCEDURE mostrarnombresalario2(p_empno emp.empno%type) AS $$
|
||||
DECLARE
|
||||
v_nombre emp.ename%type;
|
||||
BEGIN
|
||||
select ename into v_nombre from emp where empno=7782;
|
||||
RAISE NOTICE 'El nombre del empleado cuyo codigo es %, es %', p_empno,v_nombre;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
```
|
||||
|
||||
![p12](https://i.imgur.com/OKfLC2X.png)
|
After Width: | Height: | Size: 198 KiB |
@ -0,0 +1,122 @@
|
||||
---
|
||||
title: "Montaje NFS mediante systemd"
|
||||
date: 2022-12-15T13:24:40+01:00
|
||||
draft: false
|
||||
image: featured.png
|
||||
categories:
|
||||
- documentación
|
||||
- Administración de Sistemas Operativos
|
||||
tags:
|
||||
- NFS
|
||||
- Openstack
|
||||
- Debian
|
||||
---
|
||||
|
||||
En una instancia del cloud, basada en la distribución de tu elección, anexa un volumen de 2GB. En dicha instancia deberás configurar el servicio nfs de exportación y en el volumen un punto de montaje de la exportación mediante systemd.
|
||||
|
||||
|
||||
|
||||
### Escenario
|
||||
|
||||
El escenario se compone de dos máquinas, alfa, con debian 11 y que será el servidor nfs; y bravo, con rocky linux 8 y que será el cliente nfs.
|
||||
|
||||
## Servidor NFS
|
||||
|
||||
Instalamos los paquetes necesarios para el servicio nfs:
|
||||
|
||||
```bash
|
||||
apt install nfs-kernel-server nfs-common
|
||||
```
|
||||
|
||||
Creamos el fichero `/etc/systemd/system/mnt-carpeta.mount` con el siguiente contenido. El nombre del fichero, tiene que ser el mismo que el del punto de montaje en el que vamos a montar el dispositivo, además de sustituyendo las "/" por "-" (menos la primera):
|
||||
|
||||
```bash
|
||||
[Unit]
|
||||
Description=Montaje de disco para compartir
|
||||
|
||||
[Mount]
|
||||
What= /dev/vdb
|
||||
Where= /mnt/carpeta/
|
||||
Type=ext4
|
||||
Options=defaults
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
|
||||
Activamos el servicio:
|
||||
|
||||
```bash
|
||||
systemctl enable mnt-carpeta.mount
|
||||
systemctl start mnt-carpeta.mount
|
||||
```
|
||||
|
||||
|
||||
Si no funciona el montaje de la unidad, podemos comprobar os errores con `journalctl -xe`
|
||||
|
||||
Tras el montaje podemos comprobar que el disco se ha montado correctamente:
|
||||
|
||||
![Montaje de disco](https://i.imgur.com/8cUkODO.png)
|
||||
|
||||
Finalmente, añadimos la siguiente línea al fichero `/etc/exports`:
|
||||
|
||||
```bash
|
||||
/mnt/carpeta 172.16.0.0/16(rw,no_all_squash,no_subtree_check)
|
||||
```
|
||||
|
||||
Y reiniciamos el servicio:
|
||||
|
||||
```bash
|
||||
systemctl restart nfs-server
|
||||
```
|
||||
|
||||
|
||||
## Cliente NFS
|
||||
|
||||
Instalamos los paquetes necesarios para el servicio nfs:
|
||||
|
||||
```bash
|
||||
dnf install nfs-utils
|
||||
```
|
||||
|
||||
Podemos ver los dispositivos de bloques que se están compartiendo por nfs (la ip del servidor nfs es `172.16.0.1`):
|
||||
|
||||
```bash
|
||||
showmount -e 172.16.0.1
|
||||
```
|
||||
|
||||
![Dispositivos compartidos](https://i.imgur.com/oaYEhYA.png)
|
||||
|
||||
Creamos el fichero `/etc/systemd/system/mnt-carpetaNFS.mount` con el siguiente contenido:
|
||||
|
||||
```bash
|
||||
[Unit]
|
||||
Description=Montaje del disco compartido por red usando NFS
|
||||
|
||||
[Mount]
|
||||
What=172.16.0.1:/mnt/carpeta
|
||||
Where=/mnt/carpetaNFS
|
||||
Type=nfs
|
||||
Options=defaults
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
|
||||
Activamos el servicio:
|
||||
|
||||
```bash
|
||||
systemctl enable mnt-carpetaNFS.mount
|
||||
systemctl start mnt-carpetaNFS.mount
|
||||
```
|
||||
|
||||
Podemos comprobar que el disco se ha montado correctamente:
|
||||
|
||||
![Montaje de disco 2](https://i.imgur.com/l4fEpSh.png)
|
||||
|
||||
## Comprobación
|
||||
|
||||
Comprobamos que el dispositivo de bloques se está compartiendo por nfs:
|
||||
|
||||
![Comprobación](https://i.imgur.com/16NCruU.png)
|
||||
|
After Width: | Height: | Size: 118 KiB |
@ -0,0 +1,213 @@
|
||||
---
|
||||
title: "Escenario Dns"
|
||||
date: 2022-12-19T14:01:03+01:00
|
||||
draft: false
|
||||
image: featured.png
|
||||
categories:
|
||||
- práctica
|
||||
- Servicios de Red e Internet
|
||||
tags:
|
||||
- DNS
|
||||
- Openstack
|
||||
- bind9
|
||||
---
|
||||
|
||||
El enunciado de la prácica se encuentra en el siguiente [enlace](https://fp.josedomingo.org/sri2223/5_dns/practica.html)
|
||||
|
||||
## 1. Configuración DNS de cada máquina
|
||||
|
||||
Para no tocar la configuración de los servidores DHCP de **OpenStack**, cambiamos manualmente la configuración de las máquinas **Alfa, Bravo y Delta** para que tengan como servidor DNS el servidor **bind9** en **Charlie**, así como el dns del centro (Babuino). Para ello, editamos el fichero `/etc/resolv.conf` y añadimos las siguientes líneas:
|
||||
|
||||
```bash
|
||||
nameserver 192.168.0.2
|
||||
nameserver 192.168.202.2
|
||||
```
|
||||
|
||||
Para hacer los cambios persistentes en debian/ubuntu, instalamos el paquete `resolvconf`y añadimos los dns al final del fichero `/etc/resolvconf/resolv.conf.d/head`. Para aplicar los cambios sin tener que reiniciar tenemos que ejecutar el comando `resolvconf -u`.
|
||||
|
||||
#### VISTAS
|
||||
|
||||
```bash
|
||||
view interna {
|
||||
match-clients { 192.168.0.0/24; 127.0.0.1; };
|
||||
allow-recursion { any; };
|
||||
zone "roberto.gonzalonazareno.org"
|
||||
{
|
||||
type master;
|
||||
file "db.interna.roberto.gonzalonazareno.org";
|
||||
};
|
||||
zone "0.168.192.in-addr.arpa"
|
||||
{
|
||||
type master;
|
||||
file "db.0.168.192";
|
||||
};
|
||||
zone "16.172.in-addr.arpa"
|
||||
{
|
||||
type master;
|
||||
file "db.0.16.172";
|
||||
};
|
||||
include "/etc/bind/zones.rfc1918";
|
||||
include "/etc/bind/named.conf.default-zones";
|
||||
};
|
||||
|
||||
view dmz {
|
||||
match-clients { 172.16.0/16;};
|
||||
allow-recursion { any; };
|
||||
zone "roberto.gonzalonazareno.org"
|
||||
{
|
||||
type master;
|
||||
file "db.dmz.roberto.gonzalonazareno.org";
|
||||
};
|
||||
zone "16.172.in-addr.arpa"
|
||||
{
|
||||
type master;
|
||||
file "db.16.172";
|
||||
};
|
||||
include "/etc/bind/zones.rfc1918";
|
||||
include "/etc/bind/named.conf.default-zones";
|
||||
};
|
||||
|
||||
view externa {
|
||||
match-clients { 172.22.0.0/16; 172.29.0.0/16; 192.168.202.2; };
|
||||
allow-recursion { any; };
|
||||
zone "roberto.gonzalonazareno.org"
|
||||
{
|
||||
type master;
|
||||
file "db.externa.roberto.gonzalonazareno.org";
|
||||
};
|
||||
include "/etc/bind/zones.rfc1918";
|
||||
include "/etc/bind/named.conf.default-zones";
|
||||
};
|
||||
```
|
||||
|
||||
## Definición de las zonas
|
||||
|
||||
### INTERNA /var/cache/bind/db.interna.roberto.gonzalonazareno.org
|
||||
|
||||
```bash
|
||||
$TTL 86400
|
||||
@ IN SOA charlie.roberto.gonzalonazareno.org. root.roberto.gonzalonazareno.org. (
|
||||
1 ; Serial
|
||||
604800 ; Refresh
|
||||
86400 ; Retry
|
||||
2419200 ; Expire
|
||||
86400 ) ; Negative Cache TTL
|
||||
;
|
||||
@ IN NS charlie.roberto.gonzalonazareno.org.
|
||||
@ IN MX 10 mail.roberto.gonzalonazareno.org.
|
||||
|
||||
$ORIGIN roberto.gonzalonazareno.org.
|
||||
|
||||
alfa IN A 192.168.0.1
|
||||
bravo IN A 172.16.0.200
|
||||
charlie IN A 192.168.0.2
|
||||
delta IN A 192.168.0.3
|
||||
www IN CNAME bravo
|
||||
bd IN CNAME delta
|
||||
```
|
||||
|
||||
|
||||
### INTERNA INVERSA /var/cache/bind/db.0.168.192
|
||||
|
||||
```bash
|
||||
$TTL 86400
|
||||
@ IN SOA charlie.roberto.gonzalonazareno.org. root.roberto.gonzalonazareno.org. (
|
||||
1 ; Serial
|
||||
604800 ; Refresh
|
||||
86400 ; Retry
|
||||
2419200 ; Expire
|
||||
86400 ) ; Negative Cache TTL
|
||||
;
|
||||
@ IN NS charlie.roberto.gonzalonazareno.org.
|
||||
|
||||
$ORIGIN 0.168.192.in-addr.arpa.
|
||||
|
||||
1 IN PTR alfa.roberto.gonzalonazareno.org.
|
||||
2 IN PTR charlie.roberto.gonzalonazareno.org.
|
||||
3 IN PTR delta.roberto.gonzalonazareno.org.
|
||||
```
|
||||
|
||||
### INTERNA INVERSA /var/cache/bind/db.16.172
|
||||
|
||||
```bash
|
||||
$TTL 86400
|
||||
@ IN SOA charlie.roberto.gonzalonazareno.org. root.roberto.gonzalonazareno.org. (
|
||||
1 ; Serial
|
||||
604800 ; Refresh
|
||||
86400 ; Retry
|
||||
2419200 ; Expire
|
||||
86400 ) ; Negative Cache TTL
|
||||
;
|
||||
@ IN NS charlie.roberto.gonzalonazareno.org.
|
||||
|
||||
$ORIGIN 16.172.in-addr.arpa.
|
||||
|
||||
1.0 IN PTR alfa.roberto.gonzalonazareno.org.
|
||||
200.0 IN PTR bravo.roberto.gonzalonazareno.org.
|
||||
```
|
||||
|
||||
### DMZ /var/cache/bind/db.dmz.roberto.gonzalonazareno.org
|
||||
|
||||
```bash
|
||||
$TTL 86400
|
||||
@ IN SOA charlie.roberto.gonzalonazareno.org. root.roberto.gonzalonazareno.org. (
|
||||
1 ; Serial
|
||||
604800 ; Refresh
|
||||
86400 ; Retry
|
||||
2419200 ; Expire
|
||||
86400 ) ; Negative Cache TTL
|
||||
;
|
||||
@ IN NS charlie.roberto.gonzalonazareno.org.
|
||||
|
||||
$ORIGIN roberto.gonzalonazareno.org.
|
||||
|
||||
alfa IN A 172.16.0.1
|
||||
bravo IN A 172.16.0.200
|
||||
charlie IN A 192.168.0.2
|
||||
delta IN A 192.168.0.3
|
||||
www IN CNAME bravo
|
||||
bd IN CNAME delta
|
||||
```
|
||||
|
||||
### EXTERNA /var/cache/bind/db.externa.roberto.gonzalonazareno.org
|
||||
|
||||
```bash
|
||||
$TTL 86400
|
||||
@ IN SOA alfa.roberto.gonzalonazareno.org. root.roberto.gonzalonazareno.org. (
|
||||
1 ; Serial
|
||||
604800 ; Refresh
|
||||
86400 ; Retry
|
||||
2419200 ; Expire
|
||||
86400 ) ; Negative Cache TTL
|
||||
;
|
||||
@ IN NS alfa.roberto.gonzalonazareno.org.
|
||||
|
||||
$ORIGIN roberto.gonzalonazareno.org.
|
||||
|
||||
alfa IN A 172.22.200.218
|
||||
www IN CNAME alfa
|
||||
```
|
||||
|
||||
|
||||
## Configuración de los servidores web
|
||||
|
||||
```bash
|
||||
<VirtualHost *:80>
|
||||
ServerName www.roberto.gonzalonazareno.org
|
||||
|
||||
ServerAdmin webmaster@localhost
|
||||
|
||||
DocumentRoot /var/www/html
|
||||
|
||||
ErrorLog ${APACHE_LOG_DIR}/error.log
|
||||
CustomLog ${APACHE_LOG_DIR}/access.log combined
|
||||
|
||||
<FilesMatch "\.php$">
|
||||
SetHandler "proxy:unix:/run/php/php7.4-fpm.sock|fcgi://127.0.0.1/"
|
||||
SetHandler "proxy:fcgi://127.0.0.1:9000"
|
||||
</FilesMatch>
|
||||
|
||||
</VirtualHost>
|
||||
|
||||
|
||||
```
|
After Width: | Height: | Size: 168 KiB |
@ -0,0 +1,177 @@
|
||||
---
|
||||
title: "Resolución de problemas de
|
||||
tablas mutantes"
|
||||
date: 2022-12-19T00:51:41+01:00
|
||||
draft: false
|
||||
image: featured.png
|
||||
categories:
|
||||
- documentación
|
||||
- Administración de Bases de Datos
|
||||
tags:
|
||||
- tablas mutantes
|
||||
- Oracle
|
||||
- PL/SQL
|
||||
---
|
||||
|
||||
El enunciado a resolver y que contiene una tabla mutante es el siguiente:
|
||||
|
||||
**6 - Realiza los módulos de programación necesarios para evitar que un catador puntue más de tres aspectos de una misma versión de un experimento.**
|
||||
|
||||
En este caso, el trigger principal sería sobre la tabla puntuaciones, y dentro, para comprobar que se cumple la condición de que un catador no puntúa más de 3 aspectos, se tendría que hacer una consulta a la misma tabla puntuaciones, que en ese caso estaría mutando. Para resolver el problema vamos a realizar los siguientes pasos:
|
||||
|
||||
1. Leer bien los requisitos del problema e identificar la
|
||||
información de la tabla que debo guardar en variables
|
||||
persistentes.
|
||||
2. Crear el paquete declarando los tipos de datos y las variables
|
||||
necesarias para guardar dicha información.
|
||||
3. Hacer un trigger before por sentencia que rellene dichas
|
||||
variables consultando la tabla mutante.
|
||||
4. Hacer un trigger before por fila que compruebe si el registro
|
||||
que se está manejando cumple la condición especificada
|
||||
consultando las variables persistentes.
|
||||
|
||||
## Leer bien los requisitos del problema e identificar la información de la tabla que debo guardar en variables persistentes
|
||||
|
||||
El contenido de la tabla de puntuaciones es el siguiente:
|
||||
|
||||
![Tabla puntuaciones](https://i.imgur.com/wMxNzMj.png)
|
||||
|
||||
En este caso, tendríamos que almacenar en variables persistentes los datos de la consulta, que en este caso son los siguientes campos:
|
||||
|
||||
* NIFCatador
|
||||
* CodigoAspecto
|
||||
* CodigoExperimento
|
||||
* CodigoVersion
|
||||
|
||||
## Crear el paquete declarando los tipos de datos y las variables necesarias para guardar dicha información
|
||||
|
||||
```sql
|
||||
CREATE OR REPLACE PACKAGE ControlPuntuaciones
|
||||
AS
|
||||
TYPE tRegistroTablaPuntuaciones IS RECORD --defino el tipo de datos registro
|
||||
(
|
||||
NIFCatador Puntuaciones.NIFCatador%TYPE,
|
||||
CodigoAspecto Puntuaciones.CodigoAspecto%TYPE,
|
||||
CodigoExperimento Puntuaciones.CodigoExperimento%TYPE,
|
||||
CodigoVersion Puntuaciones.CodigoVersion%TYPE
|
||||
);
|
||||
|
||||
TYPE tTablasPuntuaciones IS TABLE OF tRegistroTablaPuntuaciones -- defino el tipo de datos tabla
|
||||
INDEX BY BINARY_INTEGER;
|
||||
PuntuacionesCatador tTablasPuntuaciones;
|
||||
-- declaro una variable del tipo tabla antes creado
|
||||
END ControlPuntuaciones;
|
||||
/
|
||||
```
|
||||
|
||||
## Hacer un trigger before por sentencia que rellene dichas variables consultando la tabla mutante
|
||||
|
||||
```sql
|
||||
CREATE OR REPLACE TRIGGER RELLENARPUNTUACIONES
|
||||
BEFORE INSERT OR UPDATE ON Puntuaciones
|
||||
FOR EACH ROW
|
||||
DECLARE
|
||||
CURSOR c_puntuaciones IS SELECT NIFCatador,CodigoAspecto,CodigoExperimento,CodigoVersion
|
||||
FROM Puntuaciones;
|
||||
INDICE NUMBER:=0;
|
||||
indice_u number;
|
||||
BEGIN
|
||||
|
||||
-- vacio el contenido de la tabla
|
||||
ControlPuntuaciones.PuntuacionesCatador.DELETE;
|
||||
-- relleno la tabla de puntuaciones los datos que me interesan
|
||||
FOR v_puntuacion IN c_puntuaciones LOOP
|
||||
ControlPuntuaciones.PuntuacionesCatador(INDICE).NIFCatador := v_puntuacion.NIFCatador;
|
||||
ControlPuntuaciones.PuntuacionesCatador(INDICE).CodigoAspecto := v_puntuacion.CodigoAspecto;
|
||||
ControlPuntuaciones.PuntuacionesCatador(INDICE).CodigoExperimento := v_puntuacion.CodigoExperimento;
|
||||
ControlPuntuaciones.PuntuacionesCatador(INDICE).CodigoVersion := v_puntuacion.CodigoVersion;
|
||||
INDICE := INDICE + 1;
|
||||
END LOOP;
|
||||
if inserting then
|
||||
indice_u := ControlPuntuaciones.PuntuacionesCatador.LAST + 1;
|
||||
ControlPuntuaciones.PuntuacionesCatador(indice_u).NIFCatador := :NEW.NIFCatador;
|
||||
ControlPuntuaciones.PuntuacionesCatador(indice_u).CodigoAspecto := :NEW.CodigoAspecto;
|
||||
ControlPuntuaciones.PuntuacionesCatador(indice_u).CodigoExperimento := :NEW.CodigoExperimento;
|
||||
ControlPuntuaciones.PuntuacionesCatador(indice_u).CodigoVersion := :NEW.CodigoVersion;
|
||||
end if;
|
||||
|
||||
END RELLENARPUNTUACIONES;
|
||||
/
|
||||
```
|
||||
|
||||
## Hacer un trigger before por fila que compruebe si el registro que se está manejando cumple la condición especificada consultando las variables persistentes
|
||||
|
||||
```sql
|
||||
CREATE OR REPLACE TRIGGER ControlarPuntuaciones
|
||||
BEFORE INSERT OR UPDATE ON Puntuaciones
|
||||
FOR EACH ROW
|
||||
DECLARE
|
||||
BEGIN
|
||||
-- compruebo que el catador no haya puntuado más de 3 aspectos
|
||||
IF (NumeroPuntuacionesCatador(:NEW.NIFCatador,:NEW.CodigoExperimento,:NEW.CodigoVersion) > 3) THEN
|
||||
RAISE_APPLICATION_ERROR(-20001,'El catador no puede puntuar mas de 3 aspectos');
|
||||
end if;
|
||||
END;
|
||||
/
|
||||
```
|
||||
|
||||
Voy a crear una funcion para comprobar el numero de puntuaciones que tiene un catador en una versión de un experimento:
|
||||
|
||||
```sql
|
||||
CREATE OR REPLACE FUNCTION NumeroPuntuacionesCatador
|
||||
( p_NIFCatador Puntuaciones.NIFCatador%TYPE, p_CodigoExperimento Puntuaciones.CodigoExperimento%TYPE, p_CodigoVersion Puntuaciones.CodigoVersion%TYPE)
|
||||
RETURN NUMBER
|
||||
IS
|
||||
v_NumeroPuntuaciones NUMBER:= 1;
|
||||
v_cantidad NUMBER;
|
||||
BEGIN
|
||||
for i in ControlPuntuaciones.PuntuacionesCatador.FIRST..ControlPuntuaciones.PuntuacionesCatador.LAST
|
||||
LOOP
|
||||
if (ControlPuntuaciones.PuntuacionesCatador(i).NIFCatador = p_NIFCatador) and (ControlPuntuaciones.PuntuacionesCatador(i).CodigoExperimento = p_CodigoExperimento) and (ControlPuntuaciones.PuntuacionesCatador(i).CodigoVersion = p_CodigoVersion) then
|
||||
v_NumeroPuntuaciones := v_NumeroPuntuaciones + 1;
|
||||
end if;
|
||||
END LOOP;
|
||||
return v_NumeroPuntuaciones;
|
||||
end;
|
||||
/
|
||||
|
||||
--- prueba
|
||||
|
||||
create or replace procedure prueba
|
||||
is
|
||||
numero number;
|
||||
begin
|
||||
numero:=NumeroPuntuacionesCatador('14425879A','A0003-A','0.0.2');
|
||||
dbms_output.put_line(numero);
|
||||
end;
|
||||
/
|
||||
insert into puntuaciones values('14425879A','0004','A0003-A','0.0.2',7.5);
|
||||
|
||||
|
||||
create or replace procedure imprimirtabla
|
||||
is
|
||||
begin
|
||||
for i in ControlPuntuaciones.PuntuacionesCatador.FIRST..ControlPuntuaciones.PuntuacionesCatador.LAST
|
||||
LOOP
|
||||
dbms_output.put_line('Registro numero '|| i);
|
||||
dbms_output.put_line('NIFCatador: '|| ControlPuntuaciones.PuntuacionesCatador(i).NIFCatador);
|
||||
dbms_output.put_line('CodigoAspecto: '|| ControlPuntuaciones.PuntuacionesCatador(i).CodigoAspecto);
|
||||
dbms_output.put_line('CodigoExperimento: '|| ControlPuntuaciones.PuntuacionesCatador(i).CodigoExperimento);
|
||||
dbms_output.put_line('CodigoVersion: '|| ControlPuntuaciones.PuntuacionesCatador(i).CodigoVersion);
|
||||
|
||||
|
||||
end loop;
|
||||
end;
|
||||
/
|
||||
```
|
||||
|
||||
|
||||
|
||||
```sql
|
||||
insert into puntuaciones values('14425879A','0004','A0003-A','0.0.2',7.5);
|
||||
insert into puntuaciones values('14425879A','0005','A0003-A','0.0.2',7.5);
|
||||
insert into puntuaciones values('14425879A','0006','A0003-A','0.0.2',7.5);
|
||||
insert into puntuaciones values('14425879A','0007','A0003-A','0.0.2',7.5);
|
||||
select * from puntuaciones where nifcatador='14425879A' and codigoexperimento='A0003-A' and codigoversion='0.0.2';
|
||||
insert into puntuaciones values('14425879A','0005','A0003-A','0.0.1',7.5);
|
||||
```
|
Before Width: | Height: | Size: 304 KiB After Width: | Height: | Size: 304 KiB |
Before Width: | Height: | Size: 233 KiB After Width: | Height: | Size: 233 KiB |
Before Width: | Height: | Size: 53 KiB After Width: | Height: | Size: 53 KiB |
Before Width: | Height: | Size: 257 KiB After Width: | Height: | Size: 257 KiB |
Before Width: | Height: | Size: 166 KiB After Width: | Height: | Size: 166 KiB |
Before Width: | Height: | Size: 125 KiB After Width: | Height: | Size: 125 KiB |
Before Width: | Height: | Size: 516 KiB After Width: | Height: | Size: 516 KiB |
Before Width: | Height: | Size: 109 KiB After Width: | Height: | Size: 109 KiB |
Before Width: | Height: | Size: 546 KiB After Width: | Height: | Size: 546 KiB |
Before Width: | Height: | Size: 407 KiB After Width: | Height: | Size: 407 KiB |
Before Width: | Height: | Size: 459 KiB After Width: | Height: | Size: 459 KiB |
Before Width: | Height: | Size: 273 KiB After Width: | Height: | Size: 273 KiB |
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 40 KiB |