0% encontró este documento útil (0 votos)
47 vistas56 páginas

Apuntes sobre PL/SQL en Informática

Este documento contiene apuntes sobre PL/SQL divididos en tres temas. Explica conceptos básicos de PL/SQL como bloques, tipos de datos, declaraciones de variables, y control de excepciones. Incluye ejemplos de código PL/SQL y ejercicios resueltos y propuestos para que los estudiantes practiquen con el lenguaje.
Derechos de autor
© All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
47 vistas56 páginas

Apuntes sobre PL/SQL en Informática

Este documento contiene apuntes sobre PL/SQL divididos en tres temas. Explica conceptos básicos de PL/SQL como bloques, tipos de datos, declaraciones de variables, y control de excepciones. Incluye ejemplos de código PL/SQL y ejercicios resueltos y propuestos para que los estudiantes practiquen con el lenguaje.
Derechos de autor
© All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd

I.E.S.

TRASSIERRA
Crdoba
[Link]

Departamento de Informtica

APUNTES DE PL/SQL
Etapa:

Formacin Profesional Especfica.

Ciclo:

Desarrollo de Aplicaciones Web.

Nivel:

Superior.

Mdulo:

Bases de Datos.

Profesor:

Juan Carlos Prez Jorge

INDICE:
Tema 1.- PL/SQL ................................................................................................ 1
Tema 2.- Procedimientos, Funciones y Paquetes ........................................... 24
Tema 3.- Disparadores (Triggers) ................................................................. 45

I.E.S. TRASSIERRA - Crdoba

PL/SQL

TEMA 1.- PL/SQL.1.1.- Introduccin.


1.2.- El bloque PL/SQL.
1.3.- Tipos de datos, conversiones, mbito y visibilidad.
1.4.- Zona de declaraciones: DECLARE.
1.4.1.- Declaracin de variables y constantes.
1.4.2.- Declaracin de registros.
1.4.3.- Declaracin de cursores.
1.4.4.- Declaracin de excepciones.
1.5.- Zona de proceso: BEGIN.
1.5.1.- Sentencias propias de PL/SQL.
1.5.2.- Sentencias LMD.
1.5.3.- Sentencias transaccionales.
1.6.- Zona de excepciones: EXCEPTION.
1.6.1.- Control de errores.
1.6.2.- Excepciones predefinidas.
1.6.3.- Excepciones definidas por el usuario
1.6.4.- Ejecucin de excepciones: RAISE
1.6.5.- SQLCODE.1.6.6.- SQLERRM.1.6.7.- Algunos ejemplos de tratamiento de excepciones.1.7.- Ejercicios.
1.7.1.- Ejercicios resueltos.
1.7.2.- Ejercicios propuestos.

1.1.- [Link]/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.
El motor PL/SQL se encuentra en el Ncleo de Oracle (RDBMS)

Dep. Informtica

I.E.S. TRASSIERRA - Crdoba

PL/SQL

Por extensin al SQL, PL/SQL puede acceder a la base de Datos ORACLE porque soporta:

Sentencias LMD de SQL (SELECT, INSERT, UPDATE, DELETE)


Sentencias transaccionales (COMMIT, ROLLBACK, SAVEPOINT)
Todas las funciones SQL (numricas, de caracteres, de fechas, de grupos...)
Todos los tipos de predicados (sentencia WHERE)
Las propias sentencias de PL/SQL.

1.2.- EL BLOQUE PL/[Link]/SQL es un lenguaje estructurado en bloques. Un bloque es un conjunto de sentencias


procedurales y SQL. Un bloque PL/SQL consta de tres zonas:
Declaraciones: donde se definen las variables, cursores y excepciones de usuario.
Proceso: donde se escriben todas las sentencias ejecutables.
Excepciones: zona donde se define el control de errores.
DECLARE
Declaracin de variables y ctes ;
Declaracin de cursores ;
Declaracin de excepciones ;
BEGIN
Sentencias ejecutables ;
EXCEPTION
Control de excepciones ;
END ;

DECLARE
..........
BEGIN
....
DECLARE
BEGIN
....
EXCEPTION
....
END ;
.....
EXCEPTION
............
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.
Dep. Informtica

I.E.S. TRASSIERRA - Crdoba

PL/SQL

1.3.- TIPOS DE DATOS, CONVERSIONES, MBITO Y VISIBILIDAD.1.3.1.- Tipos de [Link] constante y variable posee un tipo de dato el cual especifica su forma de
almacenamiento, restricciones y rango de valores vlidos. Con PL/SQL se proveen diferentes
tipos de datos predefinidos. Un tipo escalar no tiene componentes internas. Un tipo
compuesto tiene otras componentes internas que pueden ser manipuladas individualmente. Un
tipo referencia almacena valores, llamados punteros, que designan a otros elementos de
programa. Un tipo lob (large object) especifica la ubicacin de un tipo especial de datos que
se almacenan de manera diferente.
En la siguiente figura se muestran los diferentes tipos de datos predefinidos.

Tipos de datos de PL/SQL


Los distintos tipos de datos escalares o simples son:

NUMRICOS. Binary_integer.- binario con desbordamiento a number. Usado para almacenar enteros
con signo. PL/SQL tiene predefinidos los siguientes subtipos de binary_integer:
NATURAL
NATURALN
POSITIVE
POSITIVEN
SIGNTYPE
Dep. Informtica

No negativo.
No negativo, no admite nulos.
Positivo.
Positivo, no admite nulos.
-1, 0 y 1, usado en lgica trivaluada.

I.E.S. TRASSIERRA - Crdoba

PL/SQL

Number.- Numrico. PL/SQL tiene predefinidos los siguientes subtipos:


DEC
DECIMAL
NUMERIC
DOUBLE
PRECISION
FLOAT
REAL
INTEGER
INT
SMALLINT

Nmeros con punto fijo con precisin mxima de 38 dgitos decimales

Nmeros con punto flotante con precisin mxima de 38 dgitos decimales


Nmeros con punto flotante con precisin mxima de 18 dgitos decimales
Nmeros enteros con una precisin mxima de 38 dgitos

Pls_integer.- binario sin desbordamiento. Es ms actualizado que su equivalente


binary_integer, el cual se mantiene por razones de compatibilidad.

ALFANUMRICOS.

Char(n).- Array de n caracteres, mximo 2000 bytes. Si no especificamos longitud sera 1


Long.- Array de caracteres con un mximo de 32760 bytes
Raw.- Array de bytes con un nmero mximo de 2000
Long raw.- Array de bytes con un mximo de 32760
Varchar2.- Para almacenar cadenas de longitud variable con un mximo de 32760

BOOLEANOS.- Solo pueden tomar 3 valores TRUE, FALSE y NULL. Usados para lgica
trivaluada.

DATE.- Para almacenar datos de tipo fecha.

1.3.2.- [Link] de las conversiones explcitas realizadas por las funciones de conversin, cuando se
hace necesario, PL/SQL puede convertir un tipo de dato a otro de 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
Desde
BIN_INT
CHAR
DATE
LONG
NUMBER
PLS_INT
RAW
ROWID
VARCHAR2

BIN_INT CHAR DATE LONG NUMBER PLS_INT RAW ROWID VARCHAR2


X
X

X
X

X
X
X
X
X
X
X
X

X
X
X

X
X

X
X

X
X
X

X
X

X
X
X
X
X
X
X
X

Tabla de conversiones implcitas


Dep. Informtica

I.E.S. TRASSIERRA - Crdoba

PL/SQL

1.3.3.- mbito y [Link] de un programa, las referencias a un identificador son resueltas de acuerdo a su mbito
y visibilidad. El mbito de un identificador (variable o constante) es aquella regin de la
unidad de programa (bloque, subprograma o paquete) en la que el identificador mantiene su
valor sin perderlo. La visibilidad se refiere a las zonas en que se puede referenciar (usar).
Los identificadores declarados en un bloque de PL/SQL se consideran locales al bloque y
globales a todos sus sub-bloques anidados. Por eso un mismo identificador no puede declararse
dos veces en un mismo bloque pero s en varios bloques diferentes, cuantas veces se desee.
La siguiente figura muestra el alcance y visibilidad de la variable x, la cual est declarada en
dos bloques cerrados diferentes.

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.

1.4.- ZONA DE [Link] la parte del bloque PL/SQL utilizada cuando es necesario definir variables y/o constantes,
cursores o excepciones. Es una zona opcional de forma que si no hacen falta declaraciones se
omite la palabra reservada DECLARE.
Sintaxis:

DECLARE
declaracin_variables;
declaracin_cursores;
declaracin_excepciones;

La palabra reservada DECLARE, determina el comienzo de un bloque PL/SQL. Las


definiciones realizadas en esta zona son declaraciones locales que solo se reconocern en el
bloque PL/SQL actual y en los bloques anidados que pudiese contener.
Dep. Informtica

I.E.S. TRASSIERRA - Crdoba

PL/SQL

1.4.1.- Declaracin de variables y [Link] 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:

Identificador

[CONSTANT]

<tipo_de_dato /
identificador% TYPE /
identificador% ROWTYPE>

[NOT NULL]
[:= <expresin_plsql / valor_constante>];
dnde:
identificador

Nombre de la variable o constante.

[CONSTANT]

Palabra reservada para la definicin de constantes.

tipo_de_dato

Tipo de dato de la variable.

identificador%TYPE Declara la variable o constante con el mismo tipo de dato que una
variable definida anteriormente o que una columna de una tabla.
Identificador es el nombre de la variable PL/SQL definida
anteriormente, o el nombre de la tabla y la columna de la base de datos.
Identiticador%ROWTYPE Este atributo declara una fila variable con campos con los
mismos nombres y tipos que las columnas de una tabla o de una fila
recuperada de un cursor. Al declarar una fila %ROWTYPE, no se
admite ni la constante, ni la asignacin de valores.
NOT NULL

Obliga a que siempre tenga valor.

expresin_plsql / valor_constante Asigna a la variable o constante el valor inicial como


resultado de una operacin (expresin pl/sql) o con un valor constante.
Ejemplos:
varn_dept
total
respuesta
var2
registro1

[Link]%TYPE ;
number(10,2):=0 ;
char(1) ;
varn_dept%TYPE ;
dept%ROWTYPE ;

1.4.2.- Declaracin de [Link] registros son grupos de variables que pueden recibir la informacin de un cursor. Se
declaran segn la siguiente sintaxis:
TYPE nombre_registro
campo1
campo2
....
var
nombre_registro;

IS RECORD (
[Link]%TYPE
[Link]%TYPE ) ;

Ejemplo:
TYPE

reg
IS RECORD
( empleado
[Link]%TYPE
salario
[Link]% TYPE
r_empleado
reg;

Dep. Informtica

-- Declaracin del tipo de dato reg


);
-- Declaracin de una variable de tipo reg

I.E.S. TRASSIERRA - Crdoba

PL/SQL

1.4.3.- Declaracin de [Link] declaracin de un cursor le proporciona un nombre y le asocia una consulta (SELECT). El
cursor es un rea de trabajo que utiliza ORACLE para consultas que devuelven ms de una
fila, permitiendo la lectura y manipulacin de cada una de ellas. Un cursor tiene tres
componentes:
La tabla de resultado obtenida al ejecutar la SELECT.
Un orden establecido entre sus filas.
Un puntero que seala la posicin sobre la tabla resultado.
Tipos de cursores:
Estticos Se declaran en la DECLARE con su clusula SELECT asociada, y se abren,
ejecutan y cierran en la zona BEGN. Pueden ser simples o parametrizados.
Dinmicos La SELECT asociada al cursor no se especifica en la zona DECLARE,
sino en BEGIN, con lo que el resultado de su ejecucin es dinmico. Segn se declare
o no el registro que recibir los datos de la SELECT, los cursores dinmicos pueden
ser prefijados o no prefijados.
Esttico simple
Un cursor esttico simple se declara en la DECLARE con su clusula SELECT y se
abre, ejecuta y cierra en la zona BEGIN.
Sintaxis:

CURSOR

nombre_cursor IS
sentencia SELECT ;

Ejemplo:
DECLARE
CURSOR
SELECT

departa IS
numde, nomde FROM tdepto ;

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:
CURSOR nombre_cursor (nombre_parmetro tipo_parmetro) IS
sentencia_SELECT_utilizando_los_parmtetros ;
Los parmetros son variables nicamente de entrada, nunca para recuperacin de
datos. Estas variables son locales para el cursor y solo se referencian en la SELECT.
Si se definen parmetros, stos deben especificarse en la SELECT y se utilizan igual
que si utilizsemos un valor constante. Al abrir el cursor se sustituyen los parmetros
por los valores correspondientes.
Ejemplo:
ACCEPT valor PROMPT Departamento:
DECLARE
CURSOR empleados (dept_pl NUMBER) IS
SELECT
numem, nomem
FROM
temple
WHERE
numde = dept_pl ;
..........
BEGIN
OPEN empleados (&valor) ;
-- Apertura del cursor y paso del parmetro
Dep. Informtica

I.E.S. TRASSIERRA - Crdoba

PL/SQL

Si en cualquier cursor quisiramos modificar las filas que nos devuelve, deberamos
aadir a la Select asociada al cursor la clusula:
FOR UPDATE OF nombre_columna ;
Ejemplo:
DECLARE
CURSOR

empleados IS
SELECT numem, nomem FROM temple FOR UPDATE OF nomem ;

Dinmico no prefijado
Los cursores dinmicos son aquellos que la SELECT no aparece en la zona
DECLARE. En los no prefijados no se concreta la proyeccin de la SELECT .
Sintaxis:

TYPE
tipo_cursor IS REF CURSOR ;
...
nombre_cursor tipo_cursor ;

Ejemplo:
DECLARE
TYPE CurEmp IS REF CURSOR
....
C_emple1 CurEmp ;

-- Declaracin del tipo de cursor


-- 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>.
Sintaxis:

TYPE tipo_cursor IS REF CURSOR


RETURN tabla%ROWTYPE ;
...
nombre_cursor tipo_cursor ;

Ejemplo:
DECLARE
TYPE
....
[Link]

Datos IS REF CURSOR RETURN temple%ROWTYPE ;


Datos ;

1.4.4.- Declaracin de excepciones.


Si vamos a utilizar excepciones definidas por el usuario, es necesario declararlas en la zona
DECLARE. Las excepciones de usuario se declaran simplemente escribiendo la palabra
EXCEPTION detrs del nombre asignado a la excepcin que queramos definir:
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.

Dep. Informtica

I.E.S. TRASSIERRA - Crdoba

PL/SQL

1.5.- ZONA DE PROCESO: [Link] esta zona del bloque PL/SQL se escriben todas las sentencias ejecutables. El comienzo del
bloque PL/SQL se especifica con la palabra BEGIN. En el bloque se permiten:
-

Sentencias propias de PL/SQL.

Sentencias DML de SQL (SELECT, INSERT, UPDATE, DELETE)

Sentencias transaccionales (COMMIT, ROLLBACK, SAVEPOINT)

1.5.1.- Sentencias propias de PL/[Link] sentencias propias del lenguaje PL/SQL se agrupan en:
Asignaciones
Manejo de cursores
EXIT
Control condicional
Bucles
GOTO
NULL
[Link].- Asignacin.- La asignacin de valores a una variable se hace con el operador ":=".
Algunos ejemplos son:
salario := 2251 ;
comision := substr(cod_postal,2 ,3) ;
aumento := salario * 0.1 ;
total_sueldo := salario + aumento + comision ;

[Link].- 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).

Dep. Informtica

I.E.S. TRASSIERRA - Crdoba

PL/SQL

Abrir el cursor: OPEN. La sentencia OPEN, evala la SELECT asociada al cursor y lo


prepara para permitir su lectura. La sentencia OPEN, abre el cursor y ejecuta la consulta
asociada a dicho cursor.
Tipo de cursor

Sintaxis

cursor esttico simple

OPEN nombre_cursor ;

cursor esttico parametrizado

OPEN nombre_cursor (parm1 [,parm2] .. ) ;

cursor dinmico

OPEN nombre_cursor FOR sentencia_select ;

Los parmetros se pueden pasar posicionalmente: el primer parmetro sustituye al


primero que espera el cursor y as sucesivamente, o por asociacin de nombres:
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.
Sintaxis para recuperacin en variables:
FETCH nombre_cursor INTO var1 [,var2] ;
Todas las variables que aparecen en la clusula INTO deben haber sido definidas
previamente en la zona de declaracin de variables DECLARE.
Ser necesario tener tantas variables como columnas estemos recuperando en la
SELECT asociada al cursor. La recuperacin es posicional, es decir la primera
columna seleccionada se almacenar en la primera variable, la segunda en la segunda,
y as sucesivamente, por lo tanto, los tipos de las variables debern ser compatibles
con los valores de las columnas que van a almacenar.
Sintaxis para recuperacin en registro:
FETCH nombre_cursor INTO nombre_registro ;
Es la sintaxis ms usada debido a la facilidad para declarar el registro en la zona
DECLARE con la opcin de atributo %ROWTYPE<nombre_tabla>/<nombre_cursor>.
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.

Dep. Informtica

10

I.E.S. TRASSIERRA - Crdoba

PL/SQL

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
intente realizar con un cursor cerrado, provoca la excepcin predefinida INVALID_CURSOR.
Sintaxis : CLOSE

nombre_cursor ;

Ejemplo: CLOSE curdep;


[Link].- [Link] 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.
[Link].- Control condicional.
Permite ejecutar una o varias sentencias dependiendo de una condicin. Su sintaxis es:
IF
[ELSIF
[ELSE
END IF ;

condicin
THEN sentencias ;
condicin
THEN sentencias ;]
sentencias ;]

La condicin puede ser cualquier expresin PL/SQL de comparacin.


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.
Slo una secuencia de sentencias se ejecuta al procesar una instruccin IF.
Ejemplos:

IF tipo = 1
ELSIF tipo = 2
ELSE
END IF ;

THEN sal := sal * 0.01 ;


THEN sal := sal * 0.02 ;
sal := sal * 0.03 ;

[Link].- Bucles. Existen 5 tipos de bucles:

Bucles bsicos
Bucles condicionales (WHILE)
Bucles numricos (FOR)
Bucles sobre cursores
Bucles para una SELECT

Dep. Informtica

11

I.E.S. TRASSIERRA - Crdoba

PL/SQL

Bucles Bsicos. Son bucles infinitos que responden a la siguiente sintaxis:


LOOP
sentencias ;
END LOOP ;
Para romper el bucle (salir de l) deberemos utilizar EXIT, GOTO o RAISE.
Ejemplo:
LOOP
FETCH cursor_cl INTO registro ;
EXIT WHEN cursor_cl%NOTFOUND ;
END LOOP ;

Bucles Condicionales (WHILE). La condicin se evala antes de cada entrada al bucle.


Si la condicin se cumple se ejecutan las sentencias, y si no es as, se pasa el control a la
sentencia siguiente al final del bucle. Su sintaxis es:
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:
FOR ndice IN [REVERSE] exp_n1 .. exp_n2
LOOP
Sentencias ;
END LOOP ;
ndice

es la variable numrica de control del bucle, comienza con el valor de


exp_n1 y se va incrementando de 1 en 1 hasta el valor de exp_n2.

REVERSE

realiza la cuenta al revs, desde exp_n2 hasta exp_n1.

exp_n1, exp_n2 pueden ser valores constantes o cualquier expresin numrica.


Ejemplo:
FOR x IN 1 .. 10
LOOP
valor:= valor + x ;
END LOOP ;

Bucles sobre Cursores. Son bucles que se ejecutan para cada fila del cursor. Cuando se
inicia un bucle sobre un cursor automticamente se realizan los siguientes pasos:
- Se declara implcitamente el registro especificado como nombre_cursor%ROWTYPE.
- Se abre el cursor.
- Se realiza la lectura y se ejecutan las sentencias del bucle hasta que no hay mas filas.
- Se cierra el cursor.

Dep. Informtica

12

I.E.S. TRASSIERRA - Crdoba

PL/SQL

Sintaxis:
FOR nombre_registro IN nombre_cursor
LOOP
Sentencias ;
END LOOP ;
La variable de control del bucle se incrementa automticamente y no es necesario
inicializarla, pues lo est implcitamente como variable local de tipo integer. El mbito del
contador es el bucle y no puede accederse a su valor fuera de l. Dentro del bucle, el
contador puede referenciarse como una constante pero no se le puede asignar un valor.
Tambin le podemos pasar parmetros al cursor, tal y como se indic en el apartado de
manejo de cursores. En este caso los parmetros se indican entre parntesis tras el nombre
del cursor:
FOR nombre_registro IN nombre_cursor(lista_de_parametros)
.......
Si se sale del bucle prematuramente (p.e. con 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. Su sintaxis es:
FOR nombre_registro IN sentencia_SELECT
LOOP
sentencias ;
END LOOP ;
Si se sale del bucle prematuramente, o se detecta un error, el cursor se cierra. Hay que
resaltar que las columnas del cursor no pueden ser usadas con <[Link]> fuera
de estos dos ltimos bucles, ya que cierran automticamente el cursor que tratan.
Ejemplo:
FOR
registro IN SELECT numde FROM tdepto
LOOP
sentencias ;
END LOOP ;

Dep. Informtica

13

I.E.S. TRASSIERRA - Crdoba

PL/SQL

[Link].- GOTO. Esta sentencia transfiere el control a la sentencia o bloque PL/SQL siguiente
a la etiqueta indicada. Su sintaxis es:
GOTO etiqueta;
La etiqueta se especifica entre los smbolos << y >>, por ejemplo:
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.
[Link].- 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 vsal := vsal * 0.01
ELSE NULL;
END IF;

1.5.2. Sentencias DML


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:
%NOTFOUND

Devuelve TRUE si un INSERT, UPDATE o DELETE no ha procesado


ninguna fila o si la SELECT no recupera nada. En este ltimo caso se
provoca la excepcin predefinida NO_DATA_FOUND

%FOUND

Devuelve TRUE si un INSERT, UPDATE o DELETE ha procesado


alguna fila o una SELECT recupera datos

%ROWCOUNT

Devuelve el nmero de filas procesadas por un INSERT, UPDATE o


DELETE o las recuperadas por una SELECT .

[Link].- SELECT.
La sentencia SELECT recupera valores de la Base de Datos que sern almacenados en
variables PL/SQL. La sintaxis completa de la SELECT ya se estudi en la parte de SQL, la
nica variante en programacin es la opcin INTO que permite almacenar los valores
recuperados en variables.
Para poder recuperar valores en variables, la consulta slo debe devolver una fila (no funciona
con predicados de grupo). Su sintaxis es:
SELECT
FROM
Dep. Informtica

{* / col1 [,coI2] } INTO {reg / var1 [,var2] }


tabla resto_de_la_select ;

14

I.E.S. TRASSIERRA - Crdoba

PL/SQL

Las excepciones predefinidas ms comunes son:


A.- Si la consulta no devuelve ninguna fila:
Se produce la excepcin predefinida NO_DATA_FOUND
El error Oracle (SQLCODE) ORA-01403
El mensaje de error (SQLERRM) "no data found"
SQL%NOTFOUND es TRUE
SQL%FOUND es FALSE
SQL%ROWCOUNT es 0
B.- Si la consulta devuelve ms de una fila:
Se produce la excepcin predefinida TOO_MANY _ROWS
El error Oracle (SQLCODE) ORA-O1422
El mensaje de error (SQLEERM) 'single-row query returns more than one row"
SQL%NOTFOUND es FALSE
SQL%FOUND es TRUE
SQL%ROWCOUNT es 1 (solo puede devolver 0 o 1 fila)

[Link].- INSERT.
INSERT crea filas en la tabla o vista especificada. Su sintaxis es idntica a la de SQL.
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.
Su sintaxis es la misma de SQL:
INSERT INTO tabla [ (col1 [,col2] .....) ]
{ VALUES (exp1 [,exp2]..... ) /
Sentencia_Select
};
VALUES

permite insertar una tupla indicando expresiones constantes o variables.

Sentencia_Select

permite insertar varias tuplas a la vez.

Si no se inserta ninguna fila los atributos devuelven los siguientes valores:


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:

Dep. Informtica

15

I.E.S. TRASSIERRA - Crdoba

PL/SQL

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'
INSERT INTO dept (loc, dep_no, dname) VALUES (c, x, y);
INSERT INTO dept (loc, dep_no, dname) VALUES (92, 'ADMINISTRACION', 'SEVILLA') ;
END;

[Link].- UPDATE
La sentencia UPDA TE permite modificar los datos almacenados en las tablas o vistas.
Sintaxis:
UPDATE
SET

tabla
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 cuya select utilice varias tablas (obtenidos con select con yuncin).
Si no se actualiza ninguna fila los atributos devuelven los siguientes valores:
SQL%NOTFOUND es TRUE
SQL %FOUND es FALSE
SQL %ROWCOUNT es 0
Si se actualizan una o ms filas los atributos devuelven los siguientes valores:
SQL %NOTFOUND es FALSE
SQL%FOUND es TRUE
SQL%ROWCOUNT el nmero de filas actualizadas
Ejemplo:
UPDATE
temple
SET salar = salar * 0.1 WHERE numde = 110 ;

Dep. Informtica

16

I.E.S. TRASSIERRA - Crdoba

PL/SQL

[Link].- DELETE.
La sentencia DELETE permite borrar filas de la tabla o vista especificada.
Sintaxis:
DELETE

[ FROM]
[ WHERE

tabla
{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.
Si no se borra ninguna fila los atributos devuelven los siguientes valores:
SQL%NOTFOUND es TRUE
SQL%FOUND es FALSE
SQL%ROWCOUNT es 0
Si se borran una o ms filas los atributos devuelven los siguientes valores:
SQL%NOTFOUND es FALSE
SQL%FOUND es TRUE
SQL%ROWCOUNT es nmero de filas borradas
Ejemplo:
DELETE
WHERE

FROM temple
numde = 110;

1.5.3. Sentencias transaccionales


El bloque PL/SQL admite las sentencias transaccionales ya estudiadas en el bloque de SQL.

1.6.- ZONA DE EXCEPCIONES: [Link] zona de excepciones es la ltima parte del bloque PL/SQL y en ella se realiza la gestin y
el control de errores.
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.
Sintaxis:

EXCEPTION control_de_errores ;

Slo se activa un error de todos los definidos en dicha zona.


La zona EXCEPTION termina cuando se detecta la palabra reservada END (fin de la zona y
fin del bloque PL/SQL).
La ejecucin de las sentencias asignadas a un error se produce:

Dep. Informtica

17

I.E.S. TRASSIERRA - Crdoba

PL/SQL

Automticamente Oracle detecta un error, para el proceso y pasa el control a la zona


EXCEPTION, buscando si existe tratamiento al error detectado.
Manualmente

En el proceso llega un punto en el que nos interesa realizar lo mismo que


si se hubiese detectado un error y ejecutamos la excepcin.

La zona EXCEPTION es opcional. Si se omite y 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.
1.6.1.- Control de errores.
Cuando en el proceso se detecta un error, el proceso se para, pasando el control a la zona
EXCEPTION.
Sintaxis:

WHEN nombre_excepcin THEN sentencias ;

nombre_excepcin
sentencias

es el nombre de la que se quiere controlar (predefinida o de usuario).


es el conjunto de sentencias que se ejecutan si se produce el error.

1.6.2.- Excepciones predefinidas.


En Oracle existen las siguientes excepciones predefinidas:
Nombre de excepcin
CURSOR_ALREADY_OPEN
DUP_VAL_ON_INDEX
INVALID_CURSOR
INVALID_NUMBER
LOGIN_DENIED
NO_DATA_FOUND
NOT_LOGGED_ON
PROGRAM_ERROR
STORAGE_ERROR
TIMEOUT_ON_RESOURCE
TOO_MANY_ROWS
VALUE_ERROR
ZERO_DIVIDE
OTHERS

Tipo de error indicado


Cursor abierto previamente
Valor duplicado en ndice
Cursor no vlido
Nmero no vlido
Denegada la conexin a Oracle
La consulta no recupera ninguna fila
No conectado a Oracle
Problema interno
Fuera de memoria o error de memoria
Exceso de recursos consumidos
La consulta devuelve ms de una fila
Valor incorrecto
Divisin por cero
Cualquier otro error no especificado

SQLCODE
-6511
-1
-1001
-1722
-1017
+100
-1012
-6501
-6500
-51
-1422
-6502
-1476

1.6.3.- Excepciones definidas por el usuario.


Existen dos tipos de excepciones a definir por los usuarios y son:

Basadas en errores ORACLE (EXCEPTION INIT).Asigna un nombre a un error ORACLE existente.


Sintaxis: PRAGMA EXCEPTION_INIT (nombre_excepcin, -nmero_error)

Dep. Informtica

18

I.E.S. TRASSIERRA - Crdoba

PL/SQL

nombre_excepcin Deber estar definida como excepcin de usuario.


nmero_error
Es el numero del error Oracle que se desea controlar (el que nos
devuelve el SQLCODE).
La definicin se realiza en la zona del DECLARE y el control de la excepcin en la zona
EXCEPTION. Solo debe haber una excepcin por cada error Oracle.

Otras excepciones.
Se trata de un control de errores para el usuario. Este tipo de excepciones se deben
declarar segn vimos en el apartado de DECLARE. Una vez declarada la excepcin, la
podemos provocar cuando sea necesario utilizando la funcin RAISE que se detalla a
continuacin. El tratamiento dentro de la zona de excepciones es exactamente igual que el
de una excepcin predefinida.
Sintaxis: DECLARE
A EXCEPTION;
BEGIN
RAISE A;
EXCEPTION
WHEN A THEN .... ;
END;

1.6.4. - Ejecucin de excepciones: RAISE


Para la ejecucin del bloque PL/SQL y pasa el control a la zona de excepciones.
Sintaxis:

RAISE

nombre_excepcin

El nombre_excepcin es el nombre de la excepcin que se desea ejecutar, pueden ser


excepciones predefinidas o excepciones de usuario.
Ejemplo:

DECLARE
error EXCEPTION;
BEGIN
RAISE error;
RAISE TOO_MANY _ROWS;
EXCEPTION
WHEN error THEN ...;
WHEN TOO_MANY _ROWS THEN ... ;
END;

1.6.5.- [Link] 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.
No se puede utilizar directamente, pero si se puede guardar su valor en una variable.

Dep. Informtica

19

I.E.S. TRASSIERRA - Crdoba

PL/SQL

1.6.6.- [Link] 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.

1.6.7.- Algunos ejemplos de tratamiento de excepciones.1.- Excepciones predefinidas.


EXCEPTION
WHEN zero_divide THEN
Rollback;
WHEN value_error THEN
INSERT INTO errores VALUES
Commit;
WHEN others THEN
NULL;
END;

2.- Excepcin de usuario.


DECLARE
emp_sal [Link]%TYPE;
emp_no [Link]%TYPE;
salario_muy_alto EXCEPTION;
BEGIN
SELECT numem, salar INTO emp_no, emp_sal
FROM temple WHERE nomem = 'DURAN, LIVIA';
IF emp_sal * 1.05 > 4000 THEN
RAISE salario_muy_alto
ELSE
UPDATE temple SET.....
END IF;
EXCEPTION
WHEN NO_DATA_FOUND THEN
ROLLBACK;
WHEN salario_muy_alto THEN
INSERT INTO emp_alto_sal VALUES(emp_no);
COMMIT;
END;

3.- Cualquier error se graba en el fichero errores.


DECLARE
err_num NUMBER;
err_msg VARCHAR2(100);
BEGIN

EXCEPTION
WHEN OTHERS THEN
err_num := SQLCODE;
err_msg := SUBSTR(SQLERRM, 1, 100);
INSERT INTO errores VALUES(err_num, err_msg);
END;

Dep. Informtica

20

I.E.S. TRASSIERRA - Crdoba

PL/SQL

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

-- Parmetro 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');
END;

-- Envio al buffer del literal

1.7.- EJERCICIOS.1.7.1.- EJERCICIOS RESUELTOS.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 ;

2.- Idem al anterior, pero usando un bucle WHILE.


DROP TABLE temporal ;
CREATE TABLE temporal (numero number(2));
DECLARE
i number(2):=1;
BEGIN
WHILE i < 15 LOOP
INSERT INTO temporal VALUES (i);
i:=i+1;
END LOOP;
END;
/
SELECT * FROM temporal ;

Dep. Informtica

21

I.E.S. TRASSIERRA - Crdoba

PL/SQL

3.- Idem al anterior, pero usando un bucle FOR.


DROP TABLE temporal ;
CREATE TABLE temporal (numero number(2));
DECLARE
i number(2):=1;
BEGIN
FOR I IN 1 .. 14 LOOP
INSERT INTO temporal VALUES (i);
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.7.2.- EJERCICIOS PROPUESTOS.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.
3.- Modificar el anterior programa de forma que si el empleado no existe se visualice un
mensaje de error.

Dep. Informtica

22

I.E.S. TRASSIERRA - Crdoba

PL/SQL

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.
6.- Realizar el mismo ejercicio con un bucle sobre el cursor, controlando que no se inserten en
TOTALES los departamentos inexistentes.
7.- Mejorar el programa anterior para que, tanto en caso de inexistencia del departamento
como en caso de que ya haya sido introducido (que exista ya en totales), muestre sendos
mensajes de error.

Dep. Informtica

23

I.E.S. TRASSIERRA - Crdoba

PL/SQL

TEMA 2.- PROCEDIMIENTOS, FUNCIONES Y PAQUETES.2.1.- Introduccin.


2.2.- Procedimientos.
2.2.1.- Creacin y borrado.
2.2.2.- Tipos de argumentos: in, out, in out.
2.2.3.- Polimorfismo.
2.3.- Funciones.
2.3.1.- Creacin y borrado.
2.3.2.- Recursividad.
2.3.3.- Funciones PL/SQL en sentencias SQL.
2.4.- Paquetes.
2.4.1.- Creacin y borrado.
2.4.2.- La depuracin
2.5.- Ventajas de los procedimientos, funciones y paquetes.
2.6.- Manejo de excepciones.
2.7.- Ejercicios.
2.7.1.- Ejercicios resueltos.
2.7.2.- Ejercicios propuestos.

2.1.- [Link] de los bloques de cdigo 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.
Los paquetes son agrupaciones de procedimientos, funciones y definiciones de datos; es lo
que en otros entornos de programacin se conoce como librera.
Tanto los procedimientos como las funciones disponen de la siguiente estructura:
cabecera del procedimiento o funcin
declaracin de variables, cursores, sobprocedimientos, etc.
BEGIN
zona ejecutable
EXCEPTION
manipuladores de excepciones
END [nombre_procedimiento] ;
Dep. Informtica

24

I.E.S. TRASSIERRA - Crdoba

PL/SQL

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:
1.- Escribir el texto de la sentencia CREATE PROCEDURE / FUNCTION y guardarlo
en un fichero de texto con la extensin .SQL. Mientras se compone esta sentencia se
debe ir pensando en el manejo de errores de ejecucin.
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):
CREATE PROCEDURE altalum (v_num number, v_nom varchar2) IS
BEGIN
INSERT INTO alumnos VALUES (v_num, v_nom);
END ;
/

2.- Compilar el fichero de texto ejecutndolo con el comando START <nombre_fichero>.


La ejecucin convierte el cdigo fuente en cdigo compilado y lo almacena en la base
de datos. La ejecucin se realiza desde SQL*Plus u otro interfaz que permita
sentencias LDD. El cdigo fuente se almacena siempre en la B.D. El cdigo
compilado solo se almacena si no se han producido errores. En este caso pueden verse
los errores de compilacin con el comando SHOW ERRORS.
3.- Invocar el procedimiento o funcin desde un entorno Oracle con el comando
EXECUTE. Por ejemplo:
EXECUTE altalum (1, 'JOS ANGEL FERNNDEZ') ;

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:
SQL>variable v_a number;
SQL>variable v_b varchar2(50);
SQL>execute :v_a:=2;
SQL>execute :v_b:= 'ANA PALACIOS';

Nota.- El comando variable permite definir variables desde el


prompt de SQL. Al referenciar variables desde el promt de SQL es
necesario precederlas de dos puntos (:). Desde un programa o
subprograma las variables se referencian directamente.

Las siguientes son formas vlidas de invocacin:


Con paso de parmetros posicional:
EXECUTE altalum(:v_a, :v_b);
EXECUTE altalum(:v_a+1 , 'MARIA VALVERDE');
EXECUTE altalum(3, 'JOSE SANTAELLA');

Con paso de parmetros por asociacin:


EXECUTE altalum(:v_b=>FRANCISCO RUIZ, :v_a=>4);

Dep. Informtica

25

I.E.S. TRASSIERRA - Crdoba

PL/SQL

2.2.- [Link] procedimiento es un subprograma que realiza una accin especfica. Pueden recibir
parmetros pero que no devuelven ningn valor.

2.2.1.- Creacin y [Link] 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:
CREATE [OR REPLACE] PROCEDURE nombre_proc
( argumento [tipo_arg] tipo_dato [,argumento [tipo] tipo_dato ] .... )
AS [IS] bloque PL/SQL
dnde:
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.


La opcin REPLACE se especifica cuando se desea reemplazar un procedimiento del mismo
nombre sin necesidad de borrarlo previamente. AS e IS son equivalentes.
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 (;).
Para borrar un procedimiento usaremos la sentencia:
DROP PROCEDURE nombre_proc ;

2.2.2. Tipos de [Link] 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.

Dep. Informtica

26

I.E.S. TRASSIERRA - Crdoba

PL/SQL

Tipo
IN

Descripcin
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.

OUT

Permite devolver valores desde el procedimiento al entorno de


llamada. El argumento correspondiente acta como una variable no
inicializada, por lo que dentro del subprograma solo puede
asignrsele valores, no pudiendo aparecer en la parte derecha de
una expresin. En la invocacin del subprograma, este parmetro
solo puede sustituirse por una variable.

IN OUT

Se usa para pasar parmetros por referencia y recogerlos del


procedimiento o funcin. El argumento correspondiente acta
como una variable inicializada, por lo que se le puede cambiar su
valor y usarse en la parte derecha de las expresiones. En la llamada,
este parmetro solo puede sustituirse por una variable.

Los parmetros pueden declararse para que tomen valores por defecto, veamos como:
CREATE PROCEDURE prueba(v1 varchar2 default 'Sin Nombre', v2 number default 5) is ..

Las llamadas vlidas que podemos hacer a este procedimiento son las siguientes:
EXECUTE prueba;
EXECUTE prueba ('Paco');
EXECUTE prueba ('Marta', 9);

/* equivalente a execute prueba('Sin Nombre', 5);*/


/* equivalente a execute prueba('Paco', 5); */

Si quisiramos darle un valor a v2 y tomar el de v1 por defecto, deberamos usar la notacin


nominal:
EXECUTE prueba(v2=>8);

Es til y aconsejable declarar argumentos y variables utilizando los atributos %TYPE o


%ROWTYPE.
Veamos algunos ejemplos del uso de los tipos de argumentos:
Argumentos IN
Almacenar informacin acerca de un nuevo empleado:
CREATE OR REPLACE PROCEDURE alta_emp
(v_emp_numero IN [Link]%TYPE ,
v_emp_departa IN [Link]%TYPE ,
v_emp_telefono IN [Link]%TYPE ,
v_emp_fechanac IN [Link]%TYPE ,
v_emp_fechaing IN [Link]%TYPE ,
v_emp_salario IN [Link]%TYPE ,
v_emp_comision IN [Link]%TYPE ,
v_emp_hijos
IN [Link]%TYPE ,
v_emp_nombre IN [Link]%TYPE )
IS

Dep. Informtica

27

I.E.S. TRASSIERRA - Crdoba

PL/SQL

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.
Se pueden eliminar valores innecesarios de entrada a los procedimientos derivando dichos
valores internamente dentro del procedimiento o relacionndolos con un valor por defecto de
columna al definir la tabla. Por ejemplo para:
-

Generar la clave primaria de una tabla utilizando un generador de se secuencia.


Registrar el usuario partiendo de la variable USER.
Registrar la fecha actual basndose en la variable SYSDATE.
Almacenar valores por defecto, cuando sea apropiado.
Utilizar reglas de negocio para calcular valores de entrada de forma automtica
utilizando una frmula.

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:
CREATE OR REPLACE PROCEDURE alta_emp (v_emp_numero
v_emp_departa
v_emp_telefono
v_emp_fechanac
v_emp_hijos
v_emp_nombre
v_emp_fechaing [Link]%TYPE ;
v_emp_salario [Link]%TYPE ;
v_emp_comision [Link]%TYPE ;
BEGIN
v_emp_fechaing := SYSDATE ;
IF (v_emp_departa IN (110, 111, 112)) THEN
v_emp_comision := 0 ;
ELSE v_emp_comision := NULL;
END IF;

IN [Link]%TYPE ,
IN [Link]%TYPE ,
IN [Link]%TYPE ,
IN [Link]%TYPE ,
[Link]%TYPE ,
[Link]%TYPE ) IS

SELECT
min(salar) INTO v_emp_salario
FROM temple
WHERE
numde = v_emp_departa ;
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 ;
/

Dep. Informtica

28

I.E.S. TRASSIERRA - Crdoba

PL/SQL

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.
CREATE OR REPLACE PROCEDURE consulta_emp
(v_emp_numero IN [Link]%TYPE ,
v_emp_nombre OUT [Link]%TYPE ,
v_emp_salario OUT [Link]%TYPE ,
v_emp_comision OUT [Link]%TYPE) IS
BEGIN
SELECT nomem, salar, comis INTO v_emp_nombre, v_emp_salario, v_emp_comision
FROM temple WHERE numem = v_emp_numero;
END consulta_emp;
/

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.
CREATE OR REPLACE PROCEDURE con_guion
(v_telf_no
IN OUT VARCHAR2 )
IS
BEGIN
v_telf_no := SUBSTR (v_telf_no, 1, 3) || '-' || SUBSTR(v_telf_no, 4);
END con_guion;
/

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.

2.2.3.- [Link] polimorfismo es una caracterstica que permite definir ms de un objeto con el mismo
nombre. En PL/SQL podemos definir distintas funciones y procedimientos que compartan un
nombre comn, pero han de diferenciarse en la cantidad o tipo de los parmetros que reciben
o devuelven.

Dep. Informtica

29

I.E.S. TRASSIERRA - Crdoba

PL/SQL

Ejemplo:
PROCEDURE initialize (tab OUT DateTabTyp, n INTEGER) IS
BEGIN
FOR i IN 1..n LOOP
tab(i) := SYSDATE;
END LOOP;
END initialize;
PROCEDURE initialize (tab OUT RealTabTyp, n INTEGER) IS
BEGIN
FOR i IN 1..n LOOP
tab(i) := 0.0;
END LOOP;
END initialize;

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;

2.3.- [Link] 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.

2.3.1.- Creacin y [Link] sentencia CREATE FUNCTION es idntica a CREATE PROCEDURE, excepto por la
clusula extra RETURN. Con ella se genera una nueva funcin que declara una lista de
argumentos, declara el argumento RETURN y define la accin a realizar por el bloque
PL/SQL estndar. Su sintaxis es:
CREATE [OR REPLACE] FUNCTION nombre_func
(argumento [tipo] tipo_dato [,argumento [tipo] tipo_dato ] ..) RETURN tipo_dato
AS [IS] bloque PL/SQL
Dep. Informtica

30

I.E.S. TRASSIERRA - Crdoba

PL/SQL

Dnde 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.
Ejemplo: recuperar el salario de un empleado.
CREATE OR REPLACE FUNCTION tomar_salario
(v_emp_numero IN [Link]%TYPE) RETURN number
IS
v_emp_salario [Link]%TYPE := 0;
BEGIN
SELECT
FROM
WHERE
RETURN
END tomar_salario;
/

salar INTO v_emp_salario


temple
numem = v_emp_numero;
(v_emp_salario);

Para usar la funcin podremos hacer:


SELECT nomem, tomar_salario(numem) FROM temple;

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.
Para borrar una funcin usaremos la sentencia:
DROP FUNCTION nombre_func ;

2.3.2.- [Link] funciones pueden invocarse recursivamente, tanto en autollamada como en interllamada.
Veamos la tpica funcin de factorial (autoinvocacin):
CREATE FUNCTION factorial (n number) RETURN number IS
BEGIN
IF n = 0 THEN RETURN 1;
ELSE
RETURN n* factorial (n-1);
END IF;
END ;
/

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:
SQL> variable v number;
SQL> EXECUTE :v:=factorial(4);
SQL> print v;
Dep. Informtica

31

I.E.S. TRASSIERRA - Crdoba

PL/SQL

La recursividad no es una herramienta considerada fundamental en la programacin PL/SQL.


Cualquier problema que requiera su utilizacin tambin puede ser resuelto utilizando
iteracin. Una versin iterativa de un programa es usualmente ms fcil de disear y de
entender. Sin embargo, la versin recursiva es ms simple, pequea y ms fcil de depurar. A
modo de ejemplo, observe las siguientes dos versiones de cmo calcular el nmero n-simo
de la serie de Fibonacci:
-- 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.

2.3.3.- Funciones PL/SQL en sentencias [Link] 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:
La lista de expresiones del comando SELECT.
Condiciones de las clusulas WHERE y HAVING.
La clusula VALUES de la sentencia INSERT.
La clusula SET de la sentencia UPDATE.
NO se puede invocar una funcin PL/SQL desde la clusula CHECK de una vista.

Dep. Informtica

32

I.E.S. TRASSIERRA - Crdoba

PL/SQL

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.

2.4.- [Link] 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.

Dep. Informtica

33

I.E.S. TRASSIERRA - Crdoba

PL/SQL

2.4.1.- Creacin y [Link] paquetes se crean con el comando CREATE PACKAGE, cuya sintaxis es:
- Parte de declaraciones:
CREATE [OR REPLACE] PACKAGE nombre_paq
AS [IS] bloque_pl_sql_paq_decl
- Cuerpo del paquete (implementacin):
CREATE [OR REPLACE] PACKAGE body nombre_paq
AS [IS] bloque_pl_sql_paq_body
Un paquete puede contener procedimientos, funciones, variables, constantes, cursores y
excepciones. Adems, siempre que no se cambie la parte de declaraciones, se puede cambiar
la implementacin de una rutina o el cuerpo de un cursor sin necesidad de volver a compilar
las aplicaciones que los usaban, ya que el interfaz no se ha cambiado.
Un paquete presenta normalmente el siguiente formato:
create package nombre is
/* especificacin (parte visible) */
/* declaraciones de tipos y objetos pblicos */
/* especificacin de procedimientos y funciones */
end;
/
create package body nombre is
/* cuerpo (parte oculta)*/
/*declaraciones de tipos y objetos privados */
/* implementacin de procedimientos y funciones */
[ begin
/* sentencias de inicializacin */ ]
end;
/
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.
/* para el caso de que la llamada se haga desde el prompt de SQL*/
SQL > execute nombre_paquete.nombre_procedimiento(argumentos);

Dep. Informtica

34

I.E.S. TRASSIERRA - Crdoba

PL/SQL

Cuando queramos borrar un paquete lo haremos con la sentencia


DROP PACKAGE nombre_paquete ;
A continuacin se expone un ejemplo de un paquete completo:
create or replace package acciones_empleados is
type registro_empleado is record (empleado number, salario number);
cursor salario_descendente (empleado number) return registro_empleado;
procedure alta_empleado (nombre varchar2 , trabajo varchar2 , salario number, dpto number) ;
procedure baja_empleado (id_empleado number);
end;
/
create or replace package body acciones_empleados is
cursor salario_descendente (empleado number) return registro_empleado is
select no_empleado, salario from empleados order by salario desc;
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;
procedure baja_empleado (id_empleado number) is
begin
delete from empleados where empleado = id_empleado ;
end;
end;
/

2.4.2.- La depuracin en los [Link] objeto de identificar los errores en tiempo de compilacin, en vez de esperar a la ejecucin,
puede especificarse el nivel de depuracin de una funcin empaquetada cuando se crea el
paquete. El nivel de depuracin determina que operaciones puede realizar la funcin en la
base de datos. Para especificar en nivel de depuracin se utiliza el paquete predefinido
RESTRICT_REFERENCES.
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).

Dep. Informtica

35

I.E.S. TRASSIERRA - Crdoba

PL/SQL

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.
CREATE PACKAGE finanzas AS
interes REAL;
FUNCTION comp
(anos IN NUMBER
cant
IN NUMBER
porc
IN NUMBER) RETURN NUMBER;
PRAGMA RESTRICT _REFERENCES(comp, WNDS, RNPS, WNPS);
END finanzas;
/
CREATE PACKAGE BODY finanzas AS
FUNCTION comp
(anos IN NUMBER
cant
IN NUMBER
porc
IN NUMBER) RETURN NUMBER IS
BEGIN comp
RETURN cant * POWER((porc/100) +1, anos)
END comp;
END finanzas;
/

El nivel de depuracin de una funcin se debe especificar en la zona de especificacin del


paquete. Si el paquete contiene varias funciones con el mismo nombre, el nivel de depuracin
se aplica a la ltima.
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 [Link]@bcn(anos,cant,porc) INTO interes
FROM conta
WHERE no_cuenta = cuenta_id
END;

Dep. Informtica

36

I.E.S. TRASSIERRA - Crdoba

PL/SQL

2.5.- VENTAJAS DE PROCEDIMIENTOS, FUNCIONES Y [Link] uso de procedimientos, funciones de usuario y paquetes presenta una serie de ventajas:

Modula el desarrollo de las aplicaciones.

Aumenta la seguridad y la integridad en la Base de Datos.


- Mayor independencia de los datos, al ser analizados dentro del servidor Oracle en vez
de desde dentro de una aplicacin.
- Control de acceso indirecto a objetos de la B.D. para usuarios no privilegiados.
Asegura que las acciones que estn relacionadas se ejecutan conjuntamente.

Aumenta del rendimiento


- Permite realizar clculos complejos, lentos o no disponibles en SQL
- Preanlisis de sentencias que ejecutan varios usuarios, utilizando el SQL compartido.
- Las sentencias PL/SQL se analizan en tiempo de compilacin y no en ejecucin.
- Reduccin del nmero de llamadas a la Base de Datos y el trfico por la red gracias a
la agrupacin de comandos.
- Posibilidad de manipular nuevos tipos de datos (por ejemplo latitud o longitud),
codificando cadenas de caracteres y utilizando funciones para operar con las cadenas.

Mejora en la utilizacin de la memoria


- Una nica copia del cdigo almacenado en la B.D. en lugar de mltiples copias del
mismo cdigo en aplicaciones diferentes.
- Utiliza SQL compartido para evitar el exceso de cursores.

Fcil mantenimiento
- Permite modificar procedimientos on-line sin interferir al resto de los usuarios (que
ejecutan una versin anterior).
- La modificacin de una rutina afecta a todas las aplicaciones que trabajen con ella.
Esto implica eliminar la duplicidad de las comprobaciones.

2.6.- MANEJO DE [Link] procedimientos y funciones deben prever cualquier tipo de excepcin ocurrida mientras
se ejecutan, bien propagando el error al entorno de llamada o bien desvindolo a una zona del
subprograma.
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.
Tipo de excepcin

Efecto a conseguir

Mtodo de manejo

Comunicar el error interactivamente


Oracle

Definida por usuario

Dep. Informtica

Omitir en el procedimiento el manejo de


errores
Realizar una operacin en la base de datos Incluir el manejo de excepciones dentro
adaptando el mensaje de error.
del procedimiento.
Comunicar el error interactivamente
Llamar al procedimiento
RAISE APPLICATION ERROR.
Realizar una operacin en la base de datos Incluir el manejo de excepciones dentro
adaptando el mensaje de error.
del procedimiento

37

I.E.S. TRASSIERRA - Crdoba

PL/SQL

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.
Si se omite el manejo de errores y el procedimiento termina con un fallo, devolver al entorno
de llamada el error "UNHANDLED EXCEPTION".
Ejemplo: Propagar una excepcin del Servidor Oracle (usando la base de datos de ejemplo
de oracle)

Mientras se est almacenando informacin para un empleado nuevo, comprobar que su


jefe existe como empleado:
CREATE OR REPLACE PROCEDURE alta_emp
(v_emp_no
IN [Link]%TYPE,
v_emp_name
IN [Link]%TYPE,
v_emp_job
IN [Link]%TYPE,
v_mgr_no
IN [Link]%TYPE,
v_emp_sal
[Link]%TYPE)
IS
v_emp_hiredate [Link]%TYPE ;
v_emp_comm [Link]%TYPE ;
v_emp_deptno [Link]%TYPE ;
BEGIN
v_emp_hiredate:=sysdate;
v_emp_comm:=0;
SELECT deptno INTO v_emp_deptno FROM emp WHERE empno = v_mgr_no;
INSERT INTO emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
VALUES (v_emp_no, v_emp_name, v_emp_job, v_mgr_no, v_emp_hiredate,
v_emp_sal, v_emp_comm, v_emp_deptno);
END alta_emp;
/

La siguiente sentencia provocara la respuesta:


SQL> EXECUTE alta_emp (1, 'PEPE', 'CLERK', 9999, 1000);
BEGIN alta_emp (1, 'PEPE', 'CLERK', 9999, 1000); END;
*
ERROR en lnea 1:
ORA-01403: no se han encontrado datos
ORA-06512: en "SYSTEM.ALTA_EMP", lnea 14
ORA-06512: en lnea 1

Ejemplo: Propagar una excepcin definida por el usuario.


Recordemos que el procedimiento RAISE_APPLICATION_ERROR su usa para mostrar una
excepcin definida por el usuario de forma interactiva devolviendo un cdigo de error no
estndar y un mensaje.

Mientras se intenta borrar a un empleado, comprobar que el empleado especificado existe:


CREATE OR REPLACE PROCEDURE baja_emp (v_emp_numero IN [Link]%TYPE) IS
BEGIN
DELETE FROM temple WHERE numem = v_emp_numero;
IF SQL%NOTFOUND THEN
RAISE_APPLICATION_ERROR (-20300, 'Empleado inexistente');
END IF;
END baja_emp;
/

Dep. Informtica

38

I.E.S. TRASSIERRA - Crdoba

PL/SQL

La siguiente sentencia provocara la respuesta:


SQL> EXECUTE baja_emp(9999);
BEGIN baja_emp(9999); END;
*
ERROR en lnea 1:
ORA-20300: Empleado inexistente
ORA-06512: en "SYSTEM.BAJA_EMP", lnea 6
ORA-06512: en lnea 1

Si se omite el manejo de excepciones RAISE_APPLICATION_ERROR para una excepcin


definida por el usuario y el procedimiento finaliza con un fallo, devolver un mensaje
indicando que la excepcin definida por el usuario ha fallado.
Si se incluye el manejo de excepciones, el proceso se direcciona a la zona de excepciones. El
desvo de excepciones definidas por el usuario acta de forma similar a las excepciones
Oracle, pero incluyendo su correspondiente manejador. Hay dos etapas adicionales: la
declaracin de la excepcin e invocarla de manera explcita con la sentencia RAISE.

Ejemplo: Desviar el flujo del programa a una excepcin Oracle predefinida. (usando la
base de datos de ejemplo de oracle)

Mientras se almacena informacin acerca de un nuevo empleado, comprobar que su jefe


existe como empleado.
CREATE OR REPLACE PROCEDURE alta_emp
(v_emp_no
IN [Link]%TYPE,
v_emp_name
IN [Link]%TYPE,
v_emp_job
IN [Link]%TYPE,
v_mgr_no
IN [Link]%TYPE,
v_emp_sal
[Link]%TYPE)
IS
v_emp_hiredate [Link]%TYPE ;
v_emp_comm [Link]%TYPE ;
v_emp_deptno [Link]%TYPE ;
BEGIN
v_emp_hiredate:=sysdate;
v_emp_comm:=0;
SELECT deptno INTO v_emp_deptno FROM emp WHERE empno = v_mgr_no;
INSERT INTO emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
VALUES (v_emp_no, v_emp_name, v_emp_job, v_mgr_no, v_emp_hiredate,
v_emp_sal, v_emp_comm, v_emp_deptno);
EXCEPTION
WHEN NO_DATA_FOUND THEN
RAISE_APPLICATION_ERROR (-20201, 'El jefe indicado:'|| v_mgr_no||' no es empleado');
END alta_emp;
/

La siguiente sentencia provocara la respuesta:


SQL> EXECUTE alta_emp (1, 'PEPE', 'CLERK', 9999, 1000);
BEGIN alta_emp (1, 'PEPE', 'CLERK', 9999, 1000); END;
*
ERROR en lnea 1:
ORA-20201: El jefe indicado:9999 no es empleado
ORA-06512: en "SYSTEM.ALTA_EMP", lnea 21
ORA-06512: en lnea 1

Dep. Informtica

39

I.E.S. TRASSIERRA - Crdoba

PL/SQL

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.

Ejemplo: Desviar el flujo del programa a una excepcin Oracle NO-PREDEFINIDA.

Mientras se almacena informacin acerca de un nuevo empleado, comprobar que su jefe


existe como empleado.
CREATE OR REPLACE PROCEDURE alta_emp
(v_emp_no
IN [Link]%TYPE,
v_emp_name
IN [Link]%TYPE,
v_emp_job
IN [Link]%TYPE,
v_mgr_no
IN [Link]%TYPE,
v_emp_hiredate [Link]%TYPE ,
v_emp_sal
[Link]%TYPE,
v_emp_comm [Link]%TYPE )
IS
v_emp_deptno [Link]%TYPE ;
e_jefe_erroneo EXCEPTION;
PRAGMA EXCEPTION_INIT(e_jefe_erroneo, +100);
BEGIN
SELECT deptno INTO v_emp_deptno FROM emp WHERE empno = v_mgr_no;
INSERT INTO emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
VALUES (v_emp_no, v_emp_name, v_emp_job, v_mgr_no, v_emp_hiredate,
v_emp_sal, v_emp_comm, v_emp_deptno);
EXCEPTION
WHEN e_jefe_erroneo THEN
RAISE_APPLICATION_ERROR (-20291, 'Jefe '|| v_mgr_no||' no es empleado');
END alta_emp;
/

La siguiente sentencia provocara la respuesta:


SQL> EXECUTE alta_emp(1, PEPE', 'CLERK', 9999, '01-JUL-98', 1000, NULL);
BEGIN alta_emp(1, 'PEPE', 'CLERK', 9999, '01-JUL-98', 1000, NULL); END;
*
ERROR en lnea 1:
ORA-20291: Jefe 9999 no es empleado
ORA-06512: en "SYSTEM.ALTA_EMP", lnea 20
ORA-06512: en lnea 1

2.7.- EJERCICIOS.2.7.1.- Ejercicios resueltos.1.- Crear el procedimiento aumento_salario para aumentar el salario de un empleado en una
cantidad. El nmero de empleado y el aumento se le pasarn a la funcin, la cual deber
controlar los errores producidos por la inexistencia del empleado y del salario (valor nulo).

Dep. Informtica

40

I.E.S. TRASSIERRA - Crdoba

PL/SQL

CREATE PROCEDURE aumento_salario (empleado integer, incremento real) IS


salario_actual
real;
falta_salario exception;
BEGIN
SELECT salario INTO salario_actual FROM empleados WHERE no_empleado = empleado;
IF salario_actual IS NULL THEN
RAISE falta_salario;
ELSE
UPDATE empleados
SET salario = salario + incremento WHERE no_empleado = empleado;
END IF
EXCEPTION
WHEN NO_DATA_FOUND THEN
INSERT INTO mensajes VALUES (empleado, 'No existe el empleado'};
WHEN falta_salario THEN
INSERT INTO mensajes VALUES (empleado, 'No tiene salario');
END;
/

2.- Determinar si un nmero es par o impar. Recursividad por interinvocacin.


CREATE OR REPLACE package pq_par IS
FUNCTION par(n number) RETURN boolean;
FUNCTION impar(n number) RETURN boolean;
END pq_par;
/
CREATE OR REPLACE PACKAGE BODY pq_par IS
FUNCTION par (n number) RETURN boolean IS
BEGIN
IF n = 0 THEN RETURN TRUE;
ELSE
RETURN impar(n-1);
END IF;
END;
FUNCTION impar (n number) RETURN boolean IS
BEGIN
IF n = 0 THEN RETURN FALSE;
ELSE
RETURN par(n-1);
END IF;
END;
END pq_par;

/
3.- Ejemplo completo de paquete:
Consideremos el siguiente paquete emp_actions. La parte de especificacin del paquete
declara los siguientes tipos de datos, variables y subprogramas:

Tipos EmpRecTyp y DeptRecTyp


Cursor desc_salary
Excepcin invalid_salary
Funciones hire_employee y nth_highest_salary
Procedimientos fire_employee y raise_salary

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.
Dep. Informtica

41

I.E.S. TRASSIERRA - Crdoba

PL/SQL

CREATE PACKAGE emp_actions AS


/* Declaracin pblica (visible desde fuera) de tipos, cursor y excepcin */
TYPE EmpRecTyp IS RECORD (emp_id INT, salary REAL);
TYPE DeptRecTyp IS RECORD (dept_id INT, location VARCHAR2);
CURSOR desc_salary RETURN EmpRecTyp;
invalid_salary EXCEPTION;
/* 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;
/
CREATE PACKAGE BODY emp_actions AS
number_hired INT;

-- visible solo desde este paquete

CURSOR desc_salary RETURN EmpRecTyp IS


SELECT empno, sal FROM emp ORDER BY sal DESC;
FUNCTION hire_employee (

ename VARCHAR2,
job VARCHAR2,
mgr REAL,
sal REAL,
comm REAL,
deptno REAL) RETURN INT IS

new_empno INT;
BEGIN
SELECT empno_seq.NEXTVAL INTO new_empno FROM dual;
INSERT INTO emp VALUES (new_empno, ename, job,
mgr, SYSDATE, sal, comm, deptno);
number_hired := number_hired + 1;
RETURN new_empno;
END hire_employee;
PROCEDURE fire_employee (emp_id INT) IS
BEGIN
DELETE FROM emp WHERE empno = emp_id;
END fire_employee;
/* Definiciones locales de funciones accesibles solo desde este paquete. */
FUNCTION sal_ok (rank INT, salary REAL) RETURN BOOLEAN IS
min_sal REAL;
max_sal REAL;
BEGIN
SELECT losal, hisal INTO min_sal, max_sal FROM salgrade
WHERE grade = rank;
RETURN (salary >= min_sal) AND (salary <= max_sal);
END sal_ok;
PROCEDURE raise_salary (emp_id INT, grade INT, amount REAL) IS
salary REAL;
BEGIN
SELECT sal INTO salary FROM emp WHERE empno = emp_id;
IF sal_ok(grade, salary + amount) THEN

Dep. Informtica

42

I.E.S. TRASSIERRA - Crdoba

PL/SQL

UPDATE emp SET sal = sal + amount WHERE empno = emp_id;


ELSE
RAISE invalid_salary;
END IF;
END raise_salary;
FUNCTION nth_highest_salary (n INT) RETURN EmpRecTyp IS
emp_rec EmpRecTyp;
BEGIN
OPEN desc_salary;
FOR i IN 1..n LOOP
FETCH desc_salary INTO emp_rec;
END LOOP;
CLOSE desc_salary;
RETURN emp_rec;
END nth_highest_salary;
-- Esta es la parte opcional de inicializacin. Solo se ejecuta la primera vez
BEGIN
-- que se hace referencia al paquete dentro de una misma sesin */
INSERT INTO emp_audit VALUES (SYSDATE, USER, EMP_ACTIONS);
number_hired := 0;
END emp_actions;
/

4.- Un ejemplo de paquete sin cuerpo:


CREATE PACKAGE trans_data AS
TYPE TimeRec IS RECORD (

horas
NUMBER,
minutos
NUMBER);
TYPE TransRec IS RECORD (
categoria
VARCHAR2,
cuenta
NUMBER,
cantidad
NUMBER,
horario
TimeRec);
minimo_balance
CONSTANT NUMBER := 10.00;
numero_procesado
NUMBER;
insuficiente_saldo
EXCEPTION;
END trans_data;

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.

2.7.2.- Ejercicios propuestos.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. El
procedimiento deber controlar que:
- El director existe como empleado, si no dar el error: -20001, 'El jefe no es empleado'.
- El centro de trabajo existe, si no dar el error: -20002, 'El centro de trabajo no existe'.
- El departamento no est previamente creado, si lo estuviera dar el error: -20003,
'Departamento ya creado'.
2.- Crear la funcin SUELDO_EMP, que recibir el nmero de un empleado y devolver su
sueldo total (salario+comisin). Si el empleado suministrado no existe, devolver el error 20222 'Empleado inexistente'.
Dep. Informtica

43

I.E.S. TRASSIERRA - Crdoba

PL/SQL

3.- Crear la funcin SUELDO_DEP, que haciendo uso de la funcin anterior, reciba un
nmero de departamento y devuelva el sueldo total que cobran sus empleados. Si el
departamento suministrado no existe devolver el error: -20223, 'Departamento inexistente'.
4.- Disear el procedimiento AUMENTO_SALARIO, que reciba un nmero de departamento
y un porcentaje, realice el incremento de los salarios de los empleados de ese departamento en
el porcentaje dado. Si no se especifica porcentaje, se supondr del 0,5%. Si el departamento
suministrado no existe devolver el error: -20223, 'Departamento inexistente'.
5.- Crear el paquete PAQ_EMPLE que recoja todos los procedimientos y funciones
desarrollados (alta_emp, baja_emp, consulta_emp, sueldo_emp y aumento_salario).

Dep. Informtica

44

I.E.S. TRASSIERRA - Crdoba

PL/SQL

TEMA 3.- DISPARADORES (TRIGGERS)


3.1.- Disparadores.
3.1.1.- Concepto.
3.1.2.- Sintaxis.
3.1.3.- Nombres correlativos.
3.2.- Componentes de un disparador.
3.2.1.- Instruccin.
3.2.2.- Restriccin.
3.2.3.- Accin.
3.3.- Tipos de disparadores.
3.4.- Modificar y borrar disparadores.
3.5.- Manejo de errores.
3.6.-Ejercicios.
3.6.1.- Ejercicios resueltos.
3.6.2.- Ejercicios propuestos.

3.1.- DISPARADORES.3.1.1.- [Link] permite definir procedimientos almacenados en la base de datos, que estn
asociados a una tabla y que son ejecutados implcitamente ("disparados") cuando una
instruccin INSERT, UPDATE o DELETE se ejecuta sobre la tabla asociada. Estos
procedimientos reciben el nombre de disparadores de la base de datos.
Un disparador puede incluir instrucciones SQL e instrucciones PL/SQL y puede invocar a
otros procedimientos. Los procedimientos y los disparadores se diferencian en la forma en
que son invocados. Mientras un procedimiento lo ejecuta explcitamente un usuario o una
aplicacin, un disparador es ejecutado (disparado) implcitamente por Oracle cuando se
ejecuta una instruccin INSERT , UPDATE o DELETE de un disparador.
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
ciones

UPDATE ..SET ..
INSERT INTO ..
DELETE FROM ..

Tabla 1

----------------------------------------------

UPDATE TIGGER
BEGIN
....

INSERT TIGGER
BEGIN
....

DELETE TIGGER
BEGIN
....

Los disparadores se almacenan en la base de datos, separados de las tablas asociadas a ellos.
Dep. Informtica

45

I.E.S. TRASSIERRA - Crdoba

PL/SQL

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 que se activa
al ejecutar los scripts [Link] y [Link], que en la versin 10g Express
Edition se encuentran en C:\oraclexe\app\oracle\product\10.2.0\server\RDBMS\ADMIN, y
son cargados automticamente al iniciar una sesin. Si no estuvieran cargados, el
administrador debe ejecutarlos.
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.
Si el disparador usa instrucciones SQL o invoca a procedimientos o funciones, el usuario que
define el disparador debe tener los privilegios necesarios para utilizarlos.

3.1.2.- [Link] disparador puede crearse con el DBA Studio o el comando CREATE TRIGGER desde
alguna herramienta interactiva (como SQL*PLUS, SQL*DBA). Su sintaxis es:
CREATE [OR REPLACE] TRIGGER [Link]
{BEFORE / AFTER} { INSERT / DELETE / UPDATE [OF lista_columnas]
[ OR INSERT / DELETE / UPDATE [OF lista_columnas]
[ OR INSERT / DELETE / UPDATE [OF lista_columnas]]]}
ON [Link]
[ REFERENCING OLD [AS] antiguo [ NEW [AS] nuevo ] ]
[ FOR EACH ROW [WHEN (condicin)] ]
bloque_pl/sql
/
OR REPLACE:

Reemplaza el disparador si ya existe. Se usa para cambiar la definicin de


un disparador que ya exista sin tener que borrarlo antes.

esquema:

Es el nombre del esquema que contiene al disparador. Si se omite, se crea


el disparador en el esquema del usuario.

disparador:

Es el nombre del disparador. Ha de ser nico con respecto a otros


disparadores en el esquema, aunque no tiene porque ser nico con respecto
a otros objetos del esquema (tablas, vistas y procedimientos).

BEFORE:

Indica que ORACLE dispara el disparador antes de ejecutar la instruccin


disparador (INSERT, UPDATE o DELETE).

Dep. Informtica

46

I.E.S. TRASSIERRA - Crdoba

PL/SQL

AFTER:

Indica que el disparador se dispara despus de ejecutar la instruccin


disparador (INSERT, UPDATE o DELETE).

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.

ON:

Especifica el esquema y nombre de tabla sobre la que se crea el disparador.


No se puede crear un disparador sobre una tabla en el esquema SYS.

REFERENCING: Especifica correlacin de nombres. Se puede usar correlacin de nombres


en los bloques PL/SQL y en la clusula WHEN de un disparador para
referenciar los valores viejos y nuevos de la fila actual. Los nombres
correlativos por defecto son OLD y NEW.
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.
WHEN :

Indica la restriccin disparador. Esta restriccin contiene una condicin


SQL que debe satisfacerse para disparar el disparador. Esta condicin debe
contener nombres correlativos y no puede contener una consulta. Solo
puede especificarse una restriccin para un disparador fila. La condicin se
evala para cada fila que se vea afectada por la instruccin disparador.

bloque_Pl/sql:

Es el bloque PL/SQL que ORACLE ejecuta cuando dispara el disparador.


El bloque PL/SQL de un disparador no puede contener las siguientes
instrucciones SQL: COMMIT , ROLLBACK, y SAVEPOINT.

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):

Dep. Informtica

47

I.E.S. TRASSIERRA - Crdoba

PL/SQL

3.1.3.- Nombres correlativos .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...

3.2.- COMPONENTES DE UN [Link] disparador consta de tres componentes:


-

Instruccin disparador,
Restriccin disparador, y
Accin disparador.

3.2.1.- Instruccin [Link] 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:
UPDATE OF exis ON articulos
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.
Una instruccin disparador puede contener mltiples instrucciones DML:
... INSERT OR UPDATE OR DELETE ON asegurados ...
Dep. Informtica

48

I.E.S. TRASSIERRA - Crdoba

PL/SQL

Lo que significa que cuando una instruccin INSERT, UPDATE o DELETE se ejecuta sobre
la tabla asegurados, se dispara el disparador.
Cuando se utilizan mltiples tipos de instrucciones DML en un disparador, se pueden utilizar
predicados condicionales (INSERTING, DELETING, y UPDATING) para detectar qu
instruccin ha disparado el disparador. Por lo tanto, se pueden crear disparadores que ejecuten
distintos fragmentos de cdigo segn la instruccin disparador que ha disparado 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.
CREATE OR REPLACE TRIGGER total_salario
AFTER DELETE OR INSERT OR UPDATE OF numde, salar ON temple FOR EACH ROW
BEGIN
/* se asume que numde y salar son NO NULOS */
IF DELETING OR (UPDATING AND :[Link] != :[Link]) THEN
UPDATE
tdepto
SET
total_sal = total_sal - :[Link]
WHERE
numde = :[Link] ;
END IF ;
IF INSERTING OR (UPDATING AND :[Link] != :[Link]) THEN
UPDATE
tdepto
SET
total_sal = total_sal + :[Link]
WHERE
numde = :[Link] ;
END IF ;
IF (UPDATING AND :[Link] = :[Link]) THEN
UPDATE
tdepto
SET
total_sal = total_sal - :[Link] + :[Link]
WHERE
numde = :[Link] ;
END IF ;
END;
/
Ntese que si se modifica el departamento de un empleado se cumplen las dos primeras condiciones.

3.2.2.- Restriccin [Link] 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.

3.2.3.- Accin [Link] 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.
Dep. Informtica

49

I.E.S. TRASSIERRA - Crdoba

PL/SQL

3.3.- TIPOS DE [Link] las opciones BEFORE/AFTER y FOR EACH ROW, se pueden crear cuatro tipos
bsicos de disparadores. El tipo de un disparador determina:
- cundo dispara ORACLE el disparador en relacin a la instruccin disparador, y
- cuntas veces dispara ORACLE el disparador.
La siguiente tabla describe cada tipo de disparador, sus propiedades y las opciones utilizadas
para crearlos.
Opcin

FOR EACH STATEMENT


( Instruccin)

FOR EACH ROW


(Fila)

BEFORE

La accin disparador se ejecuta antes de


La accin disparador se ejecuta antes
modificar cada fila afectada por la
de ejecutar la instruccin disparador.
instruccin disparador.

AFTER

La accin disparador se ejecuta


despus de ejecutar la actualizacin
(instruccin disparador).

La accin disparador se ejecuta despus


de modificar cada fila afectada por la
instruccin disparador.

Los disparadores de tipo BEFORE se usan normalmente en las siguientes situaciones:


-

Cuando la accin disparador debe determinar si se ejecuta o no la instruccin disparador.

Para obtener valores de columnas especficos antes de ejecutar una instruccin disparador
INSERT o UPDATE.

Los disparadores de tipo AFTER se usan normalmente en las siguientes situaciones:


-

Cuando se quiere que la instruccin disparador termine su ejecucin antes de ejecutar la


accin disparador.

Si hay definido un disparador BEFORE, se puede definir un disparador AFTER que


realice acciones diferentes sobre la misma instruccin disparador.

El siguiente ejemplo muestra distintas posibilidades de disparador. Aparece una nueva


instruccin que permite crear un paquete (objeto que permite agrupar procedimientos,
funciones y datos como una unidad y que estudiaremos en el prximo tema) de nombre stat y
que solo contiene la declaracin pblica de la variable numrica [Link].
DROP TABLE stat_tab ;
CREATE TABLE Stat_tab (utype CHAR(8),
rowent INTEGER,
uhour INTEGER);
CREATE OR REPLACE PACKAGE stat IS
rowent INTEGER;
END;
/
CREATE TRIGGER bt BEFORE UPDATE OR DELETE OR INSERT ON sal
BEGIN
[Link] :=0;
END;
/
Dep. Informtica

50

I.E.S. TRASSIERRA - Crdoba

PL/SQL

CREATE TRIGGER rt BEFORE UPDATE OR DELETE OR INSERT ON sal FOR EACH ROW
BEGIN
[Link] := [Link] + 1 ;
END ;
/
CREATE TRIGGER at AFTER UPDATE OR DELETE OR INSERT ON sal
DECLARE
typ CHAR(8);
hour NUMBER ;
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 + [Link]
WHERE
utype = typ AND uhour = hour;
IF SQL%ROWCOUNT = 0 THEN
INSERT INTO stat_tab VALUES ( typ, [Link], hour );
END IF ;
EXCEPTION
WHEN dup_val_on_index THEN
UPDATE
stat_tab
SET
rowent = rowent + [Link]
WHERE
utype = typ AND uhour = hour ;
END ;
/

3.4.- MODIFICACIN Y BORRADO DE [Link] disparador no se puede modificar explcitamente, debe reemplazarse con una nueva
definicin de disparador.
Para reemplazar un disparador en CREATE TRIGGER se incluye la opcin OR REPLACE
que permite crear una nueva versin de un disparador que ya existe en la base de datos, sin
que se vean afectados los privilegios que tena el disparador antiguo.
En caso de que en vez de usar la opcin OR REPLACE, borremos el disparador y
posteriormente lo creemos de nuevo con las modificaciones necesarias, todos los privilegios
del disparador antiguo se habrn borrado y debern volverse a otorgar al disparador nuevo.
Un disparador se puede encontrar habilitado o inhabilitado. Solo en el caso de estar
habilitado, ORACLE lo dispara siempre que se ejecuta una instruccin disparador y la
restriccin disparador (si existe) es evaluada TRUE. Cuando se crea un disparador, ORACLE
automticamente lo habilita. Es til inhabilitar temporalmente un disparador cuando:
-

Se referencia un objeto que no est disponible.

Se va a cargar una gran cantidad de datos y se quiere realizar rpidamente sin que se
disparen los disparadores.

Se est recargando datos.

Dep. Informtica

51

I.E.S. TRASSIERRA - Crdoba

PL/SQL

Para habilitar o inhabilitar disparadores usa el comando ALTER TRIGGER. Su sintaxis es:
ALTER TRIGGER disparador { ENABLE / DISABLE} ;
Otra forma es con el comando ALTER TABLE con las clusulas DISABLE y ENABLE y la
opcin ALL TRIGGERS de este comando. Ejemplo:
ALTER TABLE temple DISABLE ALL TRIGGERS

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, ste debe estar en nuestro esquema o disponer del privilegio del
sistema DROP ANY TRIGGER. Se usa el comando DROP TRIGGER, cuya sintaxis es:
DROP TRIGGER <disparador > ;

3.5.- MANEJO DE [Link] durante la ejecucin de un disparador se produce un error predefinido en el sistema o
definido por el usuario, entonces se anulan todas las actualizaciones realizadas por la accin
disparador as como el evento que la activ.
La sentencia RAISE_APPLICATION_ERROR (num_error, 'mensaje') provoca la ocurrencia
del error de nmero interno num_error y envia al usuario el mensaje 'mensaje'. (num_error
debe ser un nmero negativo comprendido entre 20000 y 20999). Un ejemplo de su uso
puede verse en el ejercicio resuelto 2.

3.6.-EJERCICIOS.3.6.1.- Ejercicios resueltos.- (usando la base de datos de ejemplo de oracle)


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
DEPT o modificar la clave primaria (deptno) de DEPT, se pongan a NULL todos los valores
relacionados de la tabla EMP:
CREATE TRIGGER dep_set_null
AFTER DELETE OR UPDATE OF deptno ON dept FOR EACH ROW
BEGIN
IF DELETING OR UPDATING AND :[Link] != :[Link] THEN
UPDATE emp SET [Link] = NULL
WHERE [Link] = :[Link] ;
END IF ;
END ;
/
Dep. Informtica

52

I.E.S. TRASSIERRA - Crdoba

PL/SQL

Las siguientes consultas muestran informacin sobre el disparador DEP_SET_NULL:


SELECT
FROM
WHERE
Rdo:

TRIGGER_TYPE

TRIGGERING_EVENT TABLE_NAME

AFTER EACH ROW

UPDATE OR DELETE

SELECT
FROM
WHERE
Rdo:

trigger_type, triggering_event, table_name


user_triggers
trigger_name='DEP_SET_NULL' ;
.

DEPT

trigger_body
user_triggers
trigger_name = 'DEP_SET_NULL' ;

TRIGGER_BODY

BEGIN
IF UPDATING AND :[Link] != :[Link] THEN
UPDATE emp SET [Link] = NULL
WHERE [Link] = :[Link] ;
END IF ;
END ;

El cuerpo del disparador se almacena en la tabla del diccionario en la columna trigger_body


de tipo long. Como la longitud de visualizacin de los campos long est predefinida en 80
caracteres, para ver mejor estos resultados deberamos aumentarla mediante el comando SET
LONG 4000.

2.- Crear el disparador instruccin BEFORE llamado EMP_DATE_CAMBIOS que


controlar que las modificaciones en los registros de empleados de la tabla EMP slo se
realicen en horas y das laborables.
CREATE TRIGGER scott.emp_date_cambios
BEFORE DELETE OR INSERT OR UPDATE ON [Link]
BEGIN

/*Si hoy es sabado o domingo se devuelve un error*/


IF ( TO_CHAR( sysdate, 'DY' ) = 'SB' OR TO_CHAR( sysdate, 'DY' ) = 'DOM' )
THEN RAISE_APPLICATION_ERROR( -20501,
'No pueden actualizarse datos de empleados en fin de semana') ;
END IF;
/* Si la actualizacin no se hace entre las 8.00 y las 18.00 h, se devuelve un error */
IF ( TO_CHAR( sysdate, 'HH24' )< 8 OR TO_CHAR( sysdate, 'HH24' ) >= 18 )
THEN RAISE_APPLICATION_ERROR( -20502,
'Solo se puede actualizar datos de empleados durante las horas de trabajo') ;
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:
1.- Si la modificacin se intenta realizar un sbado o un domingo, el
disparador no permite la modificacin y da un mensaje de error.
2.- Si la hora en que se intenta modificar no est entre las 8:00 AM y las
6:00 PM, el disparador da un mensaje de error.

Dep. Informtica

53

I.E.S. TRASSIERRA - Crdoba

PL/SQL

3.- Este ejemplo crea un disparador fila BEFORE llamado VALIDA_SALARIO. El


disparador garantizar que siempre que un empleado nuevo se aada a la tabla de empleados
EMP, o se modifique el salario o el tipo de trabajo de un empleado, el salario del empleado se
mantiene dentro del rango establecido en SAL_GUIDE para su categora. La tabla
SAL_GUIDE deberemos crearla:
DROP TABLE SAL_GUIDE;
CREATE TABLE SAL_GUIDE (JOB VARCHAR2(9) primary key,
MINSAL NUMBER(7,2),
MAXSAL NUMBER(7,2) ) ;
INSERT INTO SAL_GUIDE VALUES ('CLERK', 800, 1300);
INSERT INTO SAL_GUIDE VALUES ('ANALYST', 3000, 3500);
INSERT INTO SAL_GUIDE VALUES ('SALESMAN', 1250, 1600);
INSERT INTO SAL_GUIDE VALUES ('MANAGER', 2450, 2975);
INSERT INTO SAL_GUIDE VALUES ('PRESIDENT', 5000, 5500);
CREATE OR REPLACE TRIGGER scott.valida_salario BEFORE INSERT OR UPDATE OF sal, job
ON [Link] FOR EACH ROW
DECLARE
v_minsal
sal_guide.minsal%TYPE;
v_maxsal
sal_guide.maxsal%TYPE;
BEGIN
/* Calcula en menor y mayor salario de esa categora de la tabla SAL_GUIDE*/
SELECT
minsal, maxsal
INTO
v_minsal, v_maxsal
FROM
sal_guide
WHERE
job = :[Link];
/* Si el salario del empleado cae fuera del rango, se provoca un error*/
IF (:[Link]< v_minsal OR :[Link] > v_maxsal) THEN
RAISE_APPLICATION_ERROR( -20601,
'Salario ' ||:[Link] || ' fuera de rango de la categoria ' ||
:[Link] || ' para el empleado ' || :[Link] ) ;
END IF;
END;
/

ORACLE dispara el disparador siempre que se ejecute una de las siguientes instrucciones:
-

Una instruccin INSERT que aada una fila a la tabla EMP.


Una instruccin UPDATE que modifique los valores de las columnas SAL o JOB de
la tabla EMP.

El disparador realiza las siguientes operaciones:


1.- Consulta la tabla de salarios para obtener el salario mximo y mnimo.
2.- Compara el salario del empleado con el salario mximo y mnimo.
3.- Si el salario del empleado no est dentro del rango, el disparador d un mensaje de
error y aborta la actualizacin.

3.6.2.- Ejercicios propuestos.1.- Partiendo del ejercicio resuelto 2, desarrollar el disparador TR_TEMPLE para que
funcione con la tabla Temple, mejorndolo para que tambin evite las actualizaciones en los
das de fiesta. Para ello deber crearse la tabla FESTIVOS con una nica columna Fiestas
contendra las fechas de los das no laborables distintos a sbados y domingos. Lgicamente
esta tabla se actualizara anualmente.
Dep. Informtica

54

I.E.S. TRASSIERRA - Crdoba

PL/SQL

2.- Crear el disparador DIR_SET_NULL, que controle que antes de borrar un empleado que
sea director ponga a nulo el campo direc del departamento o departamentos de los que era
director, y que si se modifica la clave primaria de un director, actualice automticamente el
campo direc de los departamentos en los que l es director.

3.- Crear el disparador DEP_DEL_CASCADE que permita que antes de borrar un


departamento se borren todos los empleados del mismo.

4.- Sobre la tabla TDEPTO, 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'.

5.- Crear el disparador DIRPRO que evite que un director lo sea en propiedad en ms de un
departamento. Ojo, problema de las tablas mutantes.
Caso de que se intente violar la anterior restriccin, el disparador devolver el cdigo de error
-20800, y el mensaje 'El jefe ya lo es en propiedad de otro departamento.'

6.- 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:
- Se encuentren comprendidos entre el valor de minsal y maxsal de su categora (JOB).
- Que no disminuyan.
- Que no se vean incrementados en ms del 10 % de una vez.
El tratamiento de los errores se har con RAISE_APPLICATION_ERROR.

Dep. Informtica

55

También podría gustarte