You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

6.6 KiB

title date draft image categories tags
Resolución de problemas de tablas mutantes 2022-12-19T00:51:41+01:00 false featured.png
documentación
Administración de Bases de Datos
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

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

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

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

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:

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;
/
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);