CREATE EXCEPTION FALTA_FECHA
'Para poder ingresar una nueva asignación debe colocar una fecha final a la asignación anterior';
CREATE EXCEPTION FECHA_INCORRECTA
'La fecha que pretende utilizar ya se encuentra en otra asignación';
CREATE TABLE ASIGNACIONES (
ID_ASIGNACION INTEGER NOT NULL,
ID_ASESOR INTEGER NOT NULL,
FECHA_INICIO DATE NOT NULL,
FECHA_FIN DATE,
CONTADOR INTEGER,
PRIMARY KEY (ID_ASIGNACION),
CONSTRAINT FK_ASIGN_ASESOR FOREIGN KEY (ID_ASESOR)
REFERENCES ASESORES (ID_ASESOR) ON UPDATE CASCADE,
CONSTRAINT CK_FECHA_ASIGNACION_INCORRECTA
CHECK (FECHA_FIN >= FECHA_INICIO)
);
CREATE TRIGGER ASIGNACIONES_BI0 FOR ASIGNACIONES
ACTIVE BEFORE INSERT POSITION 0
AS
DECLARE VARIABLE VFIN DATE;
DECLARE VARIABLE VMAX_ID INTEGER;
DECLARE VARIABLE VMAX_CON INTEGER;
BEGIN
SELECT MAX(CONTADOR) /* Averiguo el número de la última asignación de un asesor*/
FROM ASIGNACIONES
WHERE ID_ASESOR = NEW.ID_ASESOR
INTO :VMAX_CON;
SELECT MAX(ID_ASIGNACION)/* Consigo la clave principal para luego pasarla como parámetro*/
FROM ASIGNACIONES
WHERE ID_ASESOR = NEW.ID_ASESOR
INTO :VMAX_ID;
IF (NOT VMAX_ID IS NULL) THEN /* Compruebo si dicho asesor tiene asignaciones,
puesto que si no las tiene no hay ninguna restricción */
BEGIN
NEW.CONTADOR = :VMAX_CON + 1; /*Incremento el valor del contador para el asesor en cuestión*/
SELECT FECHA_FIN
FROM ASIGNACIONES
WHERE ID_ASIGNACION = :VMAX_ID
INTO :VFIN;
IF (VFIN IS NULL) THEN /* Compruebo que el registro anterior tenga fecha final*/
EXCEPTION FALTA_FECHA; /*Aviso que falta fecha en registro anterior*/
ELSE
IF (NEW.FECHA_INICIO <= VFIN) THEN /* Finalmente comparo la fecha inicial del nuevo registro
contra la fecha final del registro anterior*/
EXCEPTION FECHA_INCORRECTA;
END
ELSE
NEW.CONTADOR = 1; /* Si dicho asesor no tiene asignaciones asignamos valor*/
END
^
CREATE TRIGGER ASIGNACIONES_BU0 FOR ASIGNACIONES
ACTIVE BEFORE UPDATE POSITION 0
AS
DECLARE VARIABLE VFIN DATE;
DECLARE VARIABLE VINI DATE;
DECLARE VARIABLE NUM INTEGER;
BEGIN
SELECT MAX(CONTADOR) /* Averiguo la cantidad de asignaciones de un asesor dado*/
FROM ASIGNACIONES
WHERE ID_ASESOR = NEW.ID_ASESOR
INTO :NUM;
IF (NUM <> 1) THEN /* Si solo tiene una asignación no tiene ninguna restricción */
BEGIN
SELECT FECHA_FIN FROM asignaciones /*Averiguo la fecha final de la asignación anterior de ese asesor*/
WHERE (ID_ASESOR = NEW.id_asesor) AND (CONTADOR = OLD.CONTADOR - 1)
INTO VFIN;
IF (NOT VFIN IS NULL) THEN
IF (NEW.fecha_inicio <= VFIN) THEN/*La comparo con la fecha de inicio del registro actual*/
EXCEPTION fecha_incorrecta;
SELECT FECHA_INICIO FROM ASIGNACIONES /*Averiguo la fecha inicial de la siguiente asignación de ese asesor*/
WHERE (ID_ASESOR = NEW.id_asesor) AND (CONTADOR =OLD.CONTADOR + 1)
INTO VINI;
IF (NOT VINI IS NULL) THEN
IF (NEW.fecha_FIN >= VINI) THEN/*La comparo con la fecha final del registro actual*/
EXCEPTION fecha_incorrecta;
END
END
^
CREATE OR ALTER TRIGGER ASIGNACIONES_BD0 FOR ASIGNACIONES
ACTIVE BEFORE DELETE POSITION 0
AS
BEGIN
UPDATE asignaciones SET contador = contador -1
WHERE ((contador >= OLD.contador) AND(ID_ASESOR = OLD.id_asesor));
/* Nos aseguramos que no queden huecos en el contador para quelos triggers */
/* BeforeInsert y BeforeUpdate funcionen correctamente*/
END
^