Sie sind auf Seite 1von 13

Ampliacin de Bases de Datos Ingeniera Tcnica en Informtica de Gestin - Curso 2010/2011 PRCTICA 3: Procedimientos, funciones y paquetes

Objetivos Aprender a crear bloques de PL/SQL con nombre Organizacin de funciones y procedimientos en paquetes Aprender a crear paquetes en PL/SQL Aprender a utilizar paquetes y subprogramas

Contenido 1. Introduccin.

Hasta ahora habamos trabajado con bloques annimos. Es decir, bloques de PL/SQL que se compilan cada vez que se ejecutan, no se almacenan en la base de datos y no pueden llamarse directamente desde otros bloques PL/SQL. A partir de esta prctica trabajaremos con bloques nominados, es decir, bloques que no tienen las anteriores restricciones: se pueden almacenar en la base de datos y ejecutarse cuando sea conveniente. 2. Procedimientos

La sintaxis bsica para la creacin de un procedimiento es: CREATE [OR REPLACE] PROCEDURE nombre_procedimiento [ (argumento [ {IN | OUT | IN OUT}] tipo, (argumento [ {IN | OUT | IN OUT}] tipo) ] {IS |AS} cuerpo_procedimiento Para modificar el cdigo de un procedimiento, ste debe eliminarse y volverse a crear. Como sta es una operacin habitual durante la fase de desarrollo del procedimiento, las palabras clave OR REPLACE permiten que esto se realice mediante una nica operacin. Si el procedimiento existe, primero se elimina. Si el procedimiento no exista, entonces se crea. Si el procedimiento existe y las palabras clave OR REPLACE no estn presentes, la instruccin CREATE devuelve el error de Oracle ORA-955: name is already used by an existing object. Esta es una operacin DDL. Por tanto, se realiza un COMMIT implcito antes y despus de la creacin del procedimiento. Puede utilizarse tanto la palabra clave IS como AS, ya que son equivalentes. Veamos un ejemplo: CREATE OR REPLACE PROCEDURE AddNewStudent ( p_FirstName students.first_name%TYPE, p_LastName students.last_name%TYPE, p_Major students.major%TYPE) AS BEGIN INSERT INTO students (ID, first_name, last_name, major, current_credits) VALUES (student_sequence.nextval, p_FirstName, p_LastName, p_Major, 0); END AddNewStudent; Tal y como podemos comprobar, la seccin declarativa del programa aparece entre la palabra clave IS o AS y la palabra clave BEGIN. La seccin ejecutable aparece entre BEGIN y END o EXCEPTION. La seccin de tratamiento de excepciones aparece entre las palabras clave EXCEPTION y END. El nombre del procedimiento puede incluirse opcionalmente despus de la instruccin END. Esta es una prctica comn ya que facilita la lectura del procedimiento y ayuda al compilador.

Ampliacin de Base de datos

Prctica3: Procedimientos, funciones y paquetes

3.

Funciones

La nica diferencia entre una funcin y un procedimiento es que la funcin devuelve un valor. Por lo cual, mientras que la llamada a un procedimiento es una instruccin PL/SQL en si misma, la llamada a una funcin se produce como parte de una expresin. La sintaxis para la creacin de una funcin es la siguiente: CREATE [OR REPLACE] FUNCTION nombre_funcion [ (argumento [ {IN | OUT | IN OUT}] tipo, (argumento [ {IN | OUT | IN OUT}] tipo) ] RETURN tipo_retorno {IS |AS} cuerpo_funcin Veamos un ejemplo: FUNCTION sal_ok (salary NUMBER, gradeSal NUMBER) RETURN BOOLEAN IS min_sal max_sal BEGIN SELECT losal, hisal INTO min_sal, max_sal FROM salgrade WHERE grade = gradeSal; RETURN (salary >= min_sal) AND (salary <= max_sal); END sal_ok; Dentro del cuerpo de la funcin, la instruccin RETURN se utiliza para devolver el control, junto con un valor, al entorno que realiz la llamada. Puede haber ms de una instruccin RETURN en una funcin, aunque slo se ejecutar una de ellas. La finalizacin de una funcin sin que se ejecute una instruccin RETURN provoca un error. 4. Eliminacin de procedimientos y funciones salgrade.losal%TYPE; salgrade.hisal%TYPE;

La sintaxis para eliminar un procedimiento es: DROP PROCEDURE nombre_procedimiento; Y la sintaxis para eliminar una funcin es: DROP FUNCTION nombre_funcion; Si el subprograma que estamos intentado borrar no existe, Oracle generar el error ORA-4043: Object does not exist. 5. Parmetros de los subprogramas

Los parmetros de funciones y procedimientos pueden tener tres modos: IN, OUT o IN OUT. Si no se especifica el modo de un parmetro, el valor por defecto es IN. El significado de los distintos modos es el siguiente: IN: parmetro de entrada. Dentro del subprograma, se considera como una constante PL/SQL. Cuando se devuelve el control al entorno en que se produjo la llamada, el parmetro no se modifica. OUT: parmetro de salida. Se ignora cualquier valor que el parmetro pueda tener cuando se produce la llamada al subprograma. Dentro del subprograma, el parmetro se comporta como una variable PL/SQL sin inicializar, por lo que inicialmente tendr valor igual a NULL. Puede leerse dicha variable y escribirse en ella. Cuando el subprograma termina, el parmetro contendr el ltimo valor que se le asign.

Ampliacin de Base de datos

Prctica3: Procedimientos, funciones y paquetes

IN OUT: parmetro de entrada/salida. Este modo es una combinacin de los anteriores. Todo parmetro que se corresponda con un modo OUT o IN OUT debe ser una variable y no puede ser una constante o una expresin. Es decir, debe existir una ubicacin para almacenar el valor que se devuelve. Otro aspecto a tener en cuenta es que en la declaracin de los parmetros de una funcin o procedimiento, no se puede restringir la longitud de los parmetros de tipo CHAR o VARCHAR2, ni la precisin y/o escala de los de tipo NUMBER. Dichas restricciones se tomarn de los parmetros reales usados en las llamadas a esos subprogramas. Sin embargo, si se aceptan parmetros definidos mediante el uso del comando %TYPE. Los parmetros pueden tener adems valores por defecto. Estos valores se incluyen mediante la siguiente sintaxis: nombre_parametro [modo] tipo_parametro [ {:= | DEFAULT} valor inicial] Por ejemplo: CREATE OR REPLACE PROCEDURE AddNewStudent ( p_FirstName students.first_name%TYPE, p_LastName students.last_name%TYPE, p_Major students.major%TYPE DEFAULT Economics) AS BEGIN INSERT INTO students (ID, first_name, last_name, major, current_credits) VALUES (student_sequence.nextval, p_FirstName, p_LastName, p_Major, 0); END AddNewStudent; As, en la llamada a dicho procedimiento podemos obviar ese parmetro: BEGIN AddNewStudent(Simon,Salovitz); END; De todas formas, si se quiere dar otro valor se puede incluir uno nuevo para este tipo de parmetros en las llamadas. 6. Excepciones generadas en los subprogramas

Si ocurre un error dentro de un subprograma, se genera una excepcin. Dicha excepcin puede ser predefinida o definida por el usuario. Si el procedimiento no trata dicho error, se pasa inmediatamente el control al entorno que efectu la llamada. Sin embargo, en este caso, los valores de los parmetros con modo OUT e IN OUT se quedarn con el mismo valor que hubiesen tenido si no se hubiese llamada al subprograma en cuestin.

7.

Qu es un paquete?

Un paquete es una estructura de PL/SQL que permite almacenar juntos varios objetos relacionados. Un paquete tiene dos partes separadas: la especificacin y el cuerpo. Cada una de ellas se almacena independientemente en el diccionario de datos. A diferencia de los procedimientos y funciones, que pueden incluirse localmente en un bloque annimo o almacenarse en la base de datos, los paquetes pueden nicamente ser almacenados. Un paquete es fundamentalmente una seccin declarativa nominada que permite la agrupacin de subprogramas relacionados, como una biblioteca. Cualquier cdigo que pueda incluirse en la parte declarativa de un bloque puede incluirse en un paquete, incluidos procedimientos, funciones, cursores, tipos y variables. Una ventaja de agrupar estos objetos en un paquete es la posibilidad de hacer referencia a los mismos desde otros bloques PL/SQL, por lo que los paquetes tambin proporcionan un medio de utilizacin de variables globales en PL/SQL.

Ampliacin de Base de datos

Prctica3: Procedimientos, funciones y paquetes

8.

Especificacin de paquetes

La especificacin del paquete (o cabecera del paquete) incluye informacin acerca del contenido del mismo, sin contener cdigo para ninguno de los subprogramas. La sintaxis general de creacin de cabeceras de paquete es:

CREATE [OR REPLACE] PACKAGE <pkgName> {IS | AS} -- Declaraciones de tipos y registros {[TYPE <TypeName> IS <Datatype>;]} -- Declaraciones de variables, constantes y cursores -- Tambin podemos declarar cursores {[<ConstantName> CONSTANT <Datatype> := <valor>;]} {[<VariableName> <Datatype>;]} -- Declaraciones de las cabeceres de procedimientos y funciones {[FUNCTION <FunctionName>(<Parameter> <Datatype>,...) RETURN <Datatype>;]} {[PROCEDURE <ProcedureName>(<Parameter> <Datatype>, ...);]} END <pkgName>;

Las reglas sintcticas para la cabecera de un paquete son las mismas que para la seccin declarativa, excepto en el caso de declaraciones de procedimientos y funciones. Puede utilizarse tanto la palabra clave IS como AS, ya que son equivalentes. Veamos un ejemplo: CREATE OR REPLACE PACKAGE ClassPackage AS -- Aadir un nuevo alumno al curso especificado. PROCEDURE AddStudent(p_StudentID IN students.id%TYPE, p_Department IN classes.department%TYPE, p_Course IN classes.course%TYPE); -- Elimina el alumno especificado del curso especificado. PROCEDURE RemoveStudent(p_StudentID IN students.id%TYPE, p_Department IN classes.department%TYPE, p_Course IN classes.course%TYPE); -- Excepcin generada por RemoveStudent. e_StudentNotRegistered EXCEPTION; -- Tipo de la tabla utilizada para el almacenamiento de la informacin -- sobre los alumnos. TYPE t_StudentIDTable IS TABLE OF students.id%TYPE INDEX BY BINARY_INTEGER; -- Devuelve una tabla PL/SQL que contiene a los alumnos actualmente -- matriculados en el curso especificado. PROCEDURE ClassList(p_Department IN classes.department%TYPE, p_Course IN classes.course%TYPE, p_IDs OUT t_StudentIDTable, p_NumStudents IN OUT BINARY_INTEGER); END ClassPackage;

El paquete ClassPackage contiene tres procedimientos, un tipo y una excepcin. La cabecera es similar a una interfaz en Java.

Ampliacin de Base de datos

Prctica3: Procedimientos, funciones y paquetes

9.

Cuerpo del paquete

El cuerpo del paquete es un objeto independiente de la cabecera del paquete en el diccionario de datos. El cuerpo del paquete no puede compilarse hasta que la cabecera del paquete se haya compilado correctamente. El cuerpo contiene el cdigo correspondiente a las declaraciones formales de los subprogramas que aparecen en la cabecera del paquete. Tambin puede incluir declaraciones adicionales, que son globales, con respecto al cuerpo del paquete pero que no son visibles en la especificacin. La sintaxis general para crear el cuerpo de un paquete es muy parecida a la de la especificacin, tan solo se aade la palabra clave BODY, y se implementa el cdigo de los subprogramas. CREATE [OR REPLACE] PACKAGE BODY <pkgName> {IS | AS} -- Declaraciones de tipos y registros {[TYPE <TypeName> IS <Datatype>;]} -- Declaraciones de variables y constantes -- Tambin podemos declarar cursores {[<ConstantName> CONSTANT <Datatype> := <valor>;]} {[<VariableName> <Datatype>;]} -- Implementacion de procedimientos y funciones FUNCTION <FunctionName>(<Parameter> <Datatype>,...) RETURN <Datatype> {IS | AS} -- Variables locales de la funcion BEGIN -- Implementeacion de la funcion return(<Result>); [EXCEPTION] -- Control de excepciones END; PROCEDURE <ProcedureName>(<Parameter> <Datatype>, ...) { IS | AS} -- Variables locales de la funcion BEGIN -- Implementacion de procedimiento [EXCEPTION] -- Control de excepciones END; END <pkgName>;

El siguiente ejemplo muestra el cuerpo del paquete ClassPackage: CREATE OR REPLACE PACKAGE BODY ClassPackage AS -- Aadir un nuevo alumno al curso especificado. PROCEDURE AddStudent(p_StudentID IN students.id%TYPE, p_Department IN classes.department%TYPE, p_Course IN classes.course%TYPE) IS BEGIN INSERT INTO registered_students (student_id, department, course) VALUES (p_StudentID, p_Department, p_Course); END AddStudent; -- Elimina el alumno especificado del curso especificado.

Ampliacin de Base de datos

Prctica3: Procedimientos, funciones y paquetes

PROCEDURE RemoveStudent(p_StudentID IN students.id%TYPE, p_Department IN classes.department%TYPE, p_Course IN classes.course%TYPE) IS BEGIN DELETE FROM registered_students WHERE student_id = p_StudentID AND department = p_Department AND course = p_Course; -- Comprobar si la operacin DELETE fue satisfactoria. Si no elimin -- ninguna fila, generar un error. IF SQL%NOTFOUND THEN RAISE e_StudentNotRegistered; END IF; END RemoveStudent; -- Devuelve una tabla PL/SQL que contiene a los alumnos actualmente -- matriculados en el curso especificado. PROCEDURE ClassList(p_Department IN classes.department%TYPE, p_Course IN classes.course%TYPE, p_IDs OUT t_StudentIDTable, p_NumStudents IN OUT BINARY_INTEGER) IS v_StudentID registered_students.student_id%TYPE; -- Cursor local para extraer los alumnos matriculados. CURSOR c_RegisteredStudents IS SELECT student_id FROM registered_students WHERE department = p_Department AND course = p_Course; BEGIN /* p_NumStudents ser el ndice de la tabla. Empezar en la posicin * 0, y se incrementar en cada pasada del bucle de extraccin. * Al final del bucle, contendr el nmero de filas extradas y, * por tanto, el nmero de filas que se devuelven en p_IDs. */ p_NumStudents := 0; OPEN c_RegisteredStudents; LOOP FETCH c_RegisteredStudents INTO v_StudentID; EXIT WHEN c_RegisteredStudents%NOTFOUND; p_NumStudents := p_NumStudents + 1; p_IDs(p_NumStudents) := v_StudentID; END LOOP; END ClassList; END ClassPackage; El cuerpo del paquete contiene el cdigo de las declaraciones formales que figuran en la cabecera, y tambin puede contener variables, cursores, tipos o subprogramas adicionales. En el cuerpo del paquete puede hacerse referencia directamente a objetos de la cabecera que no sean declaraciones formales (como la excepcin e_StudenNotRegistered). Cualquier declaracin formal en la cabecera del paquete debe tener su cuerpo correspondiente en el cuerpo del paquete. Esto incluye el nombre de los subprogramas y los nombres y los modos de los parmetros. El cuerpo de un paquete se podra comparar con la implementacin de una clase en Java. El cuerpo del paquete es opcional. Si la cabecera del paquete no contiene procedimientos o funciones, es decir, nicamente contiene declaraciones de variables, cursores, tipos, etc., el cuerpo no es necesario. Esta tcnica es de utilizada para declarar variables globales.

Ampliacin de Base de datos

Prctica3: Procedimientos, funciones y paquetes

10. Paquetes y mbitos Cualquier objeto que se declare en la cabecera del paquete es visible fuera del mismo, es decir, es pblico. Para acceder a dicho objeto hay que preceder su nombre con el nombre del paquete donde se encuentra. Por ejemplo, para acceder al procedimiento RemoveStudent de nuestro paquete de ejemplo, tendramos que utilizar la siguiente nomenclatura: Begin ClassPackage.RemoveStudent(10006,HIS,101); End Dentro del cuerpo del paquete no es necesario utilizar dicha nomenclatura, es decir, se puede hacer referencia a los objetos de la cabecera sin necesidad del nombre del paquete. En conclusin, cualquier objeto declarado en la cabecera tiene un carcter pblico y global. Dentro del cuerpo del paquete podemos encontrarnos declaraciones, definiciones o procedimientos locales, es decir, cuya especificacin no aparece en la cabecera del paquete. Por lo que dichos objetos son de mbito local y por lo tanto de uso privado e interno del cuerpo del paquete. Resumiendo: Un paquete puede contener mtodos privados y pblicos

Todo procedimiento declarado en la Especificacin tiene carcter pblico. Todo procedimiento declarado y desarrollado en el cuerpo tiene carcter privado y es slo visible por los miembros del paquete.

Las variables pueden ser Locales o Globales.


Toda variable definida dentro de un subprograma es local Toda variable definida fuera de un subprograma es global

11. Sobrecarga de subprogramas empaquetados Los procedimientos y funciones dentro de un paquete pueden sobrecargarse, lo que significa que puede haber ms de un procedimiento o funcin con el mismo nombre, pero con diferentes parmetros. Por ejemplo: CREATE OR REPLACE PACKAGE ClassPackage AS -- Aadir un nuevo alumno al curso especificado. PROCEDURE AddStudent(p_StudentID IN students.id%TYPE, p_Department IN classes.department%TYPE, p_Course IN classes.course%TYPE); -- Tambin aade un nuevo alumno dados el nombre y los apellidos, -- en lugar del identificador del alumno. PROCEDURE AddStudent(p_FirstName IN students.first_name%TYPE, p_LastName IN students.last_name%TYPE, p_Department IN classes.department%TYPE, p_Course IN classes.course%TYPE); . La sobrecarga puede ser una tcnica de gran utilidad cuando la misma operacin puede realizarse sobre argumentos de tipos distintos. Sin embargo, la sobrecarga est sujeta a varias restricciones: No se pueden sobrecargar dos subprogramas si sus parmetros difieren nicamente en el nombre o en el modo. Por ejemplo: Procedure OverloadMe(p_TheParameter IN NUMBER); Procedure OverloadMe(p_TheParameter OUT NUMBER); No se pueden sobrecargar dos funciones que nicamente difieren en el tipo del dato que devuelve. Por ejemplo: Function OverloadMeToo RETURN DATE;

Ampliacin de Base de datos

Prctica3: Procedimientos, funciones y paquetes

Function OverloadMeToo RETURN NUMBER; Finalmente, para que una function pueda sobrecargarse, los tipos de los parmetros deben pertenecer a familias diferentes. Por ejemplo, como CHAR y VARCHAR pertenecen a la misma familia, los siguientes procedimientos no pueden sobrecargarse: Procedure OverloadMe(p_TheParameter IN CHAR); Procedure OverloadMe(p_TheParameter OUT VARCHAR);

12. Uso de procedimientos, funciones y paquetes Los subprogramas y los paquetes pueden almacenarse en el diccionario de datos, para posteriormente poder llamarlos desde otro bloque PL/SQL. Cuando un subprograma se crea con CREATE OR REPLACE, se almacena en el diccionario de datos. Adems del cdigo fuente, el subprograma se almacena en su forma compilada, que se conoce como cdigo-p. Cuando se produce una llamada a un subprograma, se lee el cdigo-p de disco si es necesario, y se ejecuta. Existen varias vistas del diccionario de datos que contienen informacin acerca de los subprogramas: user_object: contiene informacin sobre todos los objetos que pertenecen al usuario actual user_source: contiene el cdigo fuente original del objeto user_error: contiene informacin sobre los errores de compilacin Por ejemplo, si tenemos el siguiente procedimiento: CREATE OR REPLACE PROCEDURE Simple AS v_Counter NUMBER; BEGIN v_Counter := 7; END Simple; Despues de la creacin del procedimiento, podemos examinar las vistas con, por ejemplos, las siguientes sentencias SQL: SELECT object_name, object_type, status FROM user_objects WHERE object_name = 'SIMPLE'; SELECT text FROM user_source WHERE name = 'SIMPLE' ORDER BY line; SELECT line, position, text FROM user_errors WHERE name='SIMPLE' ORDER BY sequence; Un subprograma puede ser local o almacenado en la base de datos. Si es local est declarado en la seccin declarativa de un bloque PL/SQL y puede ser usado solo dentro del bloque. Si es almacenado, puede ser utilizado desde cualquier bloque PL/SQL. Se considera por ejemplo el siguiente procedimiento: CREATE OR REPLACE PROCEDURE StoredProc AS /* Declaraciones locales, que incluyen un cursor, una variable y una funcin. */ CURSOR c_AllStudents IS SELECT first_name, last_name FROM students; v_FormattedName VARCHAR2(50); /* Funcin que devuelve el nombre y los apellidos concatenados y separados por un espacio. */ FUNCTION FormatName(p_FirstName IN VARCHAR2, p_LastName IN VARCHAR2) RETURN VARCHAR2 IS BEGIN

Ampliacin de Base de datos

Prctica3: Procedimientos, funciones y paquetes

RETURN p_FirstName || ' ' || p_LastName; END FormatName; -- Comienzo del bloque principal. BEGIN FOR v_StudentRecord IN c_AllStudents LOOP v_FormattedName := FormatName(v_StudentRecord.first_name, v_StudentRecord.last_name); DBMS_OUTPUT.PUT_LINE(v_FormattedName); END LOOP; END StoredProc; El procedimiento anterior tiene una funcin local que solo puede utilizarse dentro del procedimiento StoredProc. Sin embargo StoredProc puede ser utilizado desde cualquier bloque annimo PL/SQL: BEGIN StoredProc; END;

Cualquier subprograma local debe declararse al final de la seccin declarativa. Si se cambiase de posicin FormatName y se situase antes de la declaracin de c_AllStudents, se producira un error de compilacin. Un subprograma se puede declarar anticipadamente. Una declaracin anticipada consta del nombre del procedimiento y de sus parmetros formales y permite la existencia de referencias mutuas entre procedimientos. Las declaraciones anticipadas tambin se utilizan en las cabeceras de los paquetes. La declaracin anticipada de un paquete nos permite hacer referencia a l antes de que se haya especificado.

13. Subprogramas almacenados frente a subprogramas locales Generalmente es preferible utilizar subprogramas almacenados y agruparlos en un paquete. Cuando se desarrolla un subprograma de utilidad, es probable que quieran realizarse llamadas al mismo desde ms de un bloque, para lo cual el programa tiene que estar almacenado en la base de datos. Los nicos procedimientos y funciones que sera preferible declarar locales a un bloque tienden a ser aquellos que son cortos y que nicamente se llaman desde una seccin especfica del programa. 14. Dependencia de los subprogramas Cuando se compila una funcin o procedimiento almacenado, todos los objetos Oracle a los que hace referencia se registran en el diccionario de datos. El procedimiento o funcin depende, directa o indirectamente, de esos objetos. Si alguno de los objetos de los que depende se modifica, por ejemplo, se lleva a cabo una operacin DDL sobre uno de esos objetos, dicho cdigo se volvera invlido. Pongamos un ejemplo, tenemos un procedimiento, AlmostFull, que depende de la tabla CLASSES. A su vez, creamos otro procedimiento, RecordFullClasses, que llama a AlmostFull:

Ampliacin de Base de datos

Prctica3: Procedimientos, funciones y paquetes

CLASSES

AlmostFull

RecordFullClasses

Si se realiza una operacin DDL sobre CLASSES, todos los objetos que dependan de dicha tabla (directa o indirectamente) se invalidarn y aparecern como no compilados. Si un objeto dependiente se invalida, el motor de PL/SQL intentar volver a compilarlo automticamente la prxima vez que se produzca una llamada al mismo.

Bibliografa Oracle 9i: Programacin PL/SQL. OSBORNE MC GRAW-HILL. 2002, capitulo 9 paginas 317-356. Oracle 9i: Programacin PL/SQL. OSBORNE MC GRAW-HILL. 2002, capitulo 10 paginas 357-406.

Experimentos E1. Cree el procedimiento AddNewStudent que aparece como ejemplo en la pgina 1. Compruebe que se ha creado en la base de datos y, posteriormente, implemente un bloque annimo simple que realice la llamada a dicho procedimiento. E2. Almacene en la base de datos el procedimiento incluido en el archivo AddNewStudent.sql, que lanza un mensaje cada vez que es ejecutado y compruebe que sucede. Solucione el problema. E3. Almacene en la base de datos la funcin incluida en el archivo ClassInfo.sql. Dicha funcin, en el esquema STUDENTS, obtiene el nmero actual y mximo de alumnos para un curso solicitado. Posteriormente se calcula el porcentaje de ocupacin. Ejecute la funcin y compruebe resultados. E4. Cree el procedimiento incluido en el fichero ModeTest.sql. Utilizaremos dicho procedimiento para hacer experimentos con los distintos tipos de parmetros. Implemente un bloque annimo para llamar a este procedimiento. Utilizaremos tres variables de tipo NUMBER inicializadas con nmeros e imprimiremos el valor de dichas variables antes y despus de llamar a la funcin. Probar distintos tipos de llamadas. E5. Pruebe a compilar el siguiente procedimiento Qu pasa? Pruebe a llamar a dicho procedimiento con distintos tipos de parmetros. CREATE OR REPLACE PROCEDURE ParameterLength ( p_Parameter1 IN OUT VARCHAR2(10), p_Parameter2 IN OUT NUMBER(3,1)) AS BEGIN p_Parameter1 := 'abcdefghijklm'; p_Parameter2 := 12.3; END ParameterLength; E6. Qu pasara si se intenta crear el siguiente paquete con los siguientes cdigos de cabecera y cuerpo de paquete? CREATE OR REPLACE PACKAGE PackageA AS FUNCTION FunctionA(p_Parameter1 IN NUMBER, p_Parameter2 IN DATE) RETURN VARCHAR2; END PackageA; CREATE OR REPLACE PACKAGE BODY PackageA AS

Ampliacin de Base de datos

10

Prctica3: Procedimientos, funciones y paquetes

FUNCTION FunctionA(p_Parameter1 IN CHAR, p_Parameter2 IN DATE) RETURN VARCHAR2; END PackageA;

E7 Crear el procedimiento del apartado 6, y inspeccionar las vistas para obtener informacin acerca del procedimiento. Introducir un error y ver la lista de errores de compilacin. E8 Escribir el siguiente bloque PL/SQL: DECLARE FUNCTION FormatName(p_FirstName IN VARCHAR2, p_LastName IN VARCHAR2) RETURN VARCHAR2 IS BEGIN RETURN p_FirstName || ' ' || p_LastName; END FormatName; CURSOR c_AllStudents IS SELECT first_name, last_name FROM students; v_FormattedName VARCHAR2(50); -- Comienzo del bloque principal BEGIN NULL; END; Qu pasa? E9 Se considere el siguiente bloque PL/SQL: DECLARE v_TempVal BINARY_INTEGER := 5; -- Procedimiento local A. Observe que el cdigo de A llama al procedimiento B. PROCEDURE A(p_Counter IN OUT BINARY_INTEGER) IS BEGIN DBMS_OUTPUT.PUT_LINE('A(' || p_Counter || ')'); IF p_Counter > 0 THEN B(p_Counter); p_Counter := p_Counter - 1; END IF; END A; -- Procedimiento local B. Observe que el cdigo de B llama al procedimiento A. PROCEDURE B(p_Counter IN OUT BINARY_INTEGER) IS BEGIN DBMS_OUTPUT.PUT_LINE('B(' || p_Counter || ')'); p_Counter := p_Counter - 1; A(p_Counter); END B; BEGIN

Ampliacin de Base de datos

11

Prctica3: Procedimientos, funciones y paquetes

B(v_TempVal); END; El cdigo anterior no puede compilarse, por qu? Cmo se puede resolver el error?

Problemas P1. En la tabla CLASSES del esquema STUDENT est la informacin sobre el nmero actual y el nmero mximo de alumnos que tiene el curso de un determinado departamento. Implemente una funcin que devuelva TRUE si se comprueba que un curso de un departamento especfico est completo hasta el 80% o ms de su capacidad y FALSE en caso contrario. Implemente un bloque annimo que llame a dicha funcin para cada curso y departamento de la tabla CLASSES mostrando por pantalla un informe escrito para cada caso. Para probar estos programas es necesario que modifique algunos valores de la tabla CLASSES.

P2. Modifique el programa anterior para elevar una excepcin si la ocupacin es menor del 50%. Trate dicha excepcin en el bloque annimo.

P3. Basado en el esquema SCOTT, implemente un procedimiento que aumente el salario de un determinado empleado E en una cantidad C + la comisin del propio empleado. Si la comisin del empleado es NULL, se elevar una excepcin: comm missing. Implemente un bloque annimo que aplique dicho procedimiento a todos los empleados cuyo departamento se encuentre situado en New York o en Dallas y perciban un salario de grado 1. Habr que gestionar todas las posibles excepciones correctamente.

P4. Basado en el esquema SCOTT, implemente un paquete que contenga un procedimiento pblico y una funcin privada. El procedimiento aceptar un parmetro numrico, y devolver un mensaje para decir si el parmetro pasado es menor que el sueldo mximo de los empleados o si es mayor. La comprobacin de si el parmetro pasado es mayor o menor del sueldo mximo se har en la funcin privada.

P5 Basado en el esquema SCOTT, implementar un paquete que implemente las funcionalidades necesarias para contratar y despedir empleados. Comprobar el funcionamiento del paquete. Introducir sobrecarga de los procedimientos o funciones. Por ejemplo, que haya varias maneras de dar de alta a un empleado.

P6. Comprobar el estado de los paquetes creados en los problemas anteriores

Ampliacin de problemas AP1 Crear la tabla JOBS con los siguientes campos: JOB VARCHAR2(9) PK MIN_SALARY NUMBER(7,2) MAX_SALARY NUMBER(7,2) AP2. Implemente un procedimiento llamado ADD_JOB que inserte un nuevo registro en la tabla JOBS. El nombre del trabajo ser proporcionado mediante un parmetro. Detecte la excepcin generada cuando se intenta violar la clave principal de la tabla. AP3. Implemente un procedimiento llamado UPD_JOB que modifique un trabajo dado, aadindole un salario mximo y un salario mnimo. Detecte la excepcin generada cuando se intenta modificar un trabajo que no existe. AP4. Implemente un procedimiento llamado DEL_JOB que borre un trabajo determinado de la tabla JOBS. Se ha de detectar la excepcin generada cuando se intenta borrar un trabajo que no existe.

Ampliacin de Base de datos

12

Prctica3: Procedimientos, funciones y paquetes

AP5. Cree un bloque annimo que lleve a cabo las siguientes tareas utilizando los procedimientos anteriores: 1) Guardar en la tabla JOBS todos los empleos distintos detectados en la tabla emp del esquema SCOTT 2) Actualizar cada empleo de la tabla JOBS con los sueldos mximos y mnimos de sus empleados 3) Borrar aquellos empleos de JOBS cuyo salario mnimo est por debajo de los 1000 euros. 4) Gestionar todas las excepciones necesarias AP6. Cree una funcin que calcule la comisin de un determinado empleado dado su salario. La funcin devolver la comisin calculada y el nuevo salario (suma del sal + nueva comisin). Si el sueldo de un empleado es inferior a 1000 euros, la comisin ser del 10%. Si el sueldo est entre 1000 y 1500 euros, la comisin ser del 15%. Finalmente, si el salario es mayor que 1500, la comisin ascender al 20%. En el caso en el que el salario sea nulo, la comisin calculada ser cero. Pruebe dicha funcin con un bloque annimo que calcule la comisin a aquellos empleados que pertenezcan al departamento de desarrollo (RESEARCH) y que hayan sido dados de alta en la empresa durante los aos 1980 y 1981. Controle todas las excepciones que considere necesarias. AP7. Implemente un procedimiento llamado NEW_EMP, para insertar un nuevo empleado en la tabla de empleados. Dicho procedimiento tendr una llamada a una funcin, VALID_DEPTID, la cual comprobar si el ID de departamento del nuevo empleado que se quiere insertar existe o no realmente. A la hora de insertar el empleado se utilizarn valores por defecto en la mayora de parmetros: la comisin ser 0, el salario por defecto es 1000 y el trabajo ser STUDENT, aunque esos valores pueden ser sustituidos a la hora de llamar al procedimiento. Para el nmero de empleado habr que crear previamente y, utilizar posteriormente, una secuencia Oracle. Una secuencia Oracle es un objeto de base de datos que nos va a proporcionar una secuencia de nmeros desde un mnimo hasta un mximo. La sintaxis para crear dicha secuencia es: CREATE SEQUENCE nombre_secuencia INCREMENT BY 1 START WITH valor_inicial Para determinar valor_inicial se tendr que calcular el nmero de empleado mayor que existe en la actualidad y sumarle 1. Cada vez que usemos esta secuencia (nombre_secuencia.NextVal) nos devolver un valor distinto de la secuencia incrementado en 1 con respecto al ltimo valor consultado. Finalmente, no se olvide de gestionar todas las excepciones que sean necesarias. AP8 Consulte el estado de todos los subprogramas relativos a las ampliaciones de problemas de la prctica anterior utilizando las vistas predeterminadas AP9 Organice todos los subprogramas relativos a los problemas de la practica anterior en paquetes. AP10 Compruebe el funcionamiento de todos los paquetes creados desde bloque annimos PL/SQL. AP11 Basado en el esquema ACADEMIA, implementar un paquete para gestionar las operaciones relativas a los estudiantes, como matriculacin, cancelacin, modificacin de datos, informes varios etc. AP12 Basado en el esquema ACADEMIA, implementar un paquete para gestionar las operaciones relativas a los profesores (consultas, insercin, borrado y modificacin).

Ampliacin de Base de datos

13

Das könnte Ihnen auch gefallen