Programación E4G ( Examen de PL/SQL ) 24 de Enero de 2007 Nombre: Nombre: Usuario
Ejercicio 1 Desarrollar un procedimiento que permita insertar nuevos departamentos (tabla DEPART) según las siguientes especificaciones:
Se pasará al procedimiento el nombre del departamento (único) y la localidad.
El procedimiento insertará la fila nueva asignando como número de departamento la decena siguiente al número número mayor de la tabla.
Se incluirá la gestión de posibles errores, el nombre del departamento es único, alta del primer registro etc.
Ejercicio nº 2. Crear un procedimiento al que le pasaremos el importe de un trienio (euros) para que nos visualice una relación por departamento del importe que se les deberá pagar a los empleados de ese departamento en concepto de trienios. Al final nos deberá mostrar el importe total de todos los departamentos. ( Solo para los departamentos que tengan empleados) El cálculo de trienios se deberá obtener con una función tomando como fechas: la Fecha de Ingreso (FECHA_ALT) y la fecha actual (SYSDATE). SQL> execute imp_trienios (26); Depto: 10. Importe en concepto de trienios: Depto: 20. Importe en concepto de tríennos: Depto: Depto: 30. Importe Importe en concepto concepto de tríennos: tríennos: Depto: Depto: 40. Importe Importe en concepto concepto de tríennos: tríennos: ... ****************** Importe Total: 999,999 ******************
99,999 99,999 99,999 99,999 99,999 99,999
Ejercicio nº 3. Escribir un disparador de base de datos que no permita borrar o modificar el departamento numero 10 y que cuando se borre otro departamento permita pasar todos los empleados del departamento que se quiere borrar al departamento numero 10.
Ejercicio nº 1. Ejercicio nº 1. 1ª Solución: CREATE OR REPLACE PROCEDURE insertar_depart( nombre_dep VARCHAR2, loc VARCHAR2) AS CURSOR c_dep IS SELECT dnombre FROM depart WHERE dnombre = nombre_dep; v_dummy DEPART.DNOMBRE%TYPE DEFAULT NULL; v_ulti_num DEPART.DEPT_NO%TYPE; nombre_duplicado EXCEPTION; BEGIN /* Comprobación de que el departamento no está duplicado */ OPEN c_dep; FETCH c_dep INTO v_dummy; CLOSE c_dep; IF v_dummy IS NOT NULL THEN RAISE nombre_duplicado; END IF;
/* Captura del último número y cálculo del siguiente , puede levantar not data found*/ SELECT MAX(dept_no) INTO v_ulti_num FROM depart; if v_ulti_num is null then v_ulti_num:=0; end if; /* Inserción de la nueva fila */ INSERT INTO depart VALUES ((TRUNC(v_ulti_num, -1)+10), nombre_dep, loc); EXCEPTION WHEN nombre_duplicado THEN DBMS_OUTPUT.PUT_LINE('Err. departamento duplicado'); WHEN OTHERS THEN RAISE_APPLICATION_ERROR(-20005,'Err. Operación cancelada'); END insertar_depart;
Ejercicio nº 3. CREATE OR REPLACE TRIGGER borrar_depart BEFORE DELETE OR UPDATE OF DEPT_NO ON DEPART FOR EACH ROW BEGIN IF UPDATING('DEPT_NO') THEN IF :OLD.DEPT_NO=10 THEN RAISE_APPLICATION_ERROR (-20001,'Err. Modificacion no permitida'); END IF; IF DELETING THEN IF :OLD.DEPT_NO=10 THEN RAISE_APPLICATION_ERROR (-20002,'Err. Borrado no permitido'); ELSE UPDATE emple SET dept_no = 10 WHERE DEPT_NO=:OLD.DEPT_NO; END IF; END IF; END;
Ejercicio nº 2. CREATE OR REPLACE FUNCTION trienios( fecha1 date,fecha2 date) return integer IS trienios number(2); begin trienios := ABS(TRUNC(MONTHS_BETWEEN(fecha2,fecha1) / 36)); return trienios; end trienios; CREATE OR REPLACE PROCEDURE imp_trienios( imp_trienio NUMBER) IS CURSOR cur_emple is select * FROM emple ORDER BY dept_no; vr_emp cur_emple%ROWTYPE; dep_ant EMPLE.DEPT_NO%TYPE; tot_dep_trienios NUMBER(9) DEFAULT 0; imp_total NUMBER(10) DEFAULT 0; BEGIN OPEN cur_emple; FETCH cur_emple INTO vr_emp; WHILE cur_emple%FOUND LOOP dep_ant := vr_emp.dept_no; WHILE dep_ant = vr_emp.dept_no and cur_emple%FOUND LOOP /* Calculo de trienios por empleado */ tot_dep_trienios:=tot_dep_trienios+imp_trienio*trienios(vr_emp.fecha_a lt,sysdate); FETCH cur_emple INTO vr_emp; END LOOP; /* Líneas de detalle */ DBMS_OUTPUT.PUT_LINE('Depto: '||dep_ant||'. Importe en concepto de trienios: '||to_char(tot_dep_trienios,'99,999')); imp_total:=imp_total+tot_dep_trienios; tot_dep_trienios:=0; END LOOP; CLOSE cur_emple; /* Escribir totales informe */ dbms_output.put_line('*************************'); dbms_output.put_line('Importe total: '|| to_char(imp_total,'999,999')); dbms_output.put_line('*************************'); END imp_trienios;