Вы находитесь на странице: 1из 8

PL-SQL: Practico

Filed under: plsql, programming techniques, tutorial admin @ 1:09 am

Como parte de las practicas de una materia de mi carrera universitaria, tuve que practicar bastante con PLSQL. PLSQL es un lenguaje de script propietario, y una herramienta ineludible de todo programador de bases de datos Oracle en entornos productivos. Si bien PLSQL es un lenguaje antiguo, y notablemente limitado en comparacin con otros lenguajes de scripts, es una herramienta ineludible al trabajar con bases de datos Oracle. Si bien existe abundante -y realmente excelentematerial en la web, me parecio interesante publicar algunos de los ejercicios basicos que resolvi en aquel entonces. Espero que les sea de utilidad.

1. Escribir un procedimiento Alta_Job para insertar un nuevo cargo en la tabla JOB: el Job_Id debe generarse sumando 1 al mximo Job_Id existente el nombre del cargo (Function) debe ser informado por parmetro. Recordar que en la base de datos todos los nombres de funcin estn en maysculas asentar en la base de datos este insert (Commit).

CREATE OR REPLACE PROCEDURE ALTA_JOB ( p_cargo IN job.function%TYPE) IS max_job_id NUMBER; BEGIN SELECT MAX(job_id) INTO max_job_id FROM job; INSERT INTO job VALUES((max_job_id + 1),UPPER(p_cargo)); DBMS_OUTPUT.put_line (Se ha insertado un cargo'); Commit; END alta_job;
2. Crear un procedimiento Upd_Job para actualizar los nombres de los cargos: Informar el job_id y el nuevo nombre de funcin mediante dos parmetros. Si el job_id no existe, informar mediante un mensaje y cancelar el procedimiento.

CREATE OR REPLACE PROCEDURE UPD_JOB (p_id IN job.job_id%TYPE, p_cargo IN job.function%TYPE) IS BEGIN UPDATE job SET FUNCTION = UPPER(p_cargo) WHERE job_id = p_id; IF sql%notfound THEN DBMS_OUTPUT.put_line ('Error: El cargo '||p_id ||' no existe'); END IF; END upd_job;
3. Crear un procedimiento Lista_ Emp que recibe mediante un parmetro el cdigo de un departamento e informe el nombre y apellido de todos los empleados que trabajan en l. Contemplar todos los errores posibles: el nombre no corresponde a un departamento, no hay empleados en el departamento o cualquier error y desplegar mensajes.

CREATE OR REPLACE PROCEDURE LISTA_EMP (p_ depto IN department.department_id%TYPE) CURSOR c_emp IS SELECT first_name || ','||last_name nombre FROM employee WHERE department_id = p_depto; v_x VARCHAR2(1); v_i NUMBER :=0; BEGIN SELECT 'x' INTO v_x FROM department WHERE department_id=p_depto; FOR r_emp IN c_emp LOOP DBMS_OUTPUT.put_line(r_emp.nombre); v_i := v_i +1;

IS

END LOOP; IF v_i = 0 THEN DBMS_OUTPUT.put_line('Este departamento no tiene empleados'); END IF; EXCEPTION WHEN NO_DATA_FOUND THEN DBMS_OUTPUT.put_line('Error: '||'No existe el departamento'); WHEN OTHERS THEN DBMS_OUTPUT.PUT_line('Error: ' || SQLERRM); END LISTA_EMP;
4. Crear un procedimiento Consulta_Precio que recibe un cdigo de producto y devuelve el precio de lista (List_price) y el precio_mnimo (Min_price). Si el producto no existe, atrapar la excepcin correspondiente y emitir un mensaje de error. Para probar el procedimiento invocarlo desde un bloque annimos usando dos variables de Sql*plus para los dos parmetros de OUT: Variable precio number Variable precio_min number Exec consulta_precio (104361, :precio, :precio_min)

CREATE OR REPLACE PROCEDURE Consulta_Precio (p_id IN price.product_id%TYPE, p_list OUT price.list_price%TYPE, p_min OUT price.min_price%TYPE) IS BEGIN SELECT list_price, min_price INTO p_list, p_min FROM price WHERE product_id = p_id AND end_date IS NULL; EXCEPTION WHEN NO_DATA_FOUND THEN DBMS_OUTPUT.put_line('Error: '||'No existe el producto'); WHEN OTHERS THEN DBMS_OUTPUT.put_line('Error: ' || SQLERRM); END Consulta_Precio;
5. Escribir una funcin Q_Credit recibe el id de un cliente y devuelve el lmite de crdito que tiene actualmente (credit_limit). Si el cliente no existe debe devolver nulls.

CREATE OR REPLACE FUNCTION Q_CREDIT (p_id IN customer.customer.id %TYPE) RETURN NUMBER IS v_credit customer.credit_limit %TYPE; BEGIN SELECT credit_limit INTO v_credit FROM customer WHERE customer_id = p_id; RETURN v_credit;

EXCEPTION WHEN NO_DATA_FOUND THEN RETURN NULL; END Q_CREDIT;


6. Crear una funcin Valida_Loc que recibe un cdigo de localidad y devuelve TRUE si el cdigo existe en la tabla Location, en caso contrario devuelve FALSE.

CREATE OR REPLACE FUNCTION Valida_Loc (p_loc IN location.location_id%TYPE) RETURN BOOLEAN IS v_x VARCHAR2(1); BEGIN SELECT 'X' INTO v_x FROM location WHERE location_id = p_loc; RETURN TRUE; EXCEPTION WHEN NO_DATA_FOUND THEN RETURN FALSE; END Valida_Loc;
7. Crear un procedimiento New_Dept para insertar una fila en la tabla Department. Este procedimiento recibe como parmetros el id, (Department_id), el nombre (Name) y la localidad (Location_id). Para insertar el departamento se debe validar que el cdigo de localidad sea vlido usando la funcin Valida_Loc. Si la localidad es invlida cancelar el procedimiento con un mensaje se error.

CREATE OR REPLACE PROCEDURE NEW_DEPT ( p_id department.department_id%TYPE, p_name department.name%TYPE, p_loc department.location_id%TYPE) IS BEGIN IF Valida_Loc (p_loc) THEN INSERT INTO department VALUES (p_id, UPPER(p_name), p_loc); ELSE RAISE_APPLICATION_ERROR (-20000, 'Localidad invalida'); END IF; DBMS_OUTPUT.Put_line('Se ha insertado un departamento'); EXCEPTION WHEN DUP_VAL_ON_INDEX THEN DBMS_OUTPUT.Put_line ('ERROR: Clave duplicada'); WHEN OTHERS THEN DBMS_OUTPUT.Put_line('Error: '|| SQLERRM); END New_Dept;
8. Crear un procedimiento Emps_Ant que carga en una tabla pl/sql los datos de los primeros n empleados

que ganan ms que un importe dado: el importe a consultar y la cantidad de empleados a cargar deben informarse por parmetros. La cantidad por default, si no se informa, debe ser 10. en la tabla de memoria, guardar el id del empleado, su nombre y apellido y su salario. recorrer toda la tabla para desplegar todos los empleados. si no existen empleados, informar con un mensaje de advertencia.

CREATE OR REPLACE PROCEDURE Emps_Ant (p_sal IN NUMBER,p_n IN NUMBER DEFAULT 10) IS CURSOR c_emp IS SELECT employee_id id, First_name||','||last_name nombre, salary FROM Employee WHERE salary > p_sal ORDER BY salary ; TYPE T1 IS TABLE OF c_emp%ROWTYPE INDEX BY BINARY_INTEGER; t_emp T1; i BINARY_INTEGER :=0; BEGIN FOR reg_emp IN c_emp LOOP i := i+1; t_emp(i) := reg_emp; EXIT WHEN c_emp%rowcount = p_n; END LOOP; IF t_emp.FIRST IS NULL THEN DBMS_OUTPUT.Put_line ('Error: no hay empleados'); ELSE FOR j IN 1..t_emp.LAST LOOP DBMS_OUTPUT.put_line(t_emp(j).id ||''||t_emp(j).nombre||'--'||t_emp(j).salary); END LOOP; END IF; EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.Put_line ('Error: '|| SQLERRM); END Emps_Ant;
9. Modificar el ejercicio anterior agregando un tercer parmetro para indicar como se quiere mostrar el listado de empleados: ascendente o descendente. cargar en la tabla los empleados ordenados por salario de acuerdo a lo informado en el tercer parmetro: a o d recorrer la tabla empezando en el primero o en el ltimo elemento. Si este parmetro no es informado asumir a.

Ejecutar este procedimiento con las distintas opciones: Execute Emps_Ant (1200, 7,a); Execute Emps_Ant (1200, 7); Execute Emps_Ant (1200); 10 empleados que ganan mas de 1600$ y listarlos ordenados en orden descendente.

CREATE OR REPLACE PROCEDURE Emps_Ant (p_sal IN NUMBER,p_n IN NUMBER DEFAULT 10, p_ord IN VARCHAR2 DEFAULT 'a') IS CURSOR c_emp IS SELECT employee_id id, First_name||','||last_name nombre, salary FROM Employee WHERE salary > p_sal ORDER BY salary; TYPE T1 IS TABLE OF c_emp%ROWTYPE INDEX BY BINARY_INTEGER; t_emp T1; i BINARY_INTEGER :=0; BEGIN FOR reg_emp IN c_emp LOOP i := i+1; t_emp(i) := reg_emp; EXIT WHEN c_emp%rowcount = p_n; END LOOP; IF t_emp.FIRST IS NULL THEN DBMS_OUTPUT.Put_line ('Error: no hay empleados'); ELSIF p_ord ='a' THEN FOR j IN 1..t_emp.LAST LOOP DBMS_OUTPUT.put_line(t_emp(j).id ||'-'||t_emp(j).nombre||'--'|| t_emp(j).salary); END LOOP; ELSE FOR j IN REVERSE 1..t_emp.LAST LOOP DBMS_OUTPUT.put_line(t_emp(j).id ||'-'||t_emp(j).nombre||'--'|| t_emp(j).salary); END LOOP; END IF; EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.Put_line ('Error: '|| SQLERRM); END Emps_Ant;
10. Crear una funcin Iva que reciba una valor y devuelva el mismo aplicndole el 21%. Usar esta funcin para desplegar los datos de las ordenes de venta (Sales_order), mostrar todas las columnas ms una columna que muestre el total de la orden aplicndole el iva.

CREATE OR REPLACE FUNCTION IVA P_num IN NUMBER) RETURN NUMBER IS

BEGIN RETURN ROUND(p_num * 1.21 ,2); END IVA; SELECT order_id, order_date, customer,id, ship_date, total, IVA(total) FROM Sales_order;

Вам также может понравиться