Disparadores y Funciones disparadoras (Trigger)

Un disparador ejecuta una función disparadora de forma automática cuando se produce un evento de mantenimineto de una tabla (operaciones INSERT - DELETE - UPDATE)

Se puede elegir ejecutar la función disparadora
Ejercicio 1:
Deseamos controlar los préstamos de una biblioteca de forma que cuando se intente poner una fecha de devolución anterior a la fecha de préstamo, se anote la incidencia en una tabla de errores:
Función disparadora verifica()

BEGIN
if(new.fecha_devolucion < old.fecha_prestamo) then
    INSERT INTO problemas
        VALUES (now(),'Problema: '|| old.cod_lector || old.cod_libro || old.fecha_prestamo || new.fecha_devolucion);

else
    DELETE FROM prestamos
        WHERE cod_lector=old.cod_lector
        AND cod_libro=old.cod_libro
        AND fecha_prestamo=old.fecha_prestamo;
    INSERT INTO prestamos VALUES (old.cod_lector,old.cod_libro,old.fecha_prestamo,new.fecha_devolucion);
end if;
return null;
end;

Nota: No se puede hacer UPDATE dentro de un disparador para UPDATE, ya que crearía una referencia circular infinita:
UPDATE -> regla -> UPDATE -> regla ->...

Disparador d1:
Ejercicio 2:
Deseamos que se controle la posibilidad de que se introduzcan datos de forma que se preste un libro ya prestado

Función disparadora: libro_prestado

DECLARE
    prestado int8;
BEGIN
    SELECT count(*) INTO prestado
    FROM prestamos
    WHERE cod_libro=new.cod_libro
    AND fecha_devolucion IS NULL;
    IF (prestado=2) THEN
        INSERT INTO problemas VALUES (now(),'Error prestando '||new.cod_libro||' a '||new.cod_lector);
        DELETE FROM prestamos WHERE cod_lector=new.cod_lector AND cod_libro=new.cod_libro AND fecha_prestamo=new.fecha_prestamo;
    END IF;
    return null;
END;

Disparador: control_prestamos
Funcionamiento
Inserta el nuevo prestamo
Controla mediante libro_prestado
    Si comprueba que esta prestado 2 veces
        inserta un error en la tabla problemas
        borra el prestamo realizado
    Si no estaba prestado
        deja todo como estaba

Ejercicio 3:
Crear una funcion disparadora que imposibilite los borrados:

Funcion disparadora: protege_borrado

DECLARE
BEGIN
    return null;
END

Disparador d3
Ejercicio 4:
Crear una función disparadora que permita tener datos calculados coherentes en una tabla matematicas (numero int PK, cuadrado int, cubo int, raiz real)

Funcion disparadora rellena_datos

DECLARE
BEGIN
    new.cuadrado=new.numero*new.numero;
    new.cubo=power(new.numero,3);
    new.raiz=sqrt(new.numero);
    return new;
END;

Nota: return new devuelve el registro. Como se hace antes (BEFORE), se entrega y se inserta o actualiza

Disparador d4
Cuando se inserte o modifique un numero, recalcula automaticamente el resto de los campos

Ejercicio 5:
Refundir las 2 funciones de los ejercicios 3 y 4 en una sola que controle la acción que pretende realizar el usuario:

DECLARE
BEGIN
    IF(TG_OP='INSERT' OR TG_OP='UPDATE') THEN
        new.cuadrado=new.numero*new.numero;
        ...
        RETURN new;
    ELSEIF (TG_OP='DELETE') THEN
        RETIR null;
    END IF;
END;

Disparador