Está en la página 1de 11

BASE DE DATOS TAREA 6

PILAR ALONSO SUELA 1º DAMEL


Una empresa de telefonía tiene sus centros de llamadas distribuidos por la geografía
española en diferentes oficinas. Estas oficinas están jerarquizadas en familias de agentes
telefónicos. Cada familia, por tanto, podrá contener agentes u otras familias. Los agentes
telefónicos, según su categoría, además se encargarán de supervisar el trabajo de todos los
agentes de una oficina o de coordinar el trabajo de los agentes de una familia dada. El único
agente que pertenecerá directamente a una oficina y que no formará parte de ninguna
familia será el supervisor de dicha oficina, cuya categoría es la 2. Los coordinadores de las
familias deben pertenecer a dicha familia y su categoría será 1 (no todas las familias tienen
por qué tener un coordinador y dependerá del tamaño de la oficina, ya que de ese trabajo
también se puede encargar el supervisor de la oficina). Los demás agentes deberán
pertenecer a una familia, su categoría será 0 y serán los que principalmente se ocupen de
atender las llamadas.

De los agentes queremos conocer su nombre, su clave y contraseña para entrar al sistema,
su categoría y su habilidad que será un número entre 0 y 9 indicando su habilidad para
atender llamadas.

Para las familias sólo nos interesa conocer su nombre.

Finalmente, para las oficinas queremos saber su nombre, domicilio, localidad y código postal
de la misma.

Crear un procedimiento que permita cambiar a todos los agentes de una familia
determinada (familia origen) a otra familia (familia destino).
El procedimiento tendrá la siguiente cabecera CambiarAgentesFamilia( id_FamiliaOrigen,
id_FamiliaDestino), donde cada uno de los argumentos corresponde a un identificador de
Familia. Cambiará la columna Identificador de Familia de todos los agentes, de la tabla
AGENTES, que pertenecen a la Familia con código id_FamiliaOrigen por el código
id_FamiliaDestino

Previamente comprobará que ambas familias existen y que no son iguales.

Para la comprobación de la existencia de las familias se puede utilizar un cursor variable, o


contar el número de filas y en caso de que no exista, se visualizará el mensaje
correspondiente mediante una excepción del tipo RAISE_APPLICATION_ERROR. También se
mostrará un mensaje en caso de que ambos argumentos tengan el mismo valor.

El procedimiento visualizará el mensaje "Se han trasladado XXX agentes de la familia


XXXXXX a la familia ZZZZZZ" donde XXX es el número de agentes que se han cambiado de
familia, XXXXXX es el nombre de la familia origen y ZZZZZZ es el nombre de la familia
destino.

Primero voy a crear las tablas e insertar los datos del anexo I.

CREATE OR REPLACE PROCEDURE cambiaragentesfamilia (

id_familiaorigen agentes.familia%TYPE,

id_familiadestino agentes.familia%TYPE

--tengo que cambiar el atributo familia de todos los agentes que tengan la familia que
indica el id_FamiliaOrigen por el id_FamiliaDestino

AS
--declarar las variables que voy a necesitar, la primera para comprobar que el id de la familia
existe y la segunda para guardar las filas contadas ademas de las excepciones

v_id_familiadestino agentes.familia%TYPE;

v_contarfilas NUMBER(3);

iguales EXCEPTION;

nohayagentes EXCEPTION;

BEGIN

--para ello lo primero que tengo que hacer es comprobar que en la base de datos hay
agentes que tengan ese id familiaOrigen para poder ser cambiados por la de destino

--para ello contaremos las filas del id familia de la tabla agentes que corresponda con el
id_FamiliaOrigen

--cuento a.familia y no uso * porque si uso * tambén cuenta valores nulos

SELECT

COUNT(a.familia)

INTO v_contarfilas

FROM

agentes a

WHERE

a.familia = id_familiaorigen;

--También necesito comprobar que existe el id_FamiliaOrigen por lo tanto haré un select

SELECT

f.identificador

INTO v_id_familiadestino

FROM

familias f

WHERE

f.identificador = id_familiadestino;

--si las filas contadas son 0 lanzamos una excepcion

IF ( v_contarfilas = 0 ) THEN

RAISE nohayagentes;

END IF;

--si la familia de destino no existe en la base de datos lanzamos una excepcion


IF ( v_id_familiadestino IS NULL ) THEN

RAISE no_data_found;

--si todo es correcto y el id origen y el id destino no coinciden

--actualizaremos la tabla agentes y le añadiremos el id_FamiliaDestino donde antes estaba el


id_FamiliaOrigen

--UPDATE nombre-de-la-tabla

ELSIF ( id_familiaorigen != id_familiadestino ) THEN

UPDATE agentes a

SET

a.familia = id_familiadestino;

ELSE

RAISE iguales;

END IF;

dbms_output.put_line(' Se han trasladado '

|| v_contarfilas

|| ' agentes de la familia '

|| id_familiaorigen

|| ' a la

familia '

|| v_id_familiadestino);

EXCEPTION

WHEN nohayagentes THEN

raise_application_error(-2001, 'no hay agentes con esa familia en la base de datos');

WHEN no_data_found THEN

dbms_output.put_line('No existe ninguna familia con el id ' || id_familiadestino);

WHEN iguales THEN

dbms_output.put_line('La familia origen y la familia de destino son la misma');

END;
He cambiado los de la familia 11 a la 21

Pero no funciona

Queremos controlar algunas restricciones a la hora de trabajar con agentes:

La longitud de la clave de un agente no puede ser inferior a 6.

La habilidad de un agente debe estar comprendida entre 0 y 9 (ambos inclusive).

La categoría de un agente sólo puede ser igual a 0, 1 o 2.


Si un agente tiene categoría 2 no puede pertenecer a ninguna familia y debe pertenecer a
una oficina.

Si un agente tiene categoría 1 no puede pertenecer a ninguna oficina y debe pertenecer a


una familia.

Todos los agentes deben pertenecer a una oficina o a una familia pero nunca a ambas a la
vez.

Se pide crear un disparador para asegurar estas restricciones. El disparador deberá lanzar
todos los errores que se puedan producir en su ejecución mediante errores que identifiquen
con un mensaje adecuado por qué se ha producido dicho error.

Algunas de las restricciones implementadas con el disparador se pueden incorporar a la


definición del esquema de la tabla utilizando el Lenguaje de Definición de Datos
(Check,Unique,..).Identifica cuáles son y con qué tipo de restricciones las implementarías.

Voy a poner una captura de pantalla de algunas excepciones predefinidas en PLSQL para elegir
la que más se corresponda con el error producido.

Al final no he usado ninguna de las predefinidas por que no se adaptaban al error que se
mandaba, por lo tanto he definido yo algunas y otras he utilizado RAISE_APPLICATION_ERROR.

CREATE OR REPLACE TRIGGER RESTRICCIONESAGENTES --CREO EL NOMBRE DEL TRIGGER

BEFORE INSERT OR UPDATE ON AGENTES FOR EACH ROW--ANTES DE INSERTAR O ACTUALIZAR


ALGÚN ELEMENTO DE LA TABLA AGENTES, FOR EACH ROW LO USAMOS PARA PODER USAR
:NEW Y :OLD

DECLARE

--he creado algunas excepciones propias

longitud_invalida EXCEPTION;

rango_invalido EXCEPTION;
longitudClave varchar2(6);

BEGIN

--La longitud de la clave de un agente no puede ser inferior a 6.

--la excepción será creada por mí ya que no encuentro una dentro de las excepciones
predefinidas

longitudclave:=to_char(:new.clave);

if(LENGTH(longitudclave)<6) then raise longitud_invalida;

end if;

--La habilidad de un agente debe estar comprendida entre 0 y 9 (ambos inclusive).

if(:new.habilidad <0 or :new.habilidad>9) then

raise rango_invalido;

end if;

--La categoría de un agente sólo puede ser igual a 0, 1 o 2.

if(:new.categoria <>0 or :new.categoria<>1 or :new.categoria<>2) then

RAISE_APPLICATION_ERROR(-20001, 'La categoria solo puede ser 0,1 o 2.');

end if;

--Si un agente tiene categoría 2 no puede pertenecer a ninguna familia y debe pertenecer a
una oficina.

if(:new.categoria=2 AND :new.familia is not null) then

RAISE_APPLICATION_ERROR(-20002, 'La familia de un agente con categoría 2 debe de ser


nula.');

elsif(:new.categoria=2 AND :new.oficina is null ) then

RAISE_APPLICATION_ERROR(-20003, 'La oficina de un agente con categoría 2 no debe de ser


nula.');

end if;

--Si un agente tiene categoría 1 no puede pertenecer a ninguna oficina y debe pertenecer a
una familia.

if(:new.categoria=1 and :new.oficina is not null) then

RAISE_APPLICATION_ERROR(-20004, 'La oficina de un agente con categoría 1 debe de ser


nula.');

elsif(:new.categoria=1 and :new.familia is null) then

RAISE_APPLICATION_ERROR(-20003, 'La familia de un agente con categoría 1 no debe de ser


nula.');

end if;
--Todos los agentes deben pertenecer a una oficina o a una familia pero nunca a ambas a la
vez.

if(:new.oficina is not null and :new.familia is not null) then

RAISE_APPLICATION_ERROR(-20004, 'Un agente puede tener una familia o una oficina pero no
ambas a la vez.');

end if;

--Se pide crear un disparador para asegurar estas restricciones. El disparador deberá lanzar
todos los errores que se puedan producir en su ejecución mediante errores que identifiquen
con un mensaje adecuado por qué se ha producido dicho error.

EXCEPTION

when longitud_invalida then

DBMS_OUTPUT.PUT_LINE('Clave errónea ,La longitud de la clave es menor a 6');

when rango_invalido then

DBMS_OUTPUT.PUT_LINE('la habilidad debe estar entre 0 y 9');

END;
La forma en la que se pueden manejar estas restricciones con sentencias DDL es:
La longitud de la clave de un agente no puede ser inferior a 6.

La habilidad de un agente debe estar comprendida entre 0 y 9 (ambos inclusive).

La categoría de un agente sólo puede ser igual a 0, 1 o 2.

Si un agente tiene categoría 2 no puede pertenecer a ninguna familia y debe pertenecer a una oficina.

Si un agente tiene categoría 1 no puede pertenecer a ninguna oficina y debe pertenecer a una familia.

Todos los agentes deben pertenecer a una oficina o a una familia pero nunca a ambas a la vez.

No se podrán manejar todas ellas, las únicas que he manejado con DDL son:
La habilidad de un agente debe estar comprendida entre 0 y 9 (ambos inclusive).

La categoría de un agente sólo puede ser igual a 0, 1 o 2.

create table agentes (


identificador number(6) not null primary key ,
nombre varchar2(60) not null,
usuario varchar2(20) not null unique,
clave varchar2(20) not null,
habilidad number(1) not null,
constraint CK_HABILIDAD CHECK(habilidad between 0 and 9),
categoria number(1) not null,
constraint CK_CATEGORIA CHECK(categoría IN(0,1,2)),
familia number(6) references familias,
oficina number(6) references oficinas
);

También podría gustarte