BBDD
BBDD
4. Reescribe el cdigo de los ejercicios anteriores para convertirlos en funciones que retornen los valores que mostraban los procedimientos.
a) Sumar:
CREATE OR REPLACE FUNCTION sumar2 (num1 NUMBER, num2 NUMBER) RETURN REAL AS suma NUMBER (2); BEGIN suma := num1 + num2; RETURN suma; END; b) Palabra revs CREATE OR REPLACE function palabra_reves2 (palabra VARCHAR) return varchar as reves VARCHAR (20); BEGIN FOR i IN REVERSE 1 .. LENGTH (reves) LOOP reves := reves || SUBSTR (palabra, i, 1); END LOOP; return reves; END;
5. Escribe una funcin que reciba una fecha y devuelva el ao, en numero correspondiente a la fecha.
CREATE OR REPLACE function fecha(fecha date) return number as ao number; begin ao:=to_number(to_char(fecha,'yyyy')); return ao; end;
7. Desarrolla una funcin que devuelva el numero de aos completos que hay entre dos fechas que se pasan como parmetros.
CREATE OR REPLACE function aos_completos(fecha1 date,fecha2 date) return number as aos number; begin aos:=abs(round(months_between(fecha1,fecha2)/12)); return aos; end;
8. Escribe una funcino que, haciendo uso de la funcin anterior, devuelva los trienios que hay entre dos fechas ( un trienio 3 aos).
CREATE OR REPLACE function trienios(fecha1 date,fecha2 date) return number as aos number; begin aos:=FLOOR(aos_completos(fecha1,fecha2)/3); return aos; end;
9. Codifica un procedimiento que reciba una lista de hasta cinco nmeros y visualice su suma.
CREATE OR REPLACE procedure suma5num ( num1 number default 0,num2 number default 0,num3 number default 0, num4 number default 0,num5 number default 0) as sumar5 number(4); begin sumar5:=num1+num2+num3+num4+num5; dbms_output.put_line('La suma de los cinco numeros es ' || sumar5); end;
10. Escribe una funcin que devuelva solamente caracteres alfabeticos sustituyendo cualquier otro carcter por blancos a partir de una cadena que se le pasara en la llamada.
CREATE OR REPLACE function caracteres(cadena VARCHAR) return VARCHAR as alfabeticos VARCHAR(50); caracter CHARACTER; begin for i in 1.. length(cadena) loop caracter:=substr(cadena,i,1); if(ascii(caracter) not between 65 and 90) and (ascii(caracter) not between 97 and 122) then caracter:=' '; end if; alfabeticos:= alfabeticos || caracter; end loop; return alfabeticos; end caracteres;
11. Codifica un procedimiento que permita borrar un empleado cuyo numero se pasara en la llamada.
CREATE OR REPLACE procedure borrar_empleado(num_emple emple.emp_no%type) as id rowid; begin select rowid into id from emple where emp_no = num_emple; delete from emple where rowid=id; dbms_output.put_line('Empleado con numero ' || num_emple || ' borrado'); end borrar_empleado;
12. Escribir un procedimiento que modifique la localidad de un departamento. El procedimiento recibir como parmetros el numero del departamento y la nueva localidad.
CREATE OR REPLACE PROCEDURE modificar_localidad ( num_depart NUMBER, localidad VARCHAR) AS BEGIN UPDATE depart SET loc = localidad WHERE dept_no = num_depart; dbms_output.put_line('La localidad del departamente numero ' || num_depart || ' ahora es ' || localidad); END modificar_localidad;
13. Visualiza todos los procedimientos y funciones del usuario almacenados en la BBDD y su situacin( valid o invalid).
select object_name,object_type, status from user_objects where object_type in ('procedure','function')
14. Desarrolla un procedimiento que visualice el apellido y la fecha de alta de todos los empleados ordenados por apellido.
CREATE OR REPLACE procedure visualizar_empleado as cursor empleado is select apellido, fecha_alt from emple order by apellido; ape_emp VARCHAR(20); fecha_alt DATE; begin open empleado; fetch empleado into ape_emp, fecha_alt; while empleado%found loop dbms_output.put_line(ape_emp || '*' || fecha_alt); fetch empleado into ape_emp, fecha_alt; end loop; close empleado; end visualizar_empleado;
15. Codifica un procedimiento que muestre el nombre de cada departamento y el numero de empleados que tiene.
CREATE OR REPLACE PROCEDURE visualizar_departamento AS CURSOR empleado IS SELECT dnombre, COUNT(emp_no) FROM emple e, depart d WHERE d.dept_no = e.dept_no(+) GROUP BY dnombre; nombredep depart.dnombre%TYPE; num_emp BINARY_INTEGER; BEGIN OPEN empleado; FETCH empleado into nombredep, num_emp; WHILE empleado%FOUND LOOP DBMS_OUTPUT.PUT_LINE(nombredep||' * '||num_emp); FETCH empleado into nombredep,num_emp; END LOOP; CLOSE empleado; END visualizar_departamento;
16. Escribe un programa que visualice el apellido y el salario de los cinco empleados que tienen el salario mas alto.
CREATE OR REPLACE procedure visualizar_ape_sal as cursor empleado is select apellido,salario from emple order by salario desc; emp empleado%rowtype; i number; begin i:=1; open empleado; fetch empleado into emp; while empleado%found and i<=5 loop
dbms_output.put_line(emp.apellido || '*' || emp.salario); fetch empleado into emp; i:=i+1; end loop; close empleado; end visualizar_ape_sal;
17. Codifica un programa que visualice los dos empleados que ganan menos de cada oficio.
CREATE OR REPLACE PROCEDURE emp_2min_sal AS CURSOR empleado IS SELECT apellido, oficio, salario FROM emple ORDER BY oficio, salario; emp empleado%ROWTYPE; oficio_ant EMPLE.OFICIO%TYPE; i NUMBER; BEGIN OPEN empleado; oficio_ant:='*'; FETCH empleado INTO emp; WHILE empleado%FOUND LOOP IF oficio_ant <> emp.oficio THEN oficio_ant := emp.oficio; i := 1; END IF; IF i <= 2 THEN DBMS_OUTPUT.PUT_LINE(emp.oficio||' * ' ||emp.apellido||' * ' ||emp.salario); END IF; FETCH empleado INTO emp; i:=I+1; END LOOP; CLOSE empleado; END emp_2min_sal;
18. Desarrolla un procedimiento que permita insertar nuevos departamentos segn las siguientes especificaciones: - Se pasara al procedimiento el nombre del departamento y la localidad. - El procedimiento insertara la fila nueva asignando como numero de departamento la decena siguiente al numero mayor de la tabla. - Se incluir la gestoin de posibles errores.
CREATE OR REPLACE PROCEDURE insertar_departamento( nom_dep VARCHAR, loc VARCHAR) AS CURSOR departamento IS SELECT dnombre FROM depart WHERE dnombre = nom_dep; variable DEPART.DNOMBRE%TYPE DEFAULT NULL; ult_num DEPART.DEPT_NO%TYPE; nom_duplicado EXCEPTION; BEGIN OPEN departamento; FETCH departamento INTO variable; CLOSE departamento; IF variable IS NOT NULL THEN
RAISE nom_duplicado; END IF; SELECT MAX(dept_no) INTO ult_num FROM depart; INSERT INTO depart VALUES ((TRUNC(ult_num, -1)+10), nom_dep, loc); EXCEPTION WHEN nom_duplicado THEN DBMS_OUTPUT.PUT_LINE('Error, departamento duplicado'); RAISE; END insertar_departamento;
19. Codifica un procedimiento que reciba como parmetros un numero de departamento, un importe y un porcentaje; y que suba el salario a todos los empleados del departamento indicado en la llamada. La subida ser el porcentaje o el importe que se indica en la llamada(el que sea mas beneficioso para el empleado en cada caso)
CREATE OR REPLACE procedure subida_sal1(num_depar emple.dept_no%type, importe number,porcentaje number) as cursor c_sal is select salario, rowid from emple where dept_no=num_depar; vr_sal c_sal%rowtype; v_imp_pct number(10); begin open c_sal; fetch c_sal into vr_sal; while c_sal%found loop v_imp_pct:=greatest((vr_sal.salario/100)*porcentaje,importe); update emple set salario= salario+v_imp_pct where rowid=vr_sal.rowid; fetch c_sal into vr_sal; end loop; close c_sal; exception when no_data_found then dbms_output.put_line('Error, ninguna fila actualizada'); end;
20. Escribe un procedimiento que suba el sueldo de todos los empleados que ganen menos que el salario medio de su oficio. La subida ser el 50% de la diferencia entre el salario del empleado y la media de su oficio. Se deber hacer que la transaccin no se quede amedias, y se gestionara los posibles errores.
CREATE OR REPLACE PROCEDURE subida_sueldo AS CURSOR c_ofi_sal IS SELECT oficio, AVG(salario) salario FROM emple GROUP BY oficio; CURSOR c_emp_sal IS SELECT oficio, salario FROM emple E1 WHERE salario < (SELECT AVG(salario) FROM emple E2 WHERE E2.oficio = E1.oficio)
ORDER BY oficio, salario FOR UPDATE OF salario; vr_ofi_sal c_ofi_sal%ROWTYPE; vr_emp_sal c_emp_sal%ROWTYPE; v_incremento emple.salario%TYPE; BEGIN COMMIT; OPEN c_emp_sal; FETCH c_emp_sal INTO vr_emp_sal; OPEN c_ofi_sal; FETCH c_ofi_sal INTO vr_ofi_sal; WHILE c_ofi_sal%FOUND AND c_emp_sal%FOUND LOOP v_incremento := (vr_ofi_sal.salario - vr_emp_sal.salario) / 2; UPDATE emple SET salario = salario + v_incremento WHERE CURRENT OF c_emp_sal; FETCH c_emp_sal INTO vr_emp_sal; IF c_ofi_sal%FOUND and vr_ofi_sal.oficio <> vr_emp_sal.oficio THEN FETCH c_ofi_sal INTO vr_ofi_sal; END IF; END LOOP; CLOSE c_emp_sal; CLOSE c_ofi_sal; COMMIT; EXCEPTION WHEN OTHERS THEN ROLLBACK WORK; RAISE; END subida_sueldo;
21. Disea una aplicacin que simule un listado de liquidacin de los empleados segn las siguientes especificaciones:
CREATE OR REPLACE PROCEDURE liquidar AS CURSOR c_emp IS SELECT apellido, emp_no, oficio, salario, NVL(comision,0) comision, dept_no, fecha_alt FROM emple ORDER BY apellido; vr_emp c_emp%ROWTYPE; v_trien NUMBER(9) DEFAULT 0; v_comp_r NUMBER(9); v_total NUMBER(10); BEGIN FOR vr_emp in c_emp LOOP v_trien := trienios(vr_emp.fecha_alt,SYSDATE)*5000; BEGIN SELECT COUNT(*) INTO v_comp_r FROM EMPLE WHERE DIR = vr_emp.emp_no; v_comp_r := v_comp_r *10000; EXCEPTION WHEN NO_DATA_FOUND THEN v_comp_r:=0; END; v_total := vr_emp.salario + vr_emp. comision + v_trien + v_comp_r; DBMS_OUTPUT.PUT_LINE('*************************************'); DBMS_OUTPUT.PUT_LINE(' Liquidacion de : '|| vr_emp.apellido ||' Dpto: ' || vr_emp.dept_no || ' Oficio: ' || vr_emp.oficio); DBMS_OUTPUT.PUT_LINE(RPAD('Salario:',16) ||LPAD(TO_CHAR(vr_emp.salario,'9,999,999'),12)); DBMS_OUTPUT.PUT_LINE(RPAD('Trienios: ',16) || LPAD(TO_CHAR(v_trien,'9,999,999'),12)); DBMS_OUTPUT.PUT_LINE('Comp. Respons: ' ||LPAD(TO_CHAR(v_comp_r,'9,999,999'),12)); DBMS_OUTPUT.PUT_LINE(RPAD('Comision: ' ,16) ||LPAD(TO_CHAR(vr_emp.comision,'9,999,999'),12)); DBMS_OUTPUT.PUT_LINE('------------------'); DBMS_OUTPUT.PUT_LINE(RPAD(' Total : ',16) ||LPAD(TO_CHAR(v_total,'9,999,999') ,12)); DBMS_OUTPUT.PUT_LINE('**************************************'); END LOOP; EXCEPTION WHEN NO_DATA_FOUND THEN DBMS_OUTPUT.PUT_LINE('No se ha encontrado ninguna fila'); END liquidar;
22. Crea la tabla t_liquidacion con las columnas, apellido, departamento, oficio, salario, trienios, comp_responsabilidad, comisin y total; y modifica la aplicacion anterior para que, en lugar de realizar el listado directamente en pantalla,fguarde los datos en la tabla. Se controlaran todas las posibles incidencias que puedan ocurrir durante el proceso.
CREATE TABLE T_LIQUIDACION ( APELLIDO VARCHAR(10), DEPARTAMENTO NUMBER(2), OFICIO VARCHAR(10),
CREATE OR REPLACE PROCEDURE liquidar2 AS CURSOR c_emp IS SELECT apellido, emp_no, oficio, salario, NVL(comision,0) comision, dept_no, fecha_alt FROM emple ORDER BY apellido; vr_emp c_emp%ROWTYPE; v_trien NUMBER(9) DEFAULT 0; v_comp_r NUMBER(9); v_total NUMBER(10); BEGIN COMMIT WORK; FOR vr_emp in c_emp LOOP v_trien := trienios(vr_emp.fecha_alt,SYSDATE)*5000; BEGIN SELECT COUNT(*) INTO v_comp_r FROM EMPLE WHERE DIR = vr_emp.emp_no; v_comp_r := v_comp_r *10000; EXCEPTION WHEN NO_DATA_FOUND THEN v_comp_r:=0; END; v_total := vr_emp.salario + vr_emp. comision + v_trien + v_comp_r; INSERT INTO t_liquidacion (APELLIDO, OFICIO, SALARIO, TRIENIOS, COMP_RESPONSABILIDAD, COMISION, TOTAL) VALUES (vr_emp.apellido, vr_emp.oficio, vr_emp.salario, v_trien, v_comp_r, vr_emp.comision, v_total); END LOOP; EXCEPTION WHEN OTHERS THEN ROLLBACK WORK; END liquidar2;