PRACTICA - PL-SQL Joel-Fernando-Mauricio
PRACTICA - PL-SQL Joel-Fernando-Mauricio
DECLARE...BEGIN...END
a) Creación de un bloque PL/SQL.
SQL> BEGIN
2 DBMS_OUTPUT.PUT_LINE('HOLA');
3 END;
4/
2.- Escribir un bloque PL/SQL que cuente el número de filas que hay en la tabla
productos, deposita el resultado en la variable v_num, y visualiza su contenido.
SQL>DECLARE
2 v_num NUMBER;
3 BEGIN
4 SELECT count(*) INTO v_num
5 FROM productos;
6 DBMS_OUTPUT.PUT_LINE(v_num);
7 END;
8/
1
START...,GET...,RUN
c) ¿Cómo ejecutar o arrancar un bloque PL/SQL?
O bien:
SQL> GET A:\[Link]
SQL> RUN
CREATE OR REPLACE PROCEDURE...
1.- Creación procedimientos.
2
suma := num1 + num2;
DBMS_OUTPUT.PUT_LINE('Suma: '|| suma);
END sumar_numeros;
3
3) Escribir una función que reciba una fecha y devuelva el año, en número,
correspondiente a esa fecha.
4
2 .- Creación de funciones.
DECLARE n
NUMBER(4);
BEGIN
n := anio(SYSDATE);
DBMS_OUTPUT.PUT_LINE('AÑO : '|| n); END;
5
5) Dado el siguiente procedimiento:
Indicar cuáles de las siguientes llamadas son correctas y cuáles incorrectas, en este
último caso escribir la llamada correcta usando la notación posicional (en los casos que
se pueda):
1º. crear_depart;
2º. crear_depart(50);
3º. crear_depart('COMPRAS');
4º. crear_depart(50,'COMPRAS');
5º. crear_depart('COMPRAS', 50);
6º. crear_depart('COMPRAS', 'VALENCIA');
7º. crear_depart(50, 'COMPRAS', 'VALENCIA');
8º. crear_depart('COMPRAS', 50, 'VALENCIA');
9º. crear_depart('VALENCIA', ‘COMPRAS’);
10º. crear_depart('VALENCIA', 50);
2º Correcta.
6
4º Correcta.
5º Incorrecta: los argumentos están en orden inverso. Solución:
crear_depart(50, 'COMPRAS');
7º Correcta.
'COMPRAS', 'VALENCIA');
6) Desarrollar una función que devuelva el número de años completos que hay entre
dos fechas que se pasan como argumentos.
7
7) Escribir una función que, haciendo uso de la función anterior devuelva los trienios
que hay entre dos fechas. (Un trienio son tres años completos).
8
PROCEDIMIENTOS Y FUNCIONES
3 .- Procedimientos y funciones.
9
9) Escribir una función que devuelva solamente caracteres alfabéticos sustituyendo
cualquier otro carácter por blancos a partir de una cadena que se pasará en la llamada.
10
importe NUMBER) AS
cambio NATURAL := importe;
moneda NATURAL;
v_uni_moneda NATURAL;
BEGIN
DBMS_OUTPUT.PUT_LINE('***** DESGLOSE DE: ' || importe );
WHILE cambio > 0 LOOP IF
cambio >= 5000 THEN
moneda := 5000; ELSIF
cambio >= 2000 THEN
moneda := 2000; ELSIF
cambio >= 1000 THEN
moneda := 1000; ELSIF
cambio >= 500 THEN
moneda := 500; ELSIF
cambio >= 200 THEN
moneda := 200; ELSIF
cambio >= 100 THEN
moneda := 100; ELSIF
cambio >= 50 THEN
moneda := 50; ELSIF
cambio >= 25 THEN
moneda := 25; ELSIF
cambio >= 10 THEN
moneda := 10; ELSIF
cambio >= 5 THEN
moneda := 5; ELSE
moneda := 1; END IF;
v_uni_moneda := TRUNC(cambio / moneda); DBMS_OUTPUT.PUT_LINE(v_uni_moneda
||
' Unidades de: ' || moneda || ' Ptas. '); cambio
:= MOD(cambio, moneda);
END LOOP;
END desglose_cambio;
11) Codificar un procedimiento que permita borrar un empleado cuyo número se pasará
en la llamada.
11
CREATE OR REPLACE PROCEDURE borrar_emple(
num_emple emple.emp_no%TYPE)
AS v_row ROWID;
BEGIN
SELECT ROWID INTO v_row FROM emple
WHERE emp_no = num_emple;
DELETE FROM emple WHERE ROWID = v_row; END
borrar_emple;
CREATE OR REPLACE
PROCEDURE modificar_localidad(
num_depart NUMBER, localidad
VARCHAR2)
AS
BEGIN
UPDATE depart SET loc = localidad
WHERE dept_no = num_depart;
END modificar_localidad;
Nota: Lo indicado en la nota del ejercicio anterior se puede aplicar también a este.
12
v_fecha DATE; BEGIN
OPEN c_emple;
FETCH c_emple into v_apellido, v_fecha;
WHILE c_emple%FOUND LOOP
DBMS_OUTPUT.PUT_LINE( v_apellido||' * '||v_fecha);
FETCH c_emple into v_apellido,v_fecha;
END LOOP;
CLOSE c_emple;
END ver_emple;
4) Escribir un programa que visualice el apellido y el salario de los cinco empleados que
tienen el salario más alto.
5) Codificar un programa que visualice los dos empleados que ganan menos de cada
oficio.
14
WHILE c_emp%FOUND LOOP
IF oficio_ant <> vr_emp.oficio THEN
oficio_ant := vr_emp.oficio;
i := 1;
END IF;
IF i <= 2 THEN
DBMS_OUTPUT.PUT_LINE(vr_emp.oficio||' * '
||vr_emp.apellido||' * '
||vr_emp.salario);
END IF;
FETCH c_emp INTO vr_emp;
i:=I+1;
END LOOP;
CLOSE c_emp;
END emp_2minsal;
6) Escribir un programa que muestre, en formato similar a las rupturas de control o
secuencia vistas en SQL*plus los siguientes datos:
15
' NUM. EMPLEADOS: '||cont_emple ||
' SUM. SALARIOS: '||sum_sal);
dep_ant := vr_emp.dept_no;
tot_emple := tot_emple + cont_emple;
tot_sal:= tot_sal + sum_sal;
cont_emple:=0;
sum_sal:=0; END IF;
/* Líneas de detalle */
DBMS_OUTPUT.PUT_LINE(RPAD(vr_emp.apellido,10)|| ' * '
||LPAD(TO_CHAR(vr_emp.salario,'9,999,999'),12));
/* Incrementar y acumular */
cont_emple := cont_emple + 1;
sum_sal:=sum_sal + vr_emp.salario;
8) Escribir un procedimiento que reciba todos los datos de un nuevo empleado procese
la transacción de alta, gestionando posibles errores.
17
BEGIN
/* Comprobación de que existe el departamento */
SELECT dept_no INTO v_dummy_dep
FROM depart WHERE dept_no = dep;
EXCEPTION
WHEN NO_DATA_FOUND THEN
IF v_dummy_dep IS NULL THEN
RAISE_APPLICATION_ERROR(-20005,
'Err. Departamento inexistente');
ELSIF v_dummy_jef IS NULL THEN
RAISE_APPLICATION_ERROR(-20005,
'Err. No existe el jefe');
ELSE
RAISE_APPLICATION_ERROR(-20005,
'Err. Datos no encontrados(*)');
END IF;
WHEN DUP_VAL_ON_INDEX THEN
DBMS_OUTPUT.PUT_LINE
('[Link] de empleado duplicado');
RAISE;
END alta_emp;
WHILE...FOUND...LOOP...
3 .- Procedimientos con cursores y parámetros de entrada.
/* Actualizar */
UPDATE EMPLE SET SALARIO=SALARIO + v_imp_pct
WHERE ROWID = vr_sal.rowid;
10) Escribir un procedimiento que suba el sueldo de todos los empleados que ganen
menos que el salario medio de su oficio. La subida será del 50% de la diferencia entre el
salario del empleado y la media de su oficio. Se deberá asegurar que la transacción no
se quede a medias, y se gestionarán los posibles errores.
vr_ofi_sal c_ofi_sal%ROWTYPE;
vr_emp_sal c_emp_sal%ROWTYPE;
v_incremento [Link]%TYPE;
BEGIN
COMMIT;
OPEN c_emp_sal;
FETCH c_emp_sal INTO vr_emp_sal;
19
OPEN c_ofi_sal;
FETCH c_ofi_sal INTO vr_ofi_sal;
WHILE c_ofi_sal%FOUND AND c_emp_sal%FOUND LOOP
/* actualizar */
UPDATE emple SET salario = salario + v_incremento
WHERE CURRENT OF c_emp_sal;
/* siguiente empleado */
FETCH c_emp_sal INTO vr_emp_sal;
**********************************************************************
Liquidación del empleado:...................(1)
Dpto:.................(2) Oficio:...........(3)
20
▪ 1 ,2, 3 y 4 Corresponden al apellido, departamento, oficio y salario del
empleado.
▪ 5 Es el importe en concepto de trienios. Cada trienio son tres años completos
desde la fecha de alta hasta la de emisión y supone 50€.
▪ 6 Es el complemento por responsabilidad. Será de 100€ por cada empleado que
se encuentre directamente a cargo del empleado en cuestión. ▪ 7 Es la
comisión. Los valores nulos serán sustituidos por ceros.
▪ 8 Suma de todos los conceptos anteriores.
21
||' 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;
/* Nota: También se puede utilizar una cláusula SELECT más compleja:
CURSOR c_emp IS
SELECT APELLIDO, EMP_NO, OFICIO,
(EMP_CARGO * 10000) COM_RESPONSABILIDAD,
SALARIO, NVL(COMISION, 0) COMISION, DEPT_NO,
TRIENIOS(FECHA_ALT, SYSDATE) * 5000 TOT_TRIENIOS
FROM EMPLE,(SELECT DIR,COUNT(*) EMP_CARGO FROM EMPLE
GROUP BY DIR) DIREC
WHERE EMPLE.EMP_NO = [Link](+)
ORDER BY APELLIDO;
12) Crear la tabla T_liquidacion con las columnas apellido, departamento, oficio,
salario, trienios, comp_responsabilidad, comisión y total; y modificar la aplicación
anterior para que en lugar de realizar el listado directamente en pantalla, guarde los
datos en la tabla. Se controlarán todas las posibles incidencias que puedan ocurrir
durante el proceso.
22
COMP_RESPONSABILIDAD NUMBER(10),
COMISION NUMBER(10),
TOTAL NUMBER(10)
);
23
ROLLBACK WORK;
END liquidar2;
CREATE OR REPLACE TRIGGER...
a) ¿Cómo crear un trigger?.
1.- Construir un disparador de base de datos que permita auditar las operaciones de
inserción o borrado de datos que se realicen en la tabla emple según las siguientes
especificaciones:
- En primer lugar se creará desde SQL*Plus la tabla auditaremple con la columna col1
VARCHAR2(200).
- Cuando se produzca cualquier manipulación se insertará una fila en dicha tabla que
contendrá: - Fecha y hora
- Número de empleado
- Apellido
- La operación de actualización INSERCIÓN o BORRADO
2.- Escribir un trigger de base de datos un que permita auditar las modificaciones en la
tabla empleados insertado en la tabla auditaremple los siguientes datos:
- Fecha y hora
- Número de empleado
- Apellido
- La operación de actualización: MODIFICACIÓN.
24
- El valor anterior y el valor nuevo de cada columna modificada. (solo las columnas
modificadas)
25
||:OLD.DEPT_NO|| '*'||:NEW.DEPT_NO; END
IF;
3.- Escribir un disparador de base de datos que haga fallar cualquier operación de
modificación del apellido o del número de un empleado, o que suponga una subida de
sueldo superior al 10%.
27
NUMBER, v_dep_nue
NUMBER); PROCEDURE
cambiar_localidad (v_num_dep
NUMBER, v_loc VARCHAR2);
PROCEDURE visualizar_datos_depart
(v_num_dep NUMBER);
PROCEDURE visualizar_datos_depart
(v_nom_dep VARCHAR2);
END gest_depart;
/
PROCEDURE insert_depart(
v_nom_dep VARCHAR2,
v_loc VARCHAR2) AS
ultimo_dep DEPART.DEPT_NO%TYPE; nombre_repetido
EXCEPTION;
BEGIN
28
SELECT MAX(DEPT_NO) INTO ultimo_dep FROM DEPART;
INSERT INTO DEPART VALUES ((TRUNC(ultimo_dep, -1) +10),
v_nom_dep,v_loc);
EXCEPTION
WHEN nombre_repetido THEN
DBMS_OUTPUT.PUT_LINE
('Err. Nombre de departamento duplicado');
WHEN NO_DATA_FOUND THEN /* Si no había ningún departamento */
INSERT INTO DEPART VALUES (10,v_nom_dep,v_loc);
END insert_depart;
/**************************************************************/
PROCEDURE borrar_depar (v_dep_borrar NUMBER, v_dep_nue NUMBER)
AS
BEGIN
UPDATE emple SET dept_no = v_dep_nue
WHERE DEPT_NO=v_dep_borrar;
DELETE FROM depart WHERE dept_no = v_dep_borrar;
END borrar_depar;
/*************************************************************/
PROCEDURE visualizar_datos_depart
(v_num_dep NUMBER)
AS
vr_dep depart%ROWTYPE; v_num_empleados
NUMBER(4);
BEGIN
SELECT * INTO vr_dep FROM depart
WHERE DEPT_NO=v_num_dep;
SELECT COUNT(*) INTO v_num_empleados FROM
EMPLE WHERE DEPT_NO=v_num_dep;
DBMS_OUTPUT.PUT_LINE
('Número de departamento: '||vr_dep.dept_no);
DBMS_OUTPUT.PUT_LINE
('Nombre del departamento: '||vr_dep.dnombre);
DBMS_OUTPUT.PUT_LINE
('Localidad : '||vr_dep.loc);
DBMS_OUTPUT.PUT_LINE
('Numero de empleados : '||v_num_empleados);
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('Err departamento no encontrado');
END visualizar_datos_depart;
/*************************************************************/
29
(v_nom_dep VARCHAR2)
AS v_num_dep depart.dept_no
%TYPE; vr_dep depart%ROWTYPE;
v_num_empleados NUMBER(4);
BEGIN
v_num_dep:=buscar_depart_por_nombre(v_nom_dep);
SELECT * INTO vr_dep FROM depart
WHERE dept_no=v_num_dep;
SELECT COUNT(*) INTO v_num_empleados FROM EMPLE
WHERE dept_no=v_num_dep;
DBMS_OUTPUT.PUT_LINE
('Número de departamento: '||vr_dep.dept_no);
DBMS_OUTPUT.PUT_LINE
('Nombre del departamento: '||vr_dep.dnombre);
DBMS_OUTPUT.PUT_LINE
('Localidad : '||vr_dep.loc);
DBMS_OUTPUT.PUT_LINE
('Numero de empleados : '||v_num_empleados);
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('Err departamento no encontrado');
END visualizar_datos_depart;
/*************************************************************/
FUNCTION buscar_depart_por_nombre
(v_nom_dep VARCHAR2)
RETURN NUMBER
AS
v_num_dep depart.dept_no%TYPE;
BEGIN
SELECT dept_no INTO v_num_dep FROM depart
WHERE DNOMBRE = v_nom_dep;
RETURN v_num_dep;
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('Err departamento no encontrado');
END buscar_depart_por_nombre;
/*************************************************************/
PROCEDURE cambiar_localidad(
v_num_dep NUMBER, v_loc
VARCHAR2)
AS
BEGIN
30
UPDATE depart
SET LOC=v_loc
WHERE dept_no=v_num_dep;
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('Err departamento no encontrado');
END cambiar_localidad;
END gest_depart;
CREATE OR REPLACE PACKAGE BODY....
2 .- ¿Cómo crear un paquete?.
- insertar_nuevo_emple
- borrar_emple. Cuando se borra un empleado todos los empleados que dependían de él
pasarán a depender del director del empleado borrado.
- modificar_oficio_emple
- modificar_dept_emple
- modificar_dir_emple
- modificar_salario_emple
- modificar_comision_emple
- visualizar_datos_emple. También se incluirá una versión
sobrecargada del procedimiento que recibirá el nombre del empleado.
- buscar_emple_por_nombre. Función local que recibe el nombre y devuelve el número.
Todos los procedimientos recibirán el número del empleado seguido de los demás datos
necesarios. También se incluirán en el paquete cursores y declaraciones de tipo registro,
así como siguientes procedimientos que afectarán a todos los empleados:
PROCEDURE
insertar_nuevo_emple( v_num_emp
EMPLE.EMP_NO%TYPE, v_apell
[Link]%TYPE, v_oficio
[Link]%TYPE, v_dir
31
[Link]%TYPE, v_fecha_al
EMPLE.FECHA_ALT%TYPE, v_sal
[Link]%TYPE,
v_comision [Link]%TYPE DEFAULT NULL, v_num_dep
EMPLE.DEPT_NO%TYPE);
PROCEDURE
modificar_dept_emple( v_num_emp
EMPLE.EMP_NO%TYPE, v_dept
EMPLE.DEPT_NO%TYPE);
PROCEDURE
modificar_dir_emple( v_num_emp
EMPLE.EMP_NO%TYPE, v_direccion
[Link]%TYPE);
PROCEDURE
modificar_salario_emple( v_num_emp
EMPLE.EMP_NO%TYPE, v_salario
[Link]%TYPE);
PROCEDURE
modificar_comision_emple( v_num_emp
EMPLE.EMP_NO%TYPE, v_comis
[Link]%TYPE);
PROCEDURE subida_salario_imp(
v_imp_subida NUMBER); END
gest_emple;
32
CURSOR c_sal RETURN EMPLE%ROWTYPE
IS SELECT * FROM EMPLE;
FUNCTION buscar_emple_por_nombre
(n_emp VARCHAR2)
RETURN NUMBER;
/*************************************************************/
PROCEDURE insertar_nuevo_emple( v_num_emp EMPLE.EMP_NO%TYPE, v_apell
[Link]%TYPE, v_oficio [Link]%TYPE, v_dir [Link]%TYPE,
v_fecha_al EMPLE.FECHA_ALT%TYPE, v_sal [Link]%TYPE,
v_comision [Link]%TYPE DEFAULT NULL,
v_num_dep EMPLE.DEPT_NO%TYPE)
IS
dir_no_existe EXCEPTION;
BEGIN DECLARE
v_num_emple EMPLE.EMP_NO%TYPE;
BEGIN
SELECT EMP_NO INTO v_num_emple FROM EMPLE
WHERE EMP_NO=v_dir;
EXCEPTION
WHEN NO_DATA_FOUND THEN
RAISE insertar_nuevo_emple.dir_no_existe;
END;
INSERT INTO EMPLE VALUES (v_num_emp, v_apell, v_oficio,
v_dir, v_fecha_al, v_sal, v_comision, v_num_dep);
EXCEPTION
WHEN DUP_VAL_ON_INDEX THEN
DBMS_OUTPUT.PUT_LINE('Err. Número de empleado duplicado');
WHEN dir_no_existe THEN
DBMS_OUTPUT.PUT_LINE('Err. No existe el director');
END insertar_nuevo_emple;
/*************************************************************/
PROCEDURE borrar_emple(
v_num_emple NUMBER)
IS
emp_dir [Link]%TYPE;
BEGIN
SELECT DIR INTO emp_dir FROM EMPLE
WHERE EMP_NO = v_num_emple;
DELETE FROM EMPLE WHERE EMP_NO = v_num_emple;
UPDATE EMPLE SET DIR = emp_dir WHERE DIR = v_num_emple; END
borrar_emple;
33
/*************************************************************/
PROCEDURE modificar_oficio_emple( v_num_emp EMPLE.EMP_NO%TYPE, v_oficio
[Link]%TYPE)
IS
BEGIN
UPDATE EMPLE SET OFICIO = v_oficio
WHERE EMP_NO = v_num_emp;
END modificar_oficio_emple;
/*************************************************************/
PROCEDURE modificar_dept_emple(
v_num_emp EMPLE.EMP_NO%TYPE,
v_dept EMPLE.DEPT_NO%TYPE)
IS
BEGIN
UPDATE EMPLE SET DEPT_NO = v_dept WHERE EMP_NO = v_num_emp; END
modificar_dept_emple;
/*************************************************************/
PROCEDURE
modificar_dir_emple( v_num_emp
EMPLE.EMP_NO%TYPE, v_direccion
[Link]%TYPE)
IS
BEGIN
UPDATE EMPLE SET DIR = v_direccion WHERE EMP_NO = v_num_emp; END
modificar_dir_emple;
/*************************************************************/
PROCEDURE modificar_salario_emple(
v_num_emp EMPLE.EMP_NO%TYPE,
v_salario [Link]%TYPE)
IS
BEGIN
UPDATE EMPLE SET SALARIO = v_salario WHERE EMP_NO = v_num_emp; END
modificar_salario_emple;
/*************************************************************/
PROCEDURE modificar_comision_emple(
v_num_emp EMPLE.EMP_NO%TYPE,
v_comis [Link]%TYPE)
IS
BEGIN
UPDATE EMPLE SET COMISION = v_comis WHERE EMP_NO = v_num_emp;
END modificar_comision_emple;
34
/*************************************************************/
PROCEDURE visualizar_datos_emple( v_num_emp EMPLE.EMP_NO%TYPE)
IS
reg_emple EMPLE%ROWTYPE;
BEGIN
SELECT * INTO reg_emple FROM EMPLE WHERE EMP_NO = v_num_emp;
DBMS_OUTPUT.PUT_LINE('NUMERO EMPLEADO: '||reg_emple.EMP_NO);
DBMS_OUTPUT.PUT_LINE('APELLIDO: '||reg_emple.APELLIDO);
DBMS_OUTPUT.PUT_LINE('OFICIO: '||reg_emple.OFICIO);
DBMS_OUTPUT.PUT_LINE('DIRECTOR: '||reg_emple.DIR);
DBMS_OUTPUT.PUT_LINE('FECHA ALTA): '||reg_emple.FECHA_ALT);
DBMS_OUTPUT.PUT_LINE('SALARIO: '||reg_emple.SALARIO);
DBMS_OUTPUT.PUT_LINE('COMISION: '||reg_emple.COMISION);
DBMS_OUTPUT.PUT_LINE('NUMERO DEPARTAMENTO: '||reg_emple.DEPT_NO);
END visualizar_datos_emple;
/*************************************************************/
PROCEDURE visualizar_datos_emple(
v_nombre_emp [Link]%TYPE)
IS
v_num_emp EMPLE.EMP_NO%TYPE;
reg_emple EMPLE%ROWTYPE;
BEGIN
v_num_emp:=buscar_emple_por_nombre(v_nombre_emp); SELECT *
INTO reg_emple FROM EMPLE WHERE EMP_NO = v_num_emp;
DBMS_OUTPUT.PUT_LINE('NUMERO EMPLEADO: '||reg_emple.EMP_NO);
DBMS_OUTPUT.PUT_LINE('APELLIDO : '||reg_emple.APELLIDO);
DBMS_OUTPUT.PUT_LINE('OFICIO : '||reg_emple.OFICIO);
DBMS_OUTPUT.PUT_LINE('DIRECTOR : '||reg_emple.DIR);
DBMS_OUTPUT.PUT_LINE('FECHA ALTA: '||reg_emple.FECHA_ALT);
DBMS_OUTPUT.PUT_LINE('SALARIO : '||reg_emple.SALARIO);
DBMS_OUTPUT.PUT_LINE('COMISION : '||reg_emple.COMISION);
DBMS_OUTPUT.PUT_LINE('NUM DEPART: '||reg_emple.DEPT_NO);
END visualizar_datos_emple;
/*************************************************************/
FUNCTION buscar_emple_por_nombre(
n_emp VARCHAR2)
RETURN NUMBER
IS
numero EMPLE.EMP_NO%TYPE;
BEGIN
SELECT EMP_NO INTO numero FROM EMPLE WHERE APELLIDO = n_emp;
RETURN numero;
END buscar_emple_por_nombre;
35
/*************************************************************/
PROCEDURE subida_salario_pct(
v_pct_subida NUMBER)
IS
subida_mayor EXCEPTION;
BEGIN
IF v_pct_subida > 25 THEN
RAISE subida_mayor;
END IF;
FOR vr_c_sal IN c_sal LOOP
UPDATE EMPLE SET SALARIO = SALARIO +
(SALARIO * v_pct_subida / 100)
WHERE EMP_NO = vr_c_sal.emp_no;
END LOOP;
EXCEPTION
WHEN subida_mayor THEN
DBMS_OUTPUT.PUT_LINE('Subida superior a la permitida');
END subida_salario_pct;
/*************************************************************/
1.- Crear un procedimiento que permita consultar todos los datos de la tabla depart a
partir de una condición que se indicará en la llamada al procedimiento.
36
(condicion VARCHAR2,
valor VARCHAR2) AS
id_cursor INTEGER; v_comando
VARCHAR2(2000); v_dummy
NUMBER; v_dept_no
depart.dept_no%TYPE; v_dnombre
[Link]%TYPE;
v_loc [Link]%TYPE; BEGIN id_cursor :=
DBMS_SQL.OPEN_CURSOR; v_comando := ‘
SELECT dept_no, dnombre, loc
FROM depart
WHERE ‘ || condicion || ‘:val_1’;
DBMS_OUTPUT.PUT_LINE(v_comando);
DBMS_SQL.PARSE(id_cursor, v_comando, DBMS_SQL.V7);
DBMS_SQL.BIND_VARIABLE(id_cursor, ‘:val_1’, valor);
/* A continuación se especifican las variables que recibirán los valores de la selección*/
DBMS_SQL.DEFINE_COLUMN(id_cursor, 1, v_dept_no);
DBMS_SQL.DEFINE_COLUMN(id_cursor, 2, v_dnombre,14);
DBMS_SQL.DEFINE_COLUMN(id_cursor, 3, v_loc, 14);
v_dummy := DBMS_SQL.EXECUTE(id_cursor);
/* La función FETCH_ROWS recupera filas y retorna el número de filas que quedan */
WHILE DBMS_SQL.FETCH_ROWS(id_cursor)>0 LOOP
/* A continuación se depositarán los valores recuperados en las variables PL/SQL */
DBMS_SQL.COLUMN_VALUE(id_cursor, 1, v_dept_no);
DBMS_SQL.COLUMN_VALUE(id_cursor, 2, v_dnombre);
DBMS_SQL.COLUMN_VALUE(id_cursor, 3, v_loc);
DBMS_OUTPUT.PUT_LINE(v_dept_no || ’*’ || v_dnombre
|| ’*’ || v_loc);
END LOOP;
DBMS_SQL.CLOSE_CURSOR(id_cursor);
EXCEPTION
WHEN OTHERS THEN
DBMS_SQL.CLOSE_CURSOR(id_cursor);
RAISE;
END consultar_depart;
37