PLSQL
PLSQL
TRASSIERRA
Crdoba
http://www.iestrassierra.com
Departamento de Informtica
APUNTES DE PL/SQL
Etapa: Formacin Profesional Especfica.
Ciclo: Desarrollo de Aplicaciones Informticas.
Nivel: Superior.
Mdulo: Desarrollo de Aplicaciones en Lenguajes de 4 Generacin y
con Herramientas CASE.
Profesor: Juan Carlos Prez Jorge [email protected]
INDICE:
Tema 1.- PL/SQL ................................................................................................ 1
Tema 2.- Disparadores (Triggers) ................................................................. 28
Tema 3.- Procedimientos, Funciones y Paquetes .......................................... 39
I.E.S. TRASSIERRA - Crdoba PL/SQL
1.1.- INTRODUCCIN.-
PL/SQL es un lenguaje de programacin procedural estructurado en bloques que ampla el
lenguaje estndar SQL, uniendo la potencia de ste, con la capacidad de los lenguajes de
programacin tradicionales. De esta forma, PL/SQL no slo nos permite manipular los datos
de la base de datos ORACLE, sino que dispone de tcnicas procedurales como los bucles o el
control condicional.
Una de las mayores limitaciones del SQL es la imposibilidad de tratar de forma independiente
las filas devueltas por una consulta. Esto se consigue con PL/SQL mediante el uso de cursores
que ORACLE abre para ejecutar una sentencia SELECT.
Tambin nos permite controlar los errores que se pudieran producir (excepciones), como por
ejemplo que una consulta no devuelva filas. Existen errores propios de Oracle (excepciones
predefinidas) y errores que puede provocar y definir el usuario.
Por extensin al SQL, PL/SQL puede acceder a la base de Datos ORACLE porque soporta:
Portabilidad.
Las aplicaciones escritas con PL/SQL son portables a cualquier sistema operativo y
plataforma en la cual se encuentre corriendo Oracle. En otras palabras, PL/SQL corre
dondequiera que se encuentre corriendo Oracle. Esto significa que se pueden codificar
libreras que podrn ser reutilizadas en otros entornos.
Seguridad.
Los procedimientos almacenados habilitan la divisin lgica entre cliente y servidor,
de forma que se previene que se manipulen los datos desde el cliente. Adems permite
a los usuarios ejecutar solo aquellos procedimientos para los cuales tengan privilegios.
1
Informacin adjuntada a un aviso de la red para garantizar un envo correcto al destino
DECLARE DECLARE
..........
Declaracin de variables y ctes ; BEGIN
Declaracin de cursores ; ....
Declaracin de excepciones ; DECLARE
BEGIN
BEGIN ....
Sentencias ejecutables ; EXCEPTION
....
EXCEPTION END ;
Control de excepciones ; .....
EXCEPTION
END ; ............
END ;
Los bloques PL/SQL se pueden anidar tanto en la zona BEGIN como en la EXCEPTION,
pero no en la zona DECLARE, que es nica para cada bloque. Cada bloque debe acabar con
el carcter '/' como nico de la ltima lnea.
DEC
Nmeros con punto fijo con precisin mxima de 38
DECIMAL
dgitos decimales
NUMERIC
DOUBLE
Nmeros con punto flotante con precisin mxima de
PRECISION
38 dgitos decimales
FLOAT
REAL Nmeros con punto flotante con precisin mxima de
18 dgitos decimales
INTEGER
Nmeros enteros con una precisin mxima de 38
INT
dgitos
SMALLINT
NATURAL No negativo.
NATURALN No negativo, no admite nulos.
POSITIVE Positivo.
POSITIVEN Positivo, no admite nulos.
SIGNTYPE -1, 0 y 1, usado en lgica trivaluada.
Bolanos.- solo pueden tomar 3 valores TRUE, FALSE y NULL. Usados para lgica
trivaluada.
1.3.2.- Conversiones.-
Adems de las conversiones de tipo de datos realizadas explcitamente por las funciones de
conversin, cuando se hace necesario, PL/SQL puede convertir un tipo de dato a otro en
forma implcita. Esto significa que la interpretacin que se dar a algn dato ser la que mejor
se adecue dependiendo del contexto en que se encuentre, por ejemplo cuando variables de tipo
char se operan matemticamente para obtener un resultado numrico.
Si PL/SQL no puede decidir a qu tipos de dato de destino puede convertir una variable se
generar un error de compilacin.
Hasta BIN_INT CHAR DATE LONG NUMBER PLS_INT RAW ROWID VARCHAR2
Desde
BIN_INT X X X X X
CHAR X X X X X X X X
DATE X X X
LONG X X X
NUMBER X X X X X
PLS_INT X X X X X
RAW X X X
ROWID X X
VARCHAR2 X X X X X X X X
Puede observarse que la variable ms externa tiene un mbito ms amplio pero cuando es
referenciada en el bloque en que se ha declarado otra variable con el mismo nombre, es esta
ltima la que puede ser manipulada y no la primera.
Sintaxis: DECLARE
declaracin_variables;
declaracin_cursores;
declaracin_excepciones;
Las variables se utilizan para guardar valores devueltos por una consulta o almacenar clculos
intermedios. Las constantes son campos que se definen y no alteran su valor durante el
proceso.
Sintaxis:
nombre_campo [CONSTANT] <tipo_de_dato /
identificador% TYPE /
identificador% ROWTYPE>
[NOT NULL]
[:= <expresin_plsql / valor_constante>];
dnde:
Ejemplos:
n_dept tdepto.numde%TYPE ;
total number(10,2):=0 ;
respuesta char(1) ;
var2 var1%TYPE ;
registro1 scott.dept%ROWTYPE ;
Los registros son grupos de variables que pueden recibir la informacin de un cursor. Se
declaran segn la siguiente sintaxis:
Ejemplo:
Tipos de cursores:
Esttico simple
Esttico parametrizado
Los cursores estticos parametrizados permiten obtener con el mismo cursor diferentes
resultados en funcin del valor que se le pase al parmetro. Su sintaxis es:
Ejemplo:
ACCEPT valor PROMPT Departamento:
DECLARE
CURSOR empleados (dept_pl NUMBER) IS
SELECT emp.emp_no, emp.ename
FROM emp
WHERE emp.dept_no = dept_pl ;
..........
BEGIN
OPEN empleados (&valor) ; -- Apertura del cursor y paso del parmetro
Si en cualquier cursor quisiramos modificar las filas que nos devuelve, deberamos
aadir a la Select asociada al cursor la clusula:
Ejemplo:
DECLARE
CURSOR empleados IS
SELECT emp_no, ename FROM emp FOR UPDATE OF ename ;
Dinmico no prefijado
Ejemplo:
DECLARE
TYPE CurEmp IS REF CURSOR -- Declaracin del tipo de cursor
....
C_emple1 CurEmp ; -- Declaracin de un cursor del tipo anterior
Dinmico prefijado
Los cursores dinmicos prefijados declaran el registro que va a recibir los datos del
cursor con RETURN <tipo_registro>.
Ejemplo:
DECLARE
TYPE Datos IS REF CURSOR
RETURN emp%ROWTYPE ;
....
Datos.emp Datos ;
Sintaxis:
nombre_excepcin EXCEPTION ;
El tratamiento de las excepciones, tanto las internas de Oracle como las de usuario, se realiza
en la zona EXCEPTION, y lo veremos en el apartado 1.6.
Asignaciones
Manejo de cursores
EXIT
Control condicional
Bucles
GOTO
NULL
salario := 2251 ;
comision := substr(cod_postal,2 ,3) ;
aumento := salario * 0.1 ;
total_sueldo := salario + aumento + comision ;
1.5.1.2.- Manejo de Cursores.- Los cursores que vayan a utilizarse debern haber sido
definidos en la zona DECLARE.
Para poder realizar una lectura de todas las filas recuperadas en un cursor, es necesario
realizar un bucle. Existen bucles ya predefinidos para recorrer cursores, aunque tambin se
pueden utilizar bucles simples y hacer el recorrido de forma ms controlada.
Para el manejo de los cursores, podemos utilizar los siguientes atributos predefinidos:
%NOTFOUND Devuelve TRUE si la ltima lectura falla porque no hay mas filas
disponibles o FALSE si recupera una fila. Se utiliza para detectar el
final y romper el bucle de lectura de un cursor.
%FOUND Es lo contrario de %NOTFOUND
%ROWCOUNT Devuelve el nmero de fila, procesada por el cursor.
%ISOPEN Devuelve TRUE si el cursor esta abierto y FALSE si esta cerrado.
Para manejar un cursor primero hay que abrirlo (OPEN), luego leerlo (FETCH) y por ltimo
cerrarlo (CLOSE).
DECLARE
CURSOR departamentos (dept_pl NUMBER, loc_pl CHAR) IS
SELECT dept_no, dname, loc
FROM dept
WHERE dept_no = dept_pl and loc = loc_pl ;
BEGIN
OPEN departamentos (10, 'MADRID') ;
OPEN departamentos (v_dept, v_loc) ;
OPEN departamentos (loc_pl => 'MADRID', dept_pl => 10) ;
OPEN departamentos (loc_pl => v_loc, dept_pl => v_dept) ;
Leer el Cursor: FETCH. La sentencia FETCH, recupera la siguiente fila del cursor hasta
detectar el final. Los datos recuperados deben almacenarse en variables o registros.
Todas las variables que aparecen en la clusula INTO deben haber sido definidas
previamente en la zona de declaracin de variables DECLARE.
En la zona BEGIN, y mientras el cursor est abierto, las columnas del cursor pueden
utilizarse haciendo referencia al nombre del registro, del que son variables miembro. En
el supuesto del prrafo anterior, y caso de que la select asociada al cursor tenga
columnas con expresiones distintas a nombres de columna (SUM(salar), por ejemplo),
debern usarse alias de columna, por cuyo nombre sern referenciadas.
Ejemplo:
DECLARE
CURSOR curdep IS
SELECT numde, nomde, presu FROM tdepto ;
reg_dept curdep%ROWTYPE ;
BEGIN
FETCH curdep INTO reg_dept ;
IF reg_dep.numde < 150 THEN ...
Cerrar el Cursor: CLOSE. La sentencia CLOSE cierra el cursor. Una vez cerrado no se
puede volver a leer (FETCH), pero si se puede volver a abrir. Cualquier operacin que se
intenta realizar con un cursor que esta cerrado, provoca la excepcin predefinida
INVALID_CURSOR. Su sintaxis es:
CLOSE nombre_cursor ;
1.5.1.3.- EXIT.-
EXIT nos permite salir de un bucle de forma radical o evaluando una condicin. Su sintaxis
es:
EXIT [nombre_bucle] [WHEN condicin] ;
Si se omite el nombre del bucle sale del bucle actual. Si se especifica WHEN, solo sale si se
cumple la condicin. Si se omiten ambos, sale del bucle actual incondicionalmente.
Al procesar la sentencia, se evalan una a una todas las condiciones por orden empezando por
la que le sigue a la palabra IF. Si alguna de las condiciones se cumple, se ejecutan las
sentencias especificadas y se pasa a la siguiente instruccin tras END IF .
Si no se cumple ninguna condicin, pero existe un ELSE, se ejecutan las sentencias siguientes
al ELSE, si no es as, no se ejecuta ninguna sentencia.
Bucles bsicos
Bucles condicionales (WHILE)
Bucles numricos (FOR)
Bucles sobre cursores
Bucles para una SELECT
LOOP
sentencias ;
END LOOP ;
Ejemplo:
LOOP
FETCH cursor_cl INTO registro ;
EXIT WHEN cursor_cl%NOTFOUND ;
END LOOP ;
WHILE condicin
LOOP
sentencias;
END LOOP;
Ejemplo:
WHILE a>0
LOOP
a := a - 1 ;
END LOOP ;
Bucles Numricos (FOR). Son bucles que se ejecutan una vez para cada elemento
definido dentro del rango numrico. Su sintaxis es:
Ejemplo:
FOR x IN 1 .. 10
LOOP
valor:= valor + x ;
END LOOP ;
Bucles sobre Cursores. Son bucles que se ejecutan para cada fila que recupera el cursor.
Cuando se inicia un bucle sobre un cursor automticamente se realizan los siguientes
pasos:
Sintaxis:
FOR nombre_registro IN nombre_cursor
LOOP
Sentencias ;
END LOOP ;
Si se sale del bucle prematuramente (p.e. con un EXIT), o se detecta un error (excepcin),
el cursor se cierra.
Ejemplo:
DECLARE
CURSOR curdep IS
SELECT numde, nomde FROM tdepto;
reg_dept curdep%ROWTYPE ; -- (*)
BEGIN
FOR reg_dept IN curdep
LOOP
......;
END LOOP;
(*) Esta sentencia sobra, pues es declarada implcitamente por este tipo de bucle.
Bucles para Sentencias SELECT. Es el mismo concepto que el del cursor, excepto que
en vez de declarar un cursor con su SELECT, se escribe directamente la sentencia
SELECT y Oracle utiliza un cursor interno para hacer la declaracin.
Sintaxis:
FOR nombre_registro IN sentencia_SELECT
LOOP
sentencias ;
END LOOP ;
Ejemplo:
FOR registro IN SELECT dept_no FROM dept
LOOP
sentencias ;
END LOOP ;
1.5.1.6.- GOTO. Esta sentencia transfiere el control a la sentencia o bloque PL/SQL siguiente
a la etiqueta indicada. Su sintaxis es:
GOTO etiqueta;
GOTO A
.....
<<A>>
La sentencia GOTO puede ir a otra parte del bloque o aun sub-bloque, pero nunca podr ir a
la zona de excepciones. La sentencia siguiente a una etiqueta debe ser ejecutable. En caso de
no existir, por ejemplo por ser el final del programa, se puede utilizar la sentencia NULL.
1.5.1.7.- NULL. Significa inaccin. El nico objeto que tiene es pasar el control a la siguiente
sentencia. Su sintaxis es:
NULL
Ejemplo:
IF tipo = 1 THEN sal := sal * 0.01
ELSE NULL;
END IF;
Oracle abre un cursor implcito (no definido por el usuario) por cada sentencia SQL que tenga
que procesar. PL/SQL nos permite referimos al cursor implcito mas reciente como "SQL%".
Estos cursores los maneja Oracle, por lo que no se pueden abrir, leer o cerrar, pero si podemos
utilizar algunos atributos que nos dan informacin sobre la ejecucin de la sentencia SQL
(INSERT, UPDATE, DELETE, SELECT) para la que se haya abierto. Estos atributos son:
1.5.2.1.- SELECT.
Para poder recuperar valores en variables, la consulta slo debe devolver una fila (no funciona
con predicados de grupo).
Sintaxis:
SELECT {* / col1 [,coI2] } INTO {reg / var1 [,var2] }
FROM tabla resto_de_la_select ;
1.5.2.2.- INSERT.
Se puede realizar el INSERT con valores de las variables PL/SQL o con los datos de una
SELECT. En este caso hay que tener en cuenta que sta ltima no lleva clusula INTO.
En ambos casos el nmero de columnas a insertar deber ser igual al nmero de valores y/o
variables o a las columnas especificadas en la SELECT. En caso de omitir las columnas de la
tabla en la que vamos a insertar, se debern especificar valores para todas las columnas de la
tabla y en el mismo orden en el que esta haya sido creada.
SQL%NOTFOUND es TRUE
SQL%FOUND es FALSE
SQL%ROWCOUNT es 0
Si se dan de alta una o mas filas los atributos devuelven los siguientes valores:
SQL%NOTFOUND es FALSE
SQL%FOUND es TRUE
SQL%ROWCOUNT es nmero de filas insertadas
Ejemplo:
DECLARE
x number(2) := 80;
y char(14) := 'INFORMATICA';
c char(13) := 'MADRID';
BEGIN
INSERT INTO dept (loc, dep_no, dname) VALUES (c, x, y);
x:= 90;
y := 'PERSONAL'
c := 'MALAGA'
1.5.2.3.- UPDATE
La sentencia UPDA TE permite modificar los datos almacenados en las tablas o vistas.
Sintaxis:
UPDATE tabla
SET columna = { sentencia select /
expresin_plsql /
constante /
variable_plsql }
[WHERE { condicin / CURRENT OF nombre_cursor} ] ;
La clusula WHERE CURRENT OF debe ser utilizada despus de haber realizado la lectura
del cursor que debe haber sido definido con la opcin FOR UPDATE OF. Esta clusula no es
admitida en cursores de varias tablas (obtenidos con select con yuncin).
SQL%NOTFOUND es TRUE
SQL %FOUND es FALSE
SQL %ROWCOUNT es 0
Ejemplo:
UPDATE emp
SET sal = sal * 0.1 WHERE dept_no = 10 ;
1.5.2.4.- DELETE.
Sintaxis:
DELETE [ FROM] tabla
[ WHERE {condicin / CURRENT OF nombre_cursor} ] ;
Al igual que con UPDATE, la clusula WHERE CURRENT OF debe ser utilizada despus de
haber ledo el cursor que debe haber sido definido con la opcin FOR UPDATE OF.
SQL%NOTFOUND es TRUE
SQL%FOUND es FALSE
SQL%ROWCOUNT es 0
SQL%NOTFOUND es FALSE
SQL%FOUND es TRUE
SQL%ROWCOUNT es nmero de filas borradas
Ejemplo:
DELETE FROM emp
WHERE dept_no = 10;
Como sabemos, una transaccin o Unidad Lgica de Trabajo (ULT) es una secuencia de
operaciones de actualizacin que forman un todo, de forma que o se ejecutan todas o no se
ejecuta ninguna, debiendo dejar la base de datos en estado coherente.
Una transaccin comienza en la primera sentencia SQL tras: una sentencia COMMIT, una
sentencia ROLLBACK o una conexin a la base de datos.
Una transaccin termina con: una sentencia COMMIT, una sentencia ROLLBACK o una
desconexin, intencionada o no, a la base de datos. El SGBD realiza un COMMIT implcito
antes de ejecutar cualquier sentencia de LDD (create, alter, ..) o al realizar una desconexin
que no haya sido precedida de un error.
Las sentencias SQL que permiten gestionar explcitamente las transacciones son:
o SAVEPOINT
o COMMIT
o ROLLBACK
o SET TRANSACTION READ ONLY
1.5.3.1.- SAVEPOINT.
Los puntos de salvaguarda son marcas que va poniendo el usuario durante la transaccin.
Estas marcas permiten deshacer los cambios por partes en vez de deshacer toda la transaccin.
1.5.3.2.- COMMIT.
Seala el final de una transaccin y el principio de otra indicndole al sistema que se deben
validar los cambios que se produjeron desde el principio de la transaccin que se da por
concluida, hacindolos visibles para los dems usuarios. Su sintaxis es:
COMMIT [WORK] ;
Si se hace el COMMIT cuando tenemos abierto un cursor declarado con la opcin FOR
UPDATE OF, el siguiente FETCH provoca un error, por lo que se debe cerrar el cursor.
1.5.3.3.- ROLLBACK.
Seala el final de una transaccin y el principio de otra indicndole al sistema que se deben
restaurar el estado de la base de datos tal y como estaba al comenzar la transaccin, es decir,
deshace todos los cambios pendientes de validacin de la transaccin actual. Su sintaxis es:
Una vez especificado este comando, las siguientes consultas que se realicen, solo vern los
cambios efectuados antes de que comenzase la transaccin.
Las sentencias del LMD y la desconexin de Oracle llevan implcita una validacin (commit).
Si se produce la cada del sistema o la terminacin anormal de una aplicacin, se llevar a
cabo una restauracin automtica, mediante la consulta al fichero diario o log.
El DBA Studio es una herramienta del Administrador de la Base de Datos, por lo que al abrir
una tabla nos da la visin que de la misma tiene aqul. Si accedemos a una tabla con el DBA
Studio, no apreciaremos los cambios hasta que se cierre la sesin del usuario (nos conectemos
como otro usuario o salgamos de SQL, por ejemplo), o se ejecute el comando COMMIT.
Con las excepciones ser pueden manejar los errores cmodamente sin necesidad de mantener
mltiples chequeos por cada sentencia escrita. Tambin provee claridad en el cdigo ya que
permite mantener las rutinas correspondientes al tratamiento de los errores en forma separada
de la lgica del negocio.
La zona EXCEPTION termina cuando se detecta la palabra reservada END (fin de la zona y
fin del bloque PL/SQL).
La zona EXCEPTION es opcional y se puede omitir. En este caso, si se detecta algn error, el
bloque PL/SQL termina incorrectamente, terminando el proceso y devolviendo el control al
punto de partida.
Existen dos variables para poder recuperar los errores Oracle que se pueden producir:
SQLCODE y SQLERRM.
Otras excepciones.
Sintaxis: DECLARE
A EXCEPTION;
BEGIN
RAISE A;
EXCEPTION
WHEN A THEN .... ;
END;
Ejemplo: DECLARE
error EXCEPTION;
BEGIN
RAISE error;
RAISE TOO_MANY _ROWS;
EXCEPTION
WHEN error THEN ...;
WHEN TOO_MANY _ROWS THEN ... ;
END;
1.6.5.- SQLCODE.-
La funcin SQLCODE nos devuelve el nmero del error que se ha producido. Slo tiene valor
cuando ocurre un error Oracle.
Esta funcin solo se habilita en la zona de Excepciones, ya que es el nico sitio donde se
pueden controlan los errores.
1.6.6.- SQLERRM.-
La funcin SQLERRM devuelve el mensaje del error del valor actual del SQLCODE.
Al igual que SQLCODE, no se puede utilizar directamente, sino que debemos declarar una
variable alfanumrica lo suficientemente grande para contener el mensaje de error.
4.- Ante la inexistencia de cualquier error se manda un mensaje al buffer de salida que
ser visualizado al final del programa:
SET SERVEROUTPUT ON SIZE 5000 -- Parametro de entorno que activa el buffer de salida y le
-- asigna un tamao de 5000 bytes.
DECLARE
cur1 IS ..........
no_existe EXCEPTION ;
BEGIN
OPEN cur1;
FETCH cur1 INTO registro;
IF cur1%NOTFOUND THEN
RAISE no_existe;
END IF;
........
EXCEPTION
WHEN no_existe THEN
DBMS_OUTPUT.PUT_LINE('Empleado inexistente'); -- Envio al buffer del literal
END;
1.7.- EJERCICIOS.-
1.- Programa que haciendo uso de un bucle simple, inserte sucesivamente tuplas con el valor
de un contador entre 1 y 14 en la tabla TEMPORAL, previamente creada y con una sola
columna: NUMERO number(2).
DROP TABLE temporal ;
CREATE TABLE temporal (numero number(2));
DECLARE
i number(2):=1;
BEGIN
LOOP
INSERT INTO temporal VALUES (i);
i:=i+1;
EXIT WHEN i>14;
END LOOP;
END;
/
SELECT * FROM temporal ;
4.- Programa que crea la tabla TEST, con dos nicas columnas numricas de longitud 3: NR1
y NR2. Y posteriormente asigna a NR1 un valor decreciente del 19 hasta el cero, y a NR2 el
valor de un contador creciente de 1 a 20. Y ello con el uso de un bucle de cursor.
DROP TABLE test;
CREATE TABLE test (nr1 NUMBER(3), nr2 NUMBER(3)) ;
BEGIN -- inserta valores en la tabla TEST
FOR i IN 1..20 LOOP
INSERT INTO test values( NULL, i) ;
END LOOP;
COMMIT;
END;
/
DECLARE
x NUMBER(4) := 0;
CURSOR t_cur IS
SELECT * FROM test ORDER BY nr2 desc FOR UPDATE OF nr1;
BEGIN
FOR t_rec IN t_cur LOOP
UPDATE test SET nr1 = x WHERE CURRENT OF t_cur;
x := x + 1;
END LOOP;
COMMIT;
END;
/
SELECT * FROM test ;
SET ECHO OFF;
1.- Codificar el programa PL/SQL que permita aumentar en un 10% el salario de un empleado
cuyo nmero se introduce por teclado.
2.- Modificar el anterior programa para controlar la inexistencia del empleado tecleado, no
haciendo nada, solo evitando que el programa finalice con error.
4.- Codificar el programa PL/SQL que solicite por pantalla un nmero de departamento y
calcule la suma total de los salarios y comisiones de ese departamento. Despus inserte la
tupla correspondiente en la tabla TOTALES, previamente creada con la siguiente estructura:
deptno number(3)
total number(10,2)
Realizar el ejercicio utilizando un bucle simple y tratando el cursor.
5.- Modificar el programa anterior para que en la tabla TOTALES no se inserten los
departamentos inexistentes.
7.- Crear un procedimiento que compruebe que el formato de una fecha es correcto. En caso
contrario guardar el error en la tabla f_error que deber estar creada con la siguiente
estructura:
fecha char(8)
error number
mensaje char(80)
Si se produce otro tipo de error tambin se guardar en la misma tabla.
8.- A partir de las tablas tdepto y temple, realizar los aumentos de sueldo (columna salar)
siguientes:
tdepto.nomde % subida
FINANZAS 10
PERSONAL 20
RESTO 5
Adems, crear la tabla T-DEP, que contendr, por cada departamento, el nmero de
empleados con comisin y sin comisin, y con la siguiente estructura:
deptno number(3)
sin_comm number(3)
con_comm number(3)
9.- Idem al ejercicio anterior, pero si se produce duplicidad de ndices, se acumularn los
valores de empleados con comisin y sin comisin al departamento correspondiente de la
tabla T_DEP, y cualquier otro error se registrar en la tabla errores.
2.1.- DISPARADORES .-
2.1.1.- Concepto.-
La siguiente figura muestra una aplicacin de la base de datos con algunas instrucciones SQL
que implcitamente disparan varios disparadores almacenados en la base de datos.
Base de datos
Aplica Tabla 1 UPDATE TIGGER
Los disparadores se almacenan en la base de datos, separados de las tablas asociadas a ellos.
Slo se pueden definir sobre tablas, y no sobre vistas, sin embargo, los disparadores definidos
sobre la tabla o tablas base de una vista son disparados si se ejecuta sobre la vista una
instruccin INSERT, UPDATE o DELETE.
Para crear un disparador se debe usar ORACLE con la opcin de procedimiento. Antes de
crear un disparador, el usuario SYS debe ejecutar los siguientes script de SQL,
DBMSSTDX.SQL y CATPROC.SQL, que en la versin Personal 8i se encuentran en
C:\ORACLE\ORA81\DRBMS\ADMIN, y son cargados automticamente al iniciar una
sesin.
Tambin es necesario tener uno de los siguientes privilegios CREATE TRIGGER o CREATE
ANY TRIGGER, que permiten a un usuario crear disparadores en una tabla de su esquema, o
bien de cualquier (ANY) esquema.
2.1.2.- Sintaxis.-
Un disparador puede crearse con el DBA Studio o el comando CREATE TRIGGER desde
alguna herramienta interactiva (como SQL*PLUS, SQL*DBA). Su sintaxis es:
bloque_pl/sql
/
DELETE: Indica que se dispara cuando con DELETE se borre una fila de la tabla.
INSERT: Indica que se dispara cuando con INSERT se aada una fila en la tabla.
UPDATE OF: Indica que se dispara el disparador siempre que con UPDATE se
modifique un valor en una de las columnas especificadas en la clusula
OF. Si se omite la clusula OF, el disparador se dispara siempre que una
instruccin UPDATE modifique un valor en alguna columna de la tabla.
FOR EACH ROW: Designa que el disparador ser un disparador fila. ORACLE dispara un
disparador fila una vez por cada fila afectada por el disparador. Si se omite
esta clusula, el disparador ser un disparador instruccin. ORACLE
dispara un disparador instruccin slo una vez cuando la instruccin
disparador se ejecuta.
ADVERTENCIAS:
1.- El comando CREATE TRIGGER debe terminar con una barra oblicua (/).
2.- Crear un disparador cuya sintaxis sea correcta no dando errores al ser compilado, no
significa que sea semnticamente correcto. De hecho, el error ms frecuente en el uso
de disparadores aparece al ejecutarlos y tratar de acceder o referenciar directa o
indirectamente con algn tipo de operacin a la misma tabla que activ el disparador,
cosa que est totalmente prohibida.
Las siguientes vistas del diccionario de datos muestran informacin sobre los disparadores:
- USER_TRIGGERS
- ALL_TRIGGERS
- DBA_TRIGGERS (vase el ejercicio resuelto 1):
En los disparadores de fila, existen dos nombres correlativos, OLD y NEW, para cada
columna de la tabla que se est modificando. Para referenciar a los valores nuevos de la
columna se utiliza el calificador NEW antes del nombre de la columna, y para los valores
antiguos se usa el calificador OLD.
Dependiendo del tipo de instruccin disparador puede suceder que algunos nombres
correlativos no tengan significado:
- Un disparador disparado por una instruccin INSERT tiene acceso solamente a los valores
nuevos de la columna. Los valores viejos son NULL.
- Un disparador disparado por una instruccin UPDATE tiene acceso a los valores viejos y
nuevos de la columna para los disparadores fila BEFORE y AFTER.
- Un disparador disparado por una instruccin DELETE tiene acceso solamente a los
valores viejos de la columna. Los valores nuevos son NULL.
Los nombres correlativos tambin se pueden usar en el predicado de una clusula WHEN.
Cuando los calificadores NEW y OLD se usan en el cuerpo de un disparador (bloque
PL/SQL) deben ir precedidos por dos puntos (:), que no son permitidos cuando se utilizan en
la clusula WHEN o en la opcin REFERENCING OLD...
- Instruccin disparador,
- Restriccin disparador, y
- Accin disparador.
Una instruccin disparador es la instruccin SQL que causa que un disparador sea ejecutado.
Puede ser una instruccin INSERT, UPDATE o DELETE para una tabla especfica. Por
ejemplo, la instruccin disparador:
significa que cuando la columna exis de una fila en la tabla articulos se modifique, se ejecuta
el disparador (se dispara).
Cuando la instruccin disparador es una instruccin UPDATE se puede incluir una lista de
columnas para identificar qu columnas deben ser modificadas para que se dispare el
disparador; como las instrucciones INSERT y DELETE afectan a filas completas de la tabla,
no es necesario especificar una lista de columnas para estas opciones.
Lo que significa que cuando una instruccin INSERT, UPDATE o DELETE se ejecuta sobre
la tabla asegurados, se dispara el disparador.
En el siguiente ejemplo se supone que la tabla tdepto tiene una nueva columna: total_sal, con
el total de salarios (no comisiones) de los empleados de ese departamento.
Ntese que si se modifica el departamento de un empleado se cumplen las dos primeras condiciones.
Una restriccin disparador especifica un predicado o condicin que debe ser verdadera para
que el disparador se dispare. La accin disparador no se ejecuta en caso contrario.
La restriccin disparador es una opcin disponible para los disparadores fila. Se especifica
utilizando la clusula WHEN.
Una accin disparador es el procedimiento (bloque PL/SQL) que contiene las instrucciones
SQL y el cdigo PL/SQL que se ejecuta cuando una instruccin disparador es ejecutada y la
restriccin disparador (si existe) se evala como verdadera.
Una accin disparador puede contener instrucciones SQL y PL/SQL, puede definir elementos
del lenguaje PL/SQL (variables, constantes, cursores, excepciones, etc.), y puede llamar a
otros procedimientos.
La siguiente tabla describe cada tipo de disparador, sus propiedades y las opciones
utilizadas para crearlos.
- Para obtener valores de columnas especficos antes de ejecutar una instruccin disparador
INSERT o UPDATE.
CREATE TIGGER rt BEFORE UPDATE OR DELETE OR INSERT ON sal FOR EACH ROW
BEGIN
stat.rowent := stat.rowent + 1 ;
END ;
/
BEGlN
IF updating THEN typ :='update' ; END IF ;
IF deleting THEN typ :='delete' ; END IF ;
IF inserting THEN typ :='insert' ; END IF ;
Hour := TRUNC( (SYSDATE- TRUNC( SYSDATE ) )*24 ) ;
UPDATE stat_tab
SET rowent = rowent + stat.rowent
WHERE utype = typ AND uhour = hour;
IF SQL%ROWCOUNT = 0 THEN
INSERT INTO stat_tab VALUES ( typ, stat.rowent, hour );
END IF ;
EXCEPTION
WHEN dup_val_on_index THEN
UPDATE stat_tab
SET rowent = rowent + stat.rowent
WHERE utype = typ AND uhour = hour ;
END ;
/
Para habilitar o inhabilitar disparadores usa el comando ALTER TRIGGER. Su sintaxis es:
Otra forma es con el comando ALTER TABLE con las clusulas DISABLE y ENABLE y la
opcin ALL TRIGGERS de este comando. Ejemplo:
Para habilitar o inhabilitar disparadores utilizando el comando ALTER TABLE, se debe ser el
propietario de la tabla, tener el privilegio de objetos ALTER para la tabla, o tener el privilegio
del sistema ALTER ANY TABLE. Para habilitar o inhabilitar disparadores utilizando el
comando ALTER TRIGGER, se debe ser el propietario del disparador o tener el privilegio del
sistema ALTER ANY TRIGGERS.
Para borrar un disparador se usa el comando DROP TRIGGER, cuya sintaxis es:
Para borrar un disparador, el disparador debe estar en nuestro esquema o debemos tener el
privilegio del sistema DROP ANY TRIGGER.
2.6.-EJERCICIOS.-
1.- Ejemplo de uso de las tablas del diccionario de datos. La siguiente sentencia crea un
disparador llamado DEP_SET_NULL que controla que antes de borrar una fila de la tabla
DEPTo modificar la clave primaria (deptno) de DEPT, se pongan todos los valores
relacionados de la tabla EMP a NULL:
CREATE TRIGGER dep_set_null
AFTER DELETE OR UPDATE OF deptno ON dept FOR EACH ROW
BEGIN
IF DELETING OR UPDATING AND :old.deptno != :new.deptno THEN
UPDATE emp SET emp.deptno = NULL
WHERE emp.deptno = :old.deptno ;
END IF ;
END ;
/
SELECT trigger_body
FROM user_triggers
WHERE trigger_name = 'DEP_SET_NULL' ;
Rdo: TRIGGER_BODY .
BEGIN
IF UPDATING AND :old.deptno != :new.deptno THEN
UPDATE emp SET emp.deptno = NULL
WHERE emp.deptno = :old.deptno ;
END IF ;
END ;
ORACLE dispara el disparador siempre que una instruccin INSERT, UPDATE o DELETE
afecte a la tabla EMP del esquema SCOTT. El disparador realiza las siguientes operaciones:
El/la alumn@ debera mejorar este disparador para que tambin evite las actualizaciones en
los das de fiesta. La validacin se hara consultando una tabla que se actualizara anualmente
y que contendra las fechas de las fiestas (das no laborables), y que deber crear el alumnado.
ORACLE dispara el disparador siempre que se ejecute una de las siguientes instrucciones:
1.- Crear el disparador DEP_SET_NULL en el esquema EMPRESAX, que controle que antes
de borrar una fila de la tabla TDEPTO o modificar la clave primaria (NUMDE) de TDEPTO,
se pongan a NULL todos los valores relacionados de la tabla TEMPLE.
3.- Sobre la tabla TDEPTO del esquema EMPRESAX, codificar el disparador de nombre
TDEPTO_PRESU_SAL que impedir que el presupuesto de un departamento sea inferior a la
suma de los salarios y comisiones de los empleados de ese departamento. Si una actualizacin
intenta violar la anterior restriccin, el disparador devolver el cdigo de error nmero -20112
y el mensaje 'El presupuesto no puede ser inferior a la suma de los sueldos de sus empleados'.
4.- Modificar el disparador VALIDA_SALARIO del ejercicio resuelto n 3 para que vele por
que se cumpla que los salarios de todos los empleados salvo el presidente:
- Que no se borrar ninguna tupla de SAL_GUIDE si hay algn empleado con su salario
comprendido entre sus lmites. En cuyo caso se lanzar el error 20325 y un mensaje
indicativo.
3.1.- Introduccin.
3.2.- Procedimientos.
3.2.1.- Creacin y borrado.
3.2.2.- Tipos de argumentos: in, out, in out.
3.2.3.- Polimorfismo.
3.3.- Funciones.
3.3.1.- Creacin y borrado.
3.3.2.- Recursividad.
3.3.3.- Funciones PL/SQL en sentencias SQL.
3.4.- Paquetes.
3.4.1.- Creacin y borrado.
3.4.2.- La depuracin
3.5.- Ventajas de los procedimientos, funciones y paquetes.
3.6.- Manejo de excepciones.
3.7.- Ejercicios.
3.7.1.- Ejercicios resueltos.
3.7.2.- Ejercicios propuestos.
3.1.- INTRODUCCIN.-
Adems de los disparadores ya vistos, Oracle permite desarrollar subprogramas, es decir,
agrupar una serie de definiciones y sentencias para ejecutarlas bajo un nico nombre, estos
subprogramas son: procedimientos, funciones y paquetes.
Los procedimientos son trozos de cdigo que realizan un trabajo sobre unos argumentos de
entrada que son opcionales y depositan unos valores sobre unos argumentos de salida,
tambin opcionales.
Las funciones son similares a los procedimientos con la diferencia de que devuelven siempre
un valor.
end [nombre_procedimiento] ;
Desarrollar un subprograma para almacenar un bloque PL/SQL en la base de datos es muy til
cuando es necesario ejecutarlo repetidamente. Un subprograma puede invocarse desde
multitud de entornos: SQL *Plus, Oracle Forms, otro subprograma, y desde cualquier otra
herramienta o aplicacin Oracle.
Para crear un procedimiento o funcin hay que seguir los pasos siguientes:
Es importante que los ficheros de texto acaben con una lnea que contenga el carcter
'/' como nico carcter de la columna uno. Por ejemplo (la tabla alumnos debe estar
creada):
La mayora de las aplicaciones Oracle, entre ellas SQLPls, permiten el paso de parmetros
posicionalmente o por asociacin de nombres (de forma similar a la apertura de cursores
parametrizados), incluso de forma mixta.
Supongamos que tenemos las variables v_a de tipo number y v_b de tipo char:
3.2.- PROCEDIMIENTOS.-
Un procedimiento es un subprograma que realiza una accin especfica. Pueden recibir
parmetros pero que no devuelven ningn valor.
Se crea un nuevo procedimiento con la sentencia CREATE PROCEDURE, que declara una
lista de argumentos y define la accin a ejecutar por el bloque PL/SQL estndar.
Sintaxis:
donde:
nombre_proc Es el nombre del procedimiento.
argumento Es el nombre del argumento.
tipo_arg Indica el tipo de argumento: IN (por defecto), OUT o IN OUT.
tipo_dato El tipo de dato del argumento sin precisin.
bloque PL/SQL El cuerpo procedural que define la accin a realizar.
El bloque PL/SQL debe comenzar con la palabra BEGIN o con una declaracin de variable
local. Nunca debe comenzar con DECLARE. Esta diferencia con los bloques PL/SQL
annimos ocurre porque AS (o IS) llevan implcito el DECLARE.
El procedimiento debe finalizar con la palabra END seguida opcionalmente por el nombre del
procedimiento y un punto y coma (;).
El nmero de argumentos y sus tipos de datos deben corresponderse con los de los parmetros
que se le pasan al procedimiento, pero los nombres puede ser diferentes. Esto permite que el
mismo procedimiento pueda invocarse desde diferentes lugares.
Para transferir valores desde y hacia el entorno de llamada a travs de argumentos debemos
escoger entre uno de los tres tipos de argumento: In, Out e In Out.
Tipo Descripcin
IN Se usa para pasar parmetros por valor. El parmetro acta como
constante por lo que no se le puede asignar ni cambiar su valor
dentro del procedimiento. Este parmetro puede referenciarse en la
llamada mediante una constante, variable inicializada o expresin.
Los parmetros pueden declararse para que tomen valores por defecto, veamos como:
Las llamadas vlidas que podemos hacer a este procedimiento son las siguientes:
EXECUTE prueba(v2=>8);
Argumentos IN
Almacenar informacin acerca de un nuevo empleado:
IS
BEGIN
INSERT INTO temple
VALUES (v_emp_numero, v_emp_departa, v_emp_telefono, v_emp_fechanac,
v_emp_fechaing, v_emp_salario, v_emp_comision, v_emp_hijos, v_emp_nombre) ;
COMMIT WORK ;
END alta_emp ;
/
Recordemos que la orden show errors es muy til para depurar el cdigo. Si todo va bien nos
aparecer el mensaje de Procedimiento creado. Ahora para ejecutarlo debemos escribir la
sentencia execute, por ejemplo:
EXECUTE alta_emp(555, 111, 780, '24/06/1979', sysdate, 777, null, 3, 'ARGUDO, MANUEL')
lo que provocar la ejecucin del procedimiento y por ende el alta del empleado tecleado.
El siguiente ejemplo elimina los valores de entrada innecesarios en una rutina de altas de
empleados, dejando solo como variables de entrada la informacin esencial:
Argumentos OUT
Recuperar valores desde un procedimiento a el entorno de llamada a travs de argumentos
OUT. En el siguiente ejemplo, recuperar informacin sobre un empleado.
Para invocar a este procedimiento hay que pasarle todos los parmetros, ya sean IN, OUT o
IN OUT. Aunque lo habitual es invocar a un procedimiento desde un bloque PL, el siguiente
ejemplo muestra la forma de invocarlo con argumentos IN y OUT desde el prompt de SQL:
SQL> var x varchar2(50);
SQL> var y number;
SQL> var z number;
SQL> execute consulta_emp(390, :x, :y, :z);
Incluso podramos ver el contenido de las variables OUT modificadas por el procedimiento.
SQL> PRINT :x; .......
Argumentos IN OUT
El siguiente ejemplo transforma una secuencia de nueve dgitos en un numero de telfono.
Recupera valores desde el entorno de trabajo hacia el procedimiento, y devuelve los diferentes
valores posibles desde el procedimiento al entorno de llamada utilizando argumentos IN
OUT.
El valor de un argumento tipo IN OUT debe darlo el procedimiento, bien mediante una
sentencia de asignacin, o bien por mediante una sentencia SELECT .. INTO.
3.2.3.- Polimorfismo.-
Ejemplo:
Estos procedimientos slo difieren en el tipo de dato del primer parmetro. Para efectuar una
llamada a cualquiera de ellos, se puede implementar lo siguiente:
DECLARE
TYPE DateTabTyp IS TABLE OF DATE INDEX BY BINARY_INTEGER;
TYPE RealTabTyp IS TABLE OF REAL INDEX BY BINARY_INTEGER;
hiredate_tab DateTabTyp;
comm_tab RealTabTyp;
indx BINARY_INTEGER;
BEGIN
indx := 50;
initialize(hiredate_tab, indx); -- llama a la primera versin
initialize(comm_tab, indx); -- llama a la segunda versin
...
END;
3.3.- FUNCIONES.-
Las funciones son subprogramas que reciben parmetros y devuelven un nico valor. Desde el
punto de vista estrictamente sintctico, un procedimiento conteniendo un argumento OUT
puede ser reescrito como una funcin, y uno que contenga argumentos OUT mltiples puede
reescribirse como una funcin que devuelva un argumento tipo registro. El como de largo ser
la invocacin de la rutina, es lo que determina que su implementacin se realice mediante un
procedimiento o una funcin.
Lo normal ser que sus argumentos sean de tipo IN. Los de tipo OUT o IN OUT, aunque son
vlidos dentro de las funciones, se utilizan raras veces.
donde los elementos significan lo mismo que en la sentencia CREATE PROCEDURE, salvo:
RETURN tipo_dato que indica el tipo de dato devuelto por la funcin. Este tipo de dato no
puede incluir escala o precisin.
En una funcin puede haber varias sentencias RETURN, con la nica condicin de que al
menos haya una.
IS
v_emp_salario temple.salar%TYPE := 0;
BEGIN
SELECT salar INTO v_emp_salario
FROM temple
WHERE numem = v_emp_numero;
RETURN (v_emp_salario);
END tomar_salario;
/
Al igual que los procedimientos, las funciones pueden invocarse pasndoles los parmetros
con notacin posicional, nominal o mixta, y se les pueden asignar valores por defecto.
3.3.2.- Recursividad.-
Como las funciones devuelven un valor, si queremos llamar a una funcin desde el prompt de
SQL debemos declarar una variable para almacenar dicho valor y posteriormente visualizarlo:
-- Versin recursiva
FUNCTION fib (n POSITIVE) RETURN INTEGER IS
BEGIN
IF (n = 1) OR (n = 2) THEN
RETURN 1;
ELSE
RETURN fib(n 1) + fib(n 2);
END IF;
END fib;
-- Versin iterativa
FUNCTION fib (n POSITIVE) RETURN INTEGER IS
pos1 INTEGER := 1;
pos2 INTEGER := 0;
cum INTEGER;
BEGIN
IF (n = 1) OR (n = 2) THEN
RETURN 1;
ELSE
cum := pos1 + pos2;
FOR i IN 3..n LOOP
pos2 := pos1;
pos1 := cum;
cum := pos1 + pos2;
END LOOP;
RETURN cum;
END IF;
END fib;
La versin recursiva es ms elegante que la iterativa, sin embargo esta ltima es ms eficiente,
corre ms rpido y utiliza menos memoria.
Dentro de una expresin SQL se pueden referenciar funciones definidas por el usuario. Donde
pueda haber una funcin SQL, puede situarse tambin una funcin PL/SQL..
Para invocar una funcin desde una sentencia SQL se debe ser el propietario de la funcin o
tener el privilegio EXECUTE. Las situaciones en que puede invocarse una funcin de
usuario son las siguientes:
NO se puede invocar una funcin PL/SQL desde la clusula CHECK de una vista.
Para poder invocar desde una expresin SQL, una funcin PL/SQL definida por el usuario
debe cumplir ciertos requerimientos bsicos.
Debe ser una funcin almacenada, no una funcin dentro de un Bloque PL/SQL
annimo o un subprograma.
Debe ser una funcin de fila nica y NO una funcin de columna (grupo). Esto ocurre
porque no se puede tomar el valor de todos los datos de una columna como argumento.
Todos los argumentos deben ser del tipo IN. No se admiten los tipos OUT o IN OUT.
Los tipos de datos de los argumentos deben ser tipos de datos internos del Servidor
Oracle, tales como CHAR, DATE o NUMBER, y no tipo PL/SQL como BOOLEAN,
RECORD o TABLE.
El valor resultante de la funcin tambin debe ser un tipo de dato Oracle.
Para ejecutar una sentencia SQL que llama a una funcin almacenada, el servidor Oracle debe
conocer si la funcin provoca efectos colaterales. stos pueden ser cambios en tablas de la
base de datos o en variables pblicas de paquetes (que se declaran en la zona de
especificacin del paquete). Los efectos colaterales pueden aplazar la ejecucin de una
consulta, producir resultados dependientes del orden (por lo tanto indeterminados), o requerir
que el estado del paquete se deba mantener a travs de las sesiones de usuario (lo cual no est
permitido). Por ello, las siguientes restricciones se aplican a funciones almacenadas
invocadas desde expresiones SQL:
Las funciones no pueden modificar datos en las tablas. No pueden ejecutar INSERT,
UPDATE o DELETE.
Slo las funciones locales que se referencian en la lista de la SELECT, en la clusula ,
VALUES de un INSERT o en la clusula SET de un UPDATE pueden actualizar una
variable definida en un paquete.
No pueden actualizar variables dentro de un paquete las funciones referenciadas en las
clusulas CONNECT BY, START WITH, ORDER BY o GROUP BY.
Las funciones remotas no pueden leer, ni escribir el estado de un paquete. Cada vez
que se accede aun enlace de base de datos, se establece una nueva sesin en la base de
datos remota.
Las funciones que leen o escriben en el estado de un paquete no pueden utilizar
paralelismo.
3.4.- PAQUETES.-
Los paquetes son un conjunto de procedimientos, funciones y datos. Un paquete es muy
similar a una librera con la ventaja de que podemos ocultar informacin, ya que se compone
de una parte de declaraciones visibles desde el exterior y una serie de implementaciones a las
que no puede accederse desde fuera sino es a travs del interfaz declarado en la parte pblica.
Las ventajas que ofrecen los paquetes son: modularidad, facilidad en el diseo de
aplicaciones, ocultamiento de la informacin, aaden funcionalidad al sistema, y mejoran el
rendimiento ya que la primera llamada a la librera carga sta en memoria, de forma que las
sucesivas invocaciones se evitan acceder a disco.
Los paquetes se crean con el comando CREATE PACKAGE, cuya sintaxis es:
- Parte de declaraciones:
En la cabecera del paquete se especifican todos aquellos objetos a los que se puede acceder, y
en el cuerpo del paquete se implementan dichos objetos. En el cuerpo podemos declarar e
implementar cuantos objetos estimemos oportunos teniendo en cuenta que a ellos solo se va a
poder acceder desde el cuerpo del paquete.
El cuerpo del paquete puede incluir opcionalmente una zona de inicializacin (BEGIN...) que
Solo se ejecuta la primera vez que se hace referencia al paquete dentro de una misma sesin.
Ya sabemos que los procedimientos y las funciones se declaran con la palabra reservada
CREATE y se invocan con EXECUTE. Esto es as cuando los creamos desde el prompt de
SQL, pero dentro de un paquete no hay que poner ni CREATE OR REPLACE, ni EXECUTE.
Una vez que tenemos un paquete creado y compilado podemos acceder a los objetos
declarados en la parte visible desde el prompt de SQL o desde otros procedimientos y
funciones; para ello tan solo hay que anteponerle al nombre del procedimiento o funcin el
nombre del paquete que lo contiene separado por un punto.
procedure alta_empleado ( nombre varchar2 , trabajo varchar2, salario number, dpto number) is
begin
insert into empleados values (sec_empleado.nextval, nombre, trabajo, salario, dpto);
end;
Sintaxis:
PRAGMA RESTRICT_REFERENCES ( nombre_func, WNDS
[,WNPS] [RNDS] [,RNPS] ) ;
Donde:
WNDS Indica que la funcin no puede modificar tablas de la base de datos. (Writes No
Database State). En este paquete es obligatoria.
WNPS Hace que la funcin no pueda cambiar los valores de variables de un paquete
pblico. (Writes No Package Status).
RNDS No permite que la funcin pueda consultar ninguna tabla de la base de datos.
(Reads No Database State).
RNPS Indica que la funcin no puede referenciar los valores de las variables de un
paquete pblico. (Reads No Database Status).
Este paquete sirve para alertar a los desarrolladores de aplicaciones con cdigo procedural que
incumplen las restricciones de las funciones PL/SQL dentro de sentencias SQL.
Indica al compilador PL/SQL qu tipo de acciones pueden realizar las funciones. Las
sentencias SQL que incumplan estas reglas producen un error de compilacin.
Ejemplo: Crear una funcin llamada COMP, dentro del paquete FINANZAS. La funcin ser
invocada desde sentencias SOL en bases de datos remotas. Por lo tanto ser necesario indicar
los niveles de depuracin RNPS y WNPS porque las funciones remotas no pueden nunca
escribir o leer el estado del paquete cuando se le invoca desde una sentencia SQL.
FUNCTION comp
(anos IN NUMBER
cant IN NUMBER
porc IN NUMBER) RETURN NUMBER;
BEGIN comp
RETURN cant * POWER((porc/100) +1, anos)
END comp;
END finanzas;
/
La invocacin a una funcin empaquetada se hace de la misma forma que si fuera una
funcin SQL. Por ejemplo, para llamar a la funcin COMP (que se encuentra en el paquete
FINANZAS residente enm la BD de Barcelona) desde una sentencia SELECT, dentro de un
bloque PL/SQL, haramos:
DECLARE
interes NUMBER;
BEGIN
SELECT finanzas.comp@bcn(anos,cant,porc) INTO interes
FROM conta
WHERE no_cuenta = cuenta_id
END;
Como sabemos hay dos tipos de exepciones: las de Oracle y las definidas por el usuario. La
siguiente tabla muestra como conseguir la comunicacin interactiva del error o realizar una
operacin en la base de datos.
Las excepciones de Oracle pueden ser controladas por el usuario con la sentencia
EXCEPTION_INIT ya vista, que permite comunicar el cdigo y el mensaje de error para una
excepcin de Oracle de forma interactiva omitiendo el manejo de excepciones.
*
ERROR en lnea 1:
ORA-01403: no se han encontrado datos
ORA-06512: en "SCOTT.ALTA_EMP", lnea 14
ORA-06512: en lnea 1
BEGIN
DELETE FROM temple WHERE numem = v_emp_numero;
IF SQL%NOTFOUND THEN
RAISE_APPLICATION_ERROR (-20300, 'Empleado inexistente');
END IF;
END baja_emp;
/
Para direccionar el flujo de programa a una excepcin Oracle no predefinida, invocndola con
la sentencia EXCEPTION_INIT hay que seguir los siguientes pasos:
- Declarar la excepcin.
- Asociar la excepcin declarada con un nmero de error Oracle utilizando la sentencia
EXCEPTION_INIT.
*
ERROR en lnea 1:
ORA-20291: Jefe 9999 no es empleado
ORA-06512: en "SCOTT.ALTA_EMP", lnea 20
ORA-06512: en lnea 1
3.7.- EJERCICIOS.-
3.7.1.- Ejercicios resueltos.-
Tras la escritura del paquete, podemos escribir subprogramas que hagan referencia a los tipos
que declara, a su cursor y a su excepcin, por que el paquete se almacena en la base de datos
para uso pblico.
CREATE PACKAGE emp_actions AS
/* Declaracin de subprogramas. */
FUNCTION hire_employee ( ename VARCHAR2,
job VARCHAR2,
mgr REAL,
sal REAL,
comm REAL,
deptno REAL) RETURN INT;
PROCEDURE fire_employee (emp_id INT);
PROCEDURE raise_salary (emp_id INT, grade INT, amount REAL);
FUNCTION nth_highest_salary (n INT) RETURN EmpRecTyp;
END emp_actions;
/
Este paquete no tiene ningn cuerpo, porque los registros, variables, constantes y excepciones
no tienen ninguna implementacin especial. Se definen variables globales -utilizables por
subprogramas y disparadores de bases de datos- que persistirn durante toda la sesin.
1.- Crear el procedimiento ALTA_DEP, que permitir dar de alta un nuevo departamento en
la tabla TDEPTO. Por defecto pondr el campo tidir a 'F' y el campo presu a cero.
3.- Crear la funcin SUELDO_DEP, que haciendo uso de la funcin anterior, reciba un
nmero de departamento y devuelva su sueldo total.
5.- Crear el paquete PAQ_EMPLE que recoja todos los procedimientos y funciones
desarrollados:
alta_emp
baja_emp
consulta_emp
sueldo_emp
aumento_salario