0% encontró este documento útil (0 votos)
608 vistas91 páginas

PLSQL: Guía Completa y Ventajas

Este documento describe las características y funcionalidades del lenguaje PL/SQL. Explica los tipos de datos soportados, incluyendo escalares como números enteros y cadenas, y compuestos como registros y tablas. También cubre estructuras de control como condicionales if/then/else y bucles for y while, y el manejo de cursores y errores. El objetivo general es proporcionar una introducción al uso de PL/SQL para el desarrollo de aplicaciones.
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)
608 vistas91 páginas

PLSQL: Guía Completa y Ventajas

Este documento describe las características y funcionalidades del lenguaje PL/SQL. Explica los tipos de datos soportados, incluyendo escalares como números enteros y cadenas, y compuestos como registros y tablas. También cubre estructuras de control como condicionales if/then/else y bucles for y while, y el manejo de cursores y errores. El objetivo general es proporcionar una introducción al uso de PL/SQL para el desarrollo de aplicaciones.
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

Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE

PLSQL - 161 - Mario Juncos Murcia


TEMA PLSQL


Introduccion ...................................................................................................................... 164
Relacion Entre Sql Y Pl/Sql ............................................................................................... 164
Ventajas De Pl/Sql ............................................................................................................. 164
Estructura De Bloques....................................................................................................... 165
Ambito De Visibilidad ....................................................................................................... 166
Soporte De Sql .................................................................................................................. 167
Tipos De Datos ................................................................................................................. 168
Escalares ........................................................................................................................ 168
Binary-Integer ............................................................................................................. 168
Number ....................................................................................................................... 168
Char .................................................................................................................................. 169
Varchar2 ........................................................................................................................... 169
Long ................................................................................................................................. 169
Raw .................................................................................................................................. 169
Long Raw ......................................................................................................................... 170
Boolean ............................................................................................................................. 170
Date .................................................................................................................................. 170
Rowid ............................................................................................................................... 170
Conversiones Implcitas Entre Tipos De Datos ................................................................. 171
Rowid ............................................................................................................................... 171
7.2 Compuestos ................................................................................................................. 173
Registros ........................................................................................................................... 173
Atributo %Rowtype: ......................................................................................................... 173
Registros Explicitos ........................................................................................................... 174
Registros Anidados............................................................................................................ 175
Tablas(Arrays) ................................................................................................................... 175
8.- Variables, Constantes Y Registros .................................... Error! Marcador no definido.
Variables ............................................................................... Error! Marcador no definido.
Constantes ......................................................................................................................... 172
Declaraciones Con Atributos ............................................................................................. 172
Atributo %Type: ............................................................................................................... 172
9.- Comentarios De Programador ...................................................................................... 172
10.- Comparaciones Logicas .............................................................................................. 183
11.- Control Condicional ................................................................................................... 183
Sentencia If ... Then ... Else ... End If ................................................................................ 183
12.- Control Iterativo ........................................................................................................ 184
Sentencia Loop: ................................................................................................................ 184
Bucles For ......................................................................................................................... 184
Bucles While ..................................................................................................................... 185
Sentencia Exit ................................................................................................................... 185
Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 162 - Mario Juncos Murcia
Sentencia Goto .................................................................................................................. 186
13.- Manejo De Cursores ................................................................................................... 190
Cursores Explicitos............................................................................................................ 190
Cursor ............................................................................................................................... 190
Open ................................................................................................................................. 191
Fetch ................................................................................................................................. 191
Close ................................................................................................................................. 191
Atributos Predefinidos Para Cursores ................................................................................ 192
%Notfound ....................................................................................................................... 192
%Found ............................................................................................................................ 192
%Rowcount ...................................................................................................................... 192
%Isopen ............................................................................................................................ 193
Bucles For Para Cursores .................................................................................................. 193
El Cursor Implicito Sql ...................................................................................................... 194
Sql%Notfound .................................................................................................................. 194
Sql%Found ....................................................................................................................... 194
Sql%Rowcount ................................................................................................................. 194
Sql%Isopen ....................................................................................................................... 194
15.- Manejo De Errores ..................................................................................................... 199
Declaracion: ...................................................................................................................... 199
Elevacion: ......................................................................................................................... 199
Manejo: ............................................................................................................................. 200
Excepciones Predefinidas ................................................................................................... 201
Dup_Val_On_Index .............................................................. Error! Marcador no definido.
Invalid_Cursor....................................................................... Error! Marcador no definido.
Invalid_Number ..................................................................... Error! Marcador no definido.
Login_Denied ........................................................................ Error! Marcador no definido.
No_Data_Found .................................................................... Error! Marcador no definido.
Not_Logged_On ................................................................... Error! Marcador no definido.
Program_Error ...................................................................... Error! Marcador no definido.
Storage_Error ....................................................................... Error! Marcador no definido.
Timeout_On_Resource .......................................................... Error! Marcador no definido.
Too_Many_Rows .................................................................. Error! Marcador no definido.
Value_Error .......................................................................... Error! Marcador no definido.
Zero_Divide .......................................................................... Error! Marcador no definido.
Others ................................................................................... Error! Marcador no definido.
Encapsulamiento De Errores Oracle ...................................... Error! Marcador no definido.
Sqlcode: ................................................................................ Error! Marcador no definido.
Sqlerrm: ................................................................................ Error! Marcador no definido.
14.- Subprogramas ............................................................................................................ 209
Procedimientos .................................................................................................................. 209
Funciones .......................................................................................................................... 210
Declaracion Diferida .......................................................................................................... 211
Notacion Posicional Y Nominal ......................................................................................... 211
Valores Por Defecto Para Los Argumentios ....................................................................... 212
Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 163 - Mario Juncos Murcia
Sobrecarga ........................................................................................................................ 212
RECURSIVIDAD ............................................................................................................. 213

Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 164 - Mario Juncos Murcia
INTRODUCCION
PL/SQL consiste en un lenguaje recubrimiento de SQL que dota a este de las capacidades clsicas
de los lenguajes procedurales o procedimentales, como estructuras de bucle, saltos condicionales,
variables, asignaciones, etc. Combina la potencia de SQL para manipulacin de datos con la
capacidad para procesamiento de estos de los lenguajes procedimentales.
Se trata de una herramienta fundamental para aquellos programadores que desarrollen
aplicaciones para el Sistema de Bases de Datos Relacionales ORACLE

RELACION ENTRE SQL Y PL/SQL
PL/SQL es una extensin de SQL. Por tanto, permite utilizar todas las sentencias SQL para
manejo de informacin, como INSERT, UPDATE, DELETE, SELECT, etc. Adicionalmente
permite la utilizacin de estructuras procedimentales:
- Estructuras de flujo de control como:
IF ... THEN ... ELSE,
EXIT y
GOTO.
- Estructuras repetitivas como:
FOR ... LOOP y
WHILE ... LOOP
- Sentencias de asignacin como:
X := y + Z

VENTAJAS DE PL/SQL
Entre otras, PL/SQL ofrece las siguientes caractersticas:
Capacidad procedimental
Permite el uso de estructuras procedimentales clsicas como bucles, flujo condicional,
asignaciones, etc.
Aumento de la eficiencia del sistema
Sin PL/SQL cada sentencia SQL se traduce en una llamada a ORACLE, con el consecuente
aumento de trfico de informacin. Por el contrario, un bloque PL/SQL (formado por un conjunto
de sentencias procedimentales mas sentencias SQL) se traduce en una nica llamada.
PL/SQL es fcilmente integrable con el resto de las herramientas ORACLE como Forms.
Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 165 - Mario Juncos Murcia
Portabilidad
Las aplicaciones escritas en PL/SQL son portabas a cualquier sistema informtico y cualquier
sistema operativo, con la nica condicin de que ejecuten el Sistema de Bases de Datos
Relacionales ORACLE.
Alta integracin con ORACLE
PL/SQL permite el acceso al Diccionario de Datos ORACLE de tal manera que la consistencia de
tipos de datos esta asegurada. Es el caso del atributo %TYPE, que permite definir variables del
mismo tipo que tenga determinada columna de una tabla.

ESTRUCTURA DE BLOQUES
La unidad mnima ejecutable de PL/SQL es el BLOQUE. Cada bloque esta dividido en tres partes:
Seccin DECLARATIVA Contiene la declaracin de constantes, variables, etc.
Seccin EJECUTABLE Contiene las sentencias a ejecutar.
Seccin de MANEJADORES DE EXCEPCION Contiene las sentencias de manejo de errores.
La Seccin EJECUTABLE es obligatoria, mientras que las otras dos son opcionales.
Cada bloque puede, a su vez, contener otros bloques, a los que llamaremos sub-bloques. Los
sub-bloques se declaran en la parte ejecutable.

BLOQUE PL/SQL
DECLARE
...
Sentencias de Declaracin
...
BEGIN
...
Sentencias Ejecutables
...
EXCEPTION
...
Manejadores de Excepciones
END;
Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 166 - Mario Juncos Murcia
EJEMPLO DE UN BLOQUE PL/SQL
DECLARE
V_cantidad NUMBER (5);
BEGIN
SELECT cantidad INTO v_cantidad
FROM inventario
WHERE producto ='RAQUETA'
IF v_cantidad > 0 THEN
UPDATE inventario
SET cantidad = cantidad - 1
WHERE producto ='RAQUETA';
INSERT INTO registro VALUES ('RAQUETA VENDIDA', SYSDATE);
ELSE
INSERT INTO registro VALUES ('RAQUETA SIN STOCK, SYSDATE);
END IF;
COMMIT;
EXCEPTION
WHEN NO_DATA_FOUND THEN
INSERT INTO registro VALUES( No existe la raqueta, SYSDATE);
COMMIT;
END;

AMBITO DE VISIBILIDAD
En PL/SQL un identificador denota cualquier objeto, como constantes, variables, registros,
cursores o excepciones. El mbito de visibilidad de un identificador determina qu bloques pueden
referenciarlo, es decir, para qu bloques es visible un identificador u objeto.
Los identificadores declarados en un bloque son locales a este y globales a todos sus sub-bloques.
Los identificadores globales pueden ser declarados de nuevo en un sub-bloque. En este caso el
sub-bloque pierde el acceso al objeto denotado por el identificador del padre, a menos que se
utilicen etiquetas para resolver la ambigedad del nombre.
Un bloque no puede referenciar identificadores de otros bloques anidados al mismo nivel (bloques
hermanos), pues estos identificadores no son ni locales, ni globales.
Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 167 - Mario Juncos Murcia
EJEMPLO
<< bloque_padre >>
DECLARE
fecha DATE;
BEGIN
...
<<bloque_hijo >>
DECLARE
fecha DATE;
fecha1 DATE;
BEGIN
...
IF fecha = bloque_padre.fecha THEN
....
END IF;
END bloque_hijo;
...
DECLARE
fecha2 DATE;
BEGIN
...
IF fecha2 = fecha1 THEN
........... -- NO PERMITIDO!!!
END IF;
END;
END bloque_Padre;

SOPORTE DE SQL
Toda la potencia de SQL es soportada por PL/SQL, en particular:
Sentencias SQL de manipulacin de datos:
SELECT
INSERT
UPDATE
DELETE
- Sentencias SQL para procesamiento de transacciones:
Una transaccin es una secuencia de instrucciones SQL que ORACLE trata como una operacin
atmica, es decir, o se completa entera o no se ejecuta en absoluto. Las sentencias son:

Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 168 - Mario Juncos Murcia
COMMIT
SAVEPOINT
ROLLBACK
- Funciones SQL
Numricas
De Caracteres
De Fecha
De Grupo
De conversin de datos
- Predicados SQL
PL/SQL permite el acceso a todos los predicados del lenguaje SQL formados con los siguientes
operadores:
Operadores de comparacin (=, >, <, >=, etc.)
BETWEEN
IS [NOT] NULL
[NOT] LIKE
EXISTS


TIPOS DE DATOS
Estn los escalares y los compuestos ( tablas y arrays)

ESCALARES
BINARY-INTEGER Permite almacenar nmeros enteros con signo en el rango
NUMBER Permite almacenar nmeros, (enteros y fraccionarios en coma fija o en coma flotante).
La sintaxis es: NUMBER [(precisin [,escala])]. Los valores son redondeados siempre a la cifra
indicada por la escala
NUMBER (5,2)... 26,314 -> 26,31
NUMBER (7,-3)... 2412 ---> 2000
Subtipos de NUMBER:
DEC DECIMAL DOUBLE PRECISION
FLOAT INTEGER INT
NUMERIC REAL SMALLINT
Los subtipos de NUMBER ofrecen el mismo rango y precisin que NUMBER. Se ofrecen por
compatibilidad con otros gestores de datos.

Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 169 - Mario Juncos Murcia
CHAR
Permite almacenar cadenas de caracteres de longitud fija. La representacin interna depende del
juego de caracteres (ASCII, EBCDIC, etc.). La sintaxis es: CHAR [(long_max)]
donde long_max debe estar en el rango 1 .. 32.767. Una columna CHAR admite como mximo
255 bytes.
Subtipos de CHAR:
CHARACTER STRING
Soportan los mismos valores y se ofrecen solo por compatibilidad con otros gestores de datos

VARCHAR2
Permite almacenar cadenas de caracteres en formato variable. La sintaxis es: VARCHAR2
[(long_max)]
donde long_max debe estar en el rango 1 .. 32.767. Una columna VARCHAR2 admite como
mximo 2000 bytes.
Subtipos de VARCHAR2: VARCHAR
Se ofrece por compatibilidad con otros gestores y en especial con el estndar ANSI/SQL, pero
sus caractersticas son las mismas que VARCHAR2.

LONG
Permite almacenar hasta 32.760 bytes en formato carcter. La sintaxis es: LONG
Una columna LONG puede almacenar hasta 2Gb.
Cualquier valor de tipo LONG puede ser insertado en una columna LONG, pero la inversa no es
siempre cierta.

RAW
Permite almacenar hasta 32.767 bytes. La sintaxis es: RAW
A diferencia de los valores CHAR o VARCHAR, para los datos RAW el juego de caracteres no
es relevante. Este tipo es utilizado para almacenar secuencias grficas, imgenes digitalizadas, etc.
Las columnas RAW solo admiten 255 bytes.
Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 170 - Mario Juncos Murcia
LONG RAW
Permiten almacenar secuencias de hasta 32.760 bytes. La sintaxis es: LONG RAW
Una columna LONG RAW admite hasta 2Gb.

BOOLEAN
Solo admite los valores: TRUE, FALSE, NULL
SINTAXIS: BOOLEAN
El tipo BOOLEAN no est disponible para columnas de la Base de Datos.

DATE
Permite almacenar fechas en el rango 1- 1 -4.712 a.C. .. 31-12-4.712 d.C.
SINTAXIS: DATE

ROWID
Admite valores tipo ROWID. El ROWID de una fila identifica su posicin fsica en disco.
SINTAXIS: ROWID
FORMATO: [Link]
Donde:
BBBBBBBB es el bloque de disco
RRRR es la posicin de la fila dentro del bloque
FFFF es el nmero de fichero fsico donde est la fila.
(todos en hexadecimal)
Aunque los valores ROWID de la Base de Datos se almacena en un formato interno de 6 bytes, el
tipo ROWID de PL/SQL es un subtipo de CHAR.
Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 171 - Mario Juncos Murcia
CONVERSIONES IMPLCITAS ENTRE TIPOS DE DATOS

A
De
Binary
Integer
CHAR DATE LONG NUMBER RAW ROWID VARCHAR2
Binary Integer S S S S
CHAR S S S S S S S
DATE S S S
LONG S S
NUMBER S S S S S
RAW S S S
ROWID S S
VARCHAR2 S S S S S S S

VARIABLES
Su uso mas comn esta relacionado con el almacenamiento de valores para un tratamiento
posterior o para calcular valores que sern introducidos en las tablas de la Base de Datos.
Desde el punto de vista sintctico, pueden usarse en cualquier lugar donde se pueda colocar una
expresin.
Declaracin:
Las variables pueden ser de cualquiera de los tipos nativos de ORACLE (como NUMBER,
CHAR, o DATE) o particular de PL/SQL (como BOOLEAN). La longitud mxima del
identificador (de cualquier objeto) es de 30 caracteres, debiendo de empezar siempre por un
carcter y sin distinguir entre maysculas y minsculas.
Ejemplos:
bonificacion NUMBER (11,2);
en_stock BOOLEAN;
Las variables pueden asignarse en tiempo de declaracin como en:
bonificacion NUMBER(4,2):=37.56;
en_stock BOOLEAN DEFAULT TRUE;

Asignacin:
Existen dos vas de asignacin para las variables PL/SQL:
- Operador de asignacin
total := precio + iva;
comisin := salario * 0.10;

Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 172 - Mario Juncos Murcia
- A travs de SELECT ... INTO:
SELECT salario INTO salario_actual
FROM empleados
WHERE nombre ='ARENAS';

CONSTANTES
La declaracin de constantes se realiza exactamente igual que la de variables, a excepcin de la
palabra reservada CONSTANT:
- Ejemplo:
incr CONSTANT NUMBER(2);= 10;
La inicializacin en tiempo de declaraciones es lgicamente obligatoria.
La clusula DEFAULT tambin est disponible:
incr CONSTANT NUMBER(2) DEFAULT 10;

DECLARACIONES CON ATRIBUTOS
La utilizacin de atributos facilita la declaracin de variables, accediendo directamente al
Diccionario de Datos.
Atributo %TYPE:
El atributo %TYPE permite obtener el tipo de dato de una columna determinada de la Base de
Datos, variable o constante:
Titulo libros.titulo_libro%TYPE;
var1 Number(7);
var2 var1%TYPE;
La variable 'titulo' obtiene como tipo de dato el mismo que tenga la columna 'titulo_lbro' de la
tabla 'libros'.
Este tipo de declaraciones ayuda a la transparencia del cdigo, as como a la portabilidad y
consistencia de este.

COMENTARIOS DE PROGRAMADOR
Los comentarios de programador en PL/SQL tienen dos formatos diferentes:
Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 173 - Mario Juncos Murcia
- Al estilo de C:
/* Esto es un comentario
/* Esto, que ocupa mas de
una lnea, tambin lo es */
- Al estilo de Ada:
-- Esto es un comentario
--El doble guin solo
-- afecta a una lnea


COMPUESTOS
REGISTROS
En PL/SQL un registro es una variable formada por la unin de varios campos.

Atributo %ROWTYPE:
El atributo %ROWTYPE se utiliza para que una variable de tipo registro obtenga la misma
estructura que una fila (o parte de ella) de una tabla determinada.
- Ejemplos:
un_emp empleados%ROWTYPE;
implcitamente un_emp tiene la misma estructura que la tabla empleados, as tendramos
un_emp.num_empleado, un_emp.nombre, etc.
DECLARE
un_emp emp%ROWTYPE;
Cuando se ejecute:
SELECT * INTO un_emp
FROM empleados;
los campos del registro toman los valores de las columnas indicadas y dichos campos se pueden
referenciar como:
total_sal := total_sal + un_emp.salario
Los valores de los campos pueden ser cambiados segn la sintaxis:
nombre_reg.nombre_campo := exp
Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 174 - Mario Juncos Murcia
como en: un_emp.salario := 0;
REGISTROS EXPLICITOS
Adicionalmente, se pueden declarar registros explcitos, como en la mayora de los lenguajes de
30 Generacin.
La declaracin de una variable de tipo registro se apoya en la declaracin de un nuevo tipo con la
sintaxis. Primero hay que definir la estructura del registro y despus variables de ese tipo de
registro.
TYPE nuevo_tipo IS RECORD
( tipo_base
variable%TYPE
Campo1 [Link]%TYPE [NOT NULL] [:= valor],
tabla%ROWTYPE

Campo2...
);

Ejemplo:
TYPE emp_sal IS RECORD
( num-emp NUMBER(4) NOT NULL,
nombre [Link]%TYPE,
salario [Link]%TYPE);

Permiten inicializacin en tiempo de declaracin:
TYPE ventas IS RECORD
( hardware NUMBER(8) := 0,
software NUMBER(10):= 0,
servicios NUMBER(9) := 0);
Las variables se declaran asociadas al tipo:
un_emp emp_sal;
otro_emp emp_sal;
ventas_enero ventas;
Los campos se referencian con la notacin nominal ya vista:
un_emp.salario := 7500;
ventas_enero.hardware = 10.500;
SELECT num_emp, nombre, salario INTO un_emp
FROM empleados
Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 175 - Mario Juncos Murcia
WHERE num_emp = 7902;
La asignacin global tambin est permitida:
otro_emp := un_emp;

REGISTROS ANIDADOS
Un nuevo tipo est disponible para su uso, incluso en la declaracin de tipos adicionales:
ejemplo:
TYPE cuenta_cliente IS RECORD
(nombre VARCHAR2(30),
comercial NUMBER(4),
cuenta ventas);
mi_cliente cuenta_cliente;
al definir mi_cliente del tipo cuenta_cliente puedo hacer referencia a:
mi_cliente.nombre :='CHIPS, S.A.';
mi_cliente.comercial := 7902;
mi_cliente.[Link]:= 299814;

TABLAS(ARRAYS)
El tipo TABLE es, como los registros, un tipo compuesto PL/SQL. A diferencia de los 'arrays' de
otros lenguajes de programacin las tablas de PL/SQL (no confundirlas con las tablas de la Base
de Datos) no reservan el espacio en memoria estticamente, sino que crecen a medida que se
ocupan sus elementos.
Actualmente las tablas PL/SQL solo pueden tener dos columnas. Una ha de ser de tipo
BYNARY_INTEGER y acta como ndice, y otra de cualquier tipo escalar. La sintaxis es:
tipo
TYPE tipo_tabla IS TABLE OF variable%TYPE [NOT NULL]
[Link]%TYPE
registro/tabla%ROWTYPE
INDEX BY BINARY_INTEGER;

Ejemplo:
TYPE tabla_nombre IS TABLE OF [Link]%TYPE
INDEX BY BINARY_INTEGER;
Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 176 - Mario Juncos Murcia
Una vez definido el tipo tabla pasamos a definir tablas
mi_tabla tabla_nombre;
otra_tabla tabla_nombre;
Por la indexacin con el tipo BINARY_INTEGER la tabla tiene el rango -(2
31
- 1) a 2
31
- 1
Ejemplo: mi_tabla(7902) := 'FORD';
pero tambin ser vlido: mi_tabla(-100514) := 'JIMENEZ';
La asignacin global tambin est permitida: otra_tabla := mi_tabla;

Atributos de tablas PL/SQL
Los atributos de las tablas facilitan la gestin de las variables de tipo TABLE permitiendo
recorrer la tabla, contar y borrar los elementos. En general, para utilizar los atributos se empleara
el siguiente formato:
[Link][(parmetros)]
Los parmetros harn referencia a valores de ndice:
- FIRST. Devuelve el valor (BINARY_INTEGER) de la clave o ndice del primer elemento
de la tabla.
o Formato: [Link]
- LAST. Devuelve el valor (BINARY_INTEGER) de la clave o ndice del ultimo elemento
de la tabla.
o Formato: [Link]
Por ejemplo, para recorrer una tabla cuyo ndice sabemos que tiene valores
consecutivos podemos escribir:
FOR i IN [Link] .. [Link] LOOP

- PRIOR. Devuelve el valor (BINARY_INTEGER) de la clave o ndice del elemento
anterior al elemento n.
o Formato: [Link](n)
- NEXT. Devuelve el valor (BINARY_INTEGER) de la clave o ndice del elemento
posterior al elemento n.
o Formato: [Link](n)
Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 177 - Mario Juncos Murcia
PRIOR y NEXT se pueden utilizar para recorrer una tabla (en cualquiera de los dos sentidos) con
valores de ndice no consecutivos. No obstante, deberemos tener cuidado con lo valores que
devolvern en ambos extremos, ya que PRIOR del primer elemento devuelve NULL y lo mismo
ocurre con NEXT del ultimo elemento.
i:= [Link]
WHILE i IS NOT NULL LOOP
..
i:= [Link](i);
END LOOP;

- COUNT. Devuelve el nmero de filas que tiene una tabla.
o Formato: [Link]
- EXISTS. Devuelve TRUE si existe el elemento n, en caso contrario devolver FALSE. Se
utiliza para evitar el error ORA_1403 que se produce cuando intentamos acceder a un
elemento que no existe en la tabla, lo cual levantara la excepcin NO_DATA_FOUND.
o Formato: [Link](n)
- DELETE. Se utiliza para borrar elementos de una tabla.
o [Link]. Borra todos los elementos de la tabla.
o [Link](n). Borra el elemento indicado por n. Si el valor de n es
NULL no har nada.
o [Link](nl, n2). Borra las filas comprendidas entre nl y n2, siendo
nl>=n2 (en caso contrario no har nada).
Una tabla se elimina al salir del mbito del programa en que se creo. No obstante, si quisiramos
eliminar todos los elementos de la tabla antes, en versiones que no disponen del atributo DELETE
podemos crear una tabla vaca y asignrsela a la tabla que queremos borrar:
Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 178 - Mario Juncos Murcia
DECLARE
TYPE T_tabla_emple IS TABLE OF emple%ROWTYPE
INDEX BY BINARY_INTEGER;
Tab_emple T_tabla_emple;
Tablavacia T_tabla_emple;
CURSOR c_emple IS SELECT * FROM emple;
BEGIN
..
/* El siguiente bucle carga en la tabla todas las filas de emple */
FOR v_reg_emple IN c_emple LOOP
Tab_emple(vreg_emple.emp_no):= vreg_emple;
END LOOP;

tab_emple := Tablavacia;
END;
Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 179 - Mario Juncos Murcia
Prctica 2
1 Evale las siguientes declaraciones. Determine cules de ellos no son legales, y
explique por qu.
DECLARE
v_id NUMBER(4);
v_x, v_y, v_z VARCHAR2(10);
v_birthdate DATE NOT NULL;
v_in_stock BOOLEAN :=1;

2. Determine el tipo de datos de las expresiones resultantes de las siguientes
asignaciones.
v_days_to_go := v_due_date - SYSDATE;
v_sender := USER || : TO_CHAR(v-dept_no);
v_sum := 100,000 + 250,000;
v_flag := TRUE;
v_n1 := v_n2 > (2 * v_n3);
v_value := NULL;

3. Cree un bloque annimo para imprimir la frase Mi Bloque PLSQLen la pantalla.
Mensaje
Mi Bloque PLSQL
En entorno de SQL> con VARIABLE nombre_variable tipo(escala) definimos una variable que
luego podremos usar en un bloque PLSQL como:
VARIABLE g_message VARCHAR2(30)
BEGIN
:g_message := Mi Bloque PLSQL; -- fijaros que hay que poner :nombre_variable
END;
PRINT g_message
Si queremos pedir por pantalla el valor de una variable, lo hacemos con ACCEPT. Este valor lo
podemos utilizar en un bloque PLSQL utilizando & como en:
ACCEPT p_num PROMPT 'Por favor Introduzca un nmero:
DECLARE
v_num1 NUMBER(9,2) := &p_num;
Los ACCEPT hay que ponerlos en el entorno SQL> y los bloques de codigo es preferible
escribirlos en un editor y despus con COPY PASTE pasarlos al entorno SQL>
Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 180 - Mario Juncos Murcia
SET SERVEROUTPUT ON Visualiza la salida a traves de
DBMS_OUTPUT.PUT_LINE(mensaje)
Prctica 3
DECLARE
V_weight NUMBER(3) :=600;
V_message VARCHAR2(255) := 'Product 11002';
BEGIN
DECLARE
V_weight NUMBER(3) := 1;
V_message VARCHAR2(255) := 'Product 11001';
v_new_locn VARCHAR2:= Europa;
BEGIN
V_weight := v_weight +1;
v_new_locn := Sur || v_new_locn ;
END
V_weight := v_weight +1;
V_message := V_message || esta en stock;
v_new_locn := Sur || v_new_locn ;
END;
1.- Observe el bloque PLSQL y determine los siguientes valores de acuerdo con las
reglas de mbito.
El valor de V_WEIGHT en el subbloque es
El valor de V_NEW_LOCN en el subbloque es
El valor de V_WEIGHT en el bloque principal es
El valor de V_MESSAGE en el bloque principal es
El valor de V_NEW_LOCN en el bloque principal es

2. Cree y ejecute un bloque PL/SQL que acepte dos nmeros por medio de variables de
SQL. Se debera dividir el primer nmero entre el segundo, y despus aadir el segundo
nmero al resultado. El resultado debera escribirse en una variable PLSQL e imprimirse en la
pantalla a travs de una variable de SQL
Por favor Introduzca el primer nmero: 2
Por favor Introduzca el segundo nmero: 4
PL/SQL procedure successfully completed.
V_RESULT
4.5
Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 181 - Mario Juncos Murcia
3.- Genere un bloque PLSQL que calcule la comisin total para un ao. El salario anual
y el porcentaje anual de comisin se pasarn al bloque PLSQL a travs de variables de
sustitucin SQL y el importe de las comisiones tendr que ser convertido de un nmero entero a
un decimal (por ejemplo, 15 a 0.15). Si el salario es nulo, asgnele cero antes de calcular la
compensacin total.
Utilizar la funcin NVL para gestionar los valores nulos. (Para comprobar el caso de la funcin
NVL, necesitaremos escribir NULL en el prompt; ya que pulsar [Return] provoca un error.)
Por favor introduzca el salario: 50000
Por favor introduzca el porcentaje: 10
PL/SQL procedure successfully completed.
G_TOTAL
55000
Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 182 - Mario Juncos Murcia
Prctica 4
1.- Cree un bloque PLSQL que seleccione el departamento con el nmero ms alto de la
tabla DEPT y lo almacene en una variable SQL. Imprima los resultados en la pantalla. Guarde
su bloque PLSQL en un archivo llamado [Link].
2.- Cree un bloque PLSQL que inserte un nuevo departamento en la tabla DEPT.
Guarde su bloque PLSQL en un archivo llamado [Link].
Utilice el nmero del departamento recuperado del ejercicio 1 y aada 10 al nmero como
nmero de departamento de entrada para el nuevo departamento.
Cree un parmetro para el nombre del departamento.
Por el momento deje la ubicacin como nula.
Ejecute el bloque PLSQL.
Introduzca el nombre del departamento: EDUCACION
PL/SQL procedure successfully completed.
Muestre el nuevo departamento que ha creado.
DEPTNO DNAME LOC
50 EDUCATION

3.- Cree un bloque PLSQL que actualice la ubicacin de un departamento existente.
Guarde el bloque PLSQL es un archivo llamado [Link].
Cree un parmetro para el nmero del departamento.
Cree un parmetro para la ubicacin del departamento.
Compruebe el bloque PLSQL.
Introduzca el numero de departamento : 50
Introduzca la localidad del departamento: HOUSTON
Muestre el nmero de departamento el nombre del departamento y la ubicacin del
departamento actualizado.
DEPTNO DNAME LOC
50 EDUCATION HOUSTON
4. Cree un bloque PLSQL que suprima el departamento creado en el ejercicio 2. Guarde
el bloque PLSQL en un archivo llamado [Link].
Cree un parmetro para el nmero de departamento.
Imprima en la pantalla el nmero de filas afectadas.
Compruebe el bloque PLSQL.
Qu pasa si introduce un nmero de departamento que no existe?
Confirme que el departamento ha sido suprimido.
Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 183 - Mario Juncos Murcia
COMPARACIONES LOGICAS
PL/SQL soporta la comparacin de variables y constantes en las sentencias SQL y PL/SQL.
Generalmente estn compuestas de expresiones simples unidas a travs de operadores ( <, >, =,
!=, >=, <= ), y reciben el nombre de Expresiones Booleanas.
Las Expresiones Booleanas en PL/SQL, siempre toman valores CIERTO, FALSO o NULO
(TRUE, FALSE o NULL). En caso de utilizarse para control condicional, el valor NULO se
considera como FALSO. Existen tres tipos de Expresiones Booleanas:
- Numricas:
a > 7
2*a = b
b >= a
- De Carcter: Las comparaciones se realizan segn orden alfabtico.
nombre1 > nombre2
nombre1 ='SMITH'
tipo <> 'ORDENADOR'
- De Fecha: Las comparaciones se evalan en el tiempo.
fecha_nacimiento <'20-OCT-65'
hiredate = '27-NOV-87'

CONTROL CONDICIONAL
La sentencia IF ... THEN ... ELSE ... END IF permite controlar qu conjunto de instrucciones
se ejecutan, en funcin de una condicin. La sintaxis es:

IF <condicin> THEN
....
....
[ELSIF <condicin> THEN
...
...]
[ELSE
...
...]
END IF;
Si la condicin inicial es CIERTA, se ejecutan las instrucciones posteriores a THEN. Si es
FALSA, pueden evaluarse otras condiciones con la clusula ELSIF.
La clusula 'ELSE' provoca la ejecucin de las instrucciones que le siguen, caso de que ninguna
Solo hay un IF
Puede haber varios ELSIF ( puede que no
haya ninguno)
Slo puede haber un ELSE ( puede que
no haya ninguno)

Slo hay un END IF

Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 184 - Mario Juncos Murcia
condicin haya sido CIERTA.
Ejemplo:
DECLARE
saldo [Link]%TYPE;
cuenta CONSTANT NUMBER(1):= 3;
deuda CONSTANT NUMBER(2):= 50;
BEGIN
SELECT sal INTO saldo
FROM cuentas
WHERE num_cuenta = cuenta;
IF saldo >= deuda THEN
UPDATE cuentas
SET sal = sal - deuda
WHERE num_cuenta = cuenta;
ELSE
INSERT INTO temp VALUES (cuenta, saldo, deuda,'SIN FONDOS');
END IF;
END;
Si una SELECT recupera mas de una fila o ninguna se produce una excepcin.

CONTROL ITERATIVO
El control iterativo ofrece la posibilidad de repetir o saltar determinadas partes de un bloque
PL/SQL. Las sentencias asociadas son LOOP y GOTO.

Sentencia LOOP:
En su formato mas sencillo construye bucles infinitos:
LOOP
conjunto de sentencias
END LOOP;

Bucles FOR:
FOR var IN [REVERSE] ent1..ent2 LOOP
conjunto de sentencias
END LOOP;
Las sentencias internas al bucle se ejecutan tantas veces como indique el rango de enteros
expresado.
Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 185 - Mario Juncos Murcia
El ndice 'var' no tiene que declararse como variable, implcitamente recibe el tipo NUMBER y no
puede referenciarse fuera del bucle. Dentro de l y en cada iteracin, se comporta como una
constante: puede consultarse, pero no variar su valor.
Bucles WHILE:
Un bucle WHILE tiene asociado una condicin. Las instrucciones incluidas en el bucle se ejecutan
siempre que la condicin sea cierta. Lgicamente esta se evala en cada una de las iteraciones del
bucle. El bucle finaliza una vez que la condicin evaluada de como resultado FALSO o NULO.
WHILE (Condicin) LOOP
instrucciones
END LOOP;

DECLARE
Salario [Link]%TYPE;
jefe empleados.num_sup%TYPE;
nombre [Link]%TYPE;
ini CONSTANT NUMBER(4):=7902;
BEGIN
SELECT salario, num_sup INTO salario, jefe
FROM empleados
WHERE num_emp = ini;
WHILE salario < 4000 LOOP
SELECT salario, num_sup, nombre INTO salario, jefe, nombre
FROM empleados
WHERE num_emp = jefe;
END LOOP;
INSERT INTO temp VALUES (salario, nombre);
COMMIT;
END;

Sentencia EXIT:
La sentencia EXIT se puede utilizar en la parte interna de cualquier tipo de bucle, con la finalidad
de abortarlo prematuramente. Es esencial, particularmente, en los bucles infinitos.
LOOP
contador := contador + 1;
IF contador > 1000 THEN EXIT;
END IF;
...
END LOOP;
La sentencia EXIT tambin admite el formato:
Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 186 - Mario Juncos Murcia
EXIT WHEN condicin;
Sentencia GOTO:
La sentencia GOTO permite variar el flujo de ejecucin dentro de un bloque PL/SQL. Para
utilizarla es necesario etiquetar determinadas posiciones en el bloque.
Es factible bifurcar la ejecucin a cualquier etiqueta, siempre y cuando no se intente entrar en una
secuencia de instrucciones particular, desde fuera de ella (ej.: no se puede hacer GOTO a una
etiqueta interior a un bucle desde fuera de l).
Las etiquetas se referencian sintcticamente de la siguiente forma:
<< etiqueta >>
Ejemplo incorrecto:
...
GOTO mi_etiqueta;
IF a > b THEN
b := b - c;
<< mi_etiqueta >>
x := x + 1;
END IF;
Ejemplo correcto:
SELECT salario, comision, puesto INTO salario, comision, trabajo
FROM empleados
WHERE num_emp = 7902;
IF trabajo = 'VENDEDOR' THEN
bonificacion := comision * 2;
GOTO suma_bono;
END IF;
IF trabajo = 'CLERK' THEN
bonificacion := salario * 0.15;
GOTO suma_bono;
END IF;
....
<< suma_bono >>
total := total + bonificacion;
Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 187 - Mario Juncos Murcia
Prctica 5
1.-Crear la tabla MENSAGES (Con una columna llamada RESULTADOS de tipo
VARCHAR2(100)). Escriba un bloque PL/SQL para insertar nmeros en la tabla MENSAJES.
Inserte los nmeros 1 a 1 0 excepto 6 y 8.
Haga Commit antes del final del bloque.
Haga una seleccin en la tabla MENSAJES para verificar que funcion su bloque
PL/SQL.

RESULTADOS
1
2
3
4
5
7
9
10
2. Cree un bloque PLSQL que calcule el importe de comisin de un empleado,
basndose en el sueldo del empleado.
Acepte el nmero de empleado como entrada de usuario con un parmetro de sustitucin
SQL.
Si el sueldo del empleado es inferior a 1000, establezca el importe de comisin del
empleado en un 10% del sueldo.
Si el sueldo del empleado est entre 1000 y 1500, establezca el importe de comisin del
empleado en un 15% del sueldo.
Si el sueldo del empleado pasa de 1500, establezca el importe de comisin del empleado
en el 20% del sueldo.
Si el sueldo del empleado es NULL, establezca el importe de comisin del empleado en 0.
Haga commit.
Compruebe el bloque PLSQL para cada caso utilizando los siguientes casos de prueba, y
compruebe todas las comisiones actualizadas.
Nmero de empleado Sueldo Comisin resultante
7369 800 80
7934 1300 195
7499 1600 320
8000 NULL 0
Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 188 - Mario Juncos Murcia
3.- Aada una nueva columna en la tabla EMP para almacenar asteriscos (llamarla
ASTERISCOS)
4.- Cree un bloque PL/SQL que recompense a un empleado aadiendo un asterisco en la
columna ASTERISCOS por cada 100 del sueldo del empleado. Redondee el sueldo del
empleado hasta el nmero entero ms cercano. Guarde el bloque PL/SQL en un archivo
llamado p5q4. sql.
Acepte el Nmero del empleado como entrada del usuario con un parmetro de
sustitucin SQL.
Inicialice una variable que contenga una cadena vaca.
Aada un asterisco a la cadena por cada 100 del sueldo. Por ejemplo, si el empleado
tiene un sueldo de 800, la cadena de asteriscos contar con ocho asteriscos.
Actualice la columna ASTERISCOS del empleado con la cadena de asteriscos.
Haga commit.
Compruebe el bloque con un empleado que no tiene sueldo y con un empleado que tiene
sueldo.
Introduzca el nmero de empleado: 7934
PL/SQL procedure successfully completed.
Introduzca el nmero de empleado: 8000
PL/SQL procedure successfully completed.
EMPNO SAL ASTERISCOS
8000
7934 1300 *************
Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 189 - Mario Juncos Murcia
Prctica 6
1.- Crear una nueva tabla (llmala AYUDA)en la que almacenar empleados y sus
sueldos.
2. Escriba un bloque PLSQL para recuperar el nombre y el sueldo de un empleado
concreto de la tabla EMP basndose en el nmero del empleado. Utilice tablas PLSQL.
Declare dos tablas PLSQL, ENAME_TABLE y SAL_TABLE para almacenar
temporalmente los nombres y los sueldos.
Puesto que todos los nombres y sueldos son recuperados dentro del loop, almacnelos en
tablas PLSQL.
Fuera del loop, transfiera los nombres y sueldos de las tablas PLSQL a la tabla AYUDA.
Vace la tabla AYUDA y ejecute el ejercicio.
Introduzca el nmero del empleado: 7934
PL/SQL procedure successfully completed.
NAME SALARY
MILLER 1300

Introduzca el nmero del empleado: 7876
PL/SQL procedure successfully completed.
NAME SALARY
ADAMS 1100
Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 190 - Mario Juncos Murcia
MANEJO DE CURSORES
Cuando PL/SQL debe procesar una sentencia SQL, entonces genera una rea de trabajo temporal
que recibe el nombre de rea de contexto (context rea), y que es utilizada para ejecutar la
sentencia y almacenar informacin relativa a esta.
Un cursor referencia un rea de contexto y permite acceder a la informacin contenida en esta.
PL/SQL utiliza dos tipos de cursores:
Explcitos:
Provocados por el programador para controlar el acceso a mltiples filas obtenidas como
consecuencia de la ejecucin de una sentencia SELECT.
Implcitos:
Son generados automticamente por PL/SQL cuando se ejecuta un sentencia SQL no asociada
con un cursor explcito.

CURSORES EXPLICITOS
El nmero de filas devueltas por una consulta puede ser Cero uno o mayor de uno. Cuando el
nmero de filas devueltas es superior a uno, entonces es interesante definir un CURSOR con la
finalidad de:
Realizar determinados tratamientos antes de utilizar la informacin extrada.
Mantener la pista de que fila retornada esta siendo procesada en cada instante.
Existen cuatro sentencias asociadas con el manejo de cursores:
CURSOR
Otorga un nombre de programador al cursor y declara la sentencia SELECT asociada. La sintaxis
es:
CURSOR nombre [(parmetro tipo,...)]
IS sentencia_select ;
Los parmetros, como veremos en los ejemplos, pueden utilizarse para cualificar la consulta.
Ejemplos:
CURSOR c1 IS
SELECT nombre
FROM empleados
WHERE salario > 2000;


Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 191 - Mario Juncos Murcia
CURSOR c2 (num NUMBER) IS
SELECT nombre, salario, comision
FROM empleados
WHERE num_emp = num;

OPEN
Inicializa y abre el cursor, es decir, ejecuta la sentencia SELECT asociada.
OPEN nombre [(param1 [, param2 ...])];
Ejemplos:
OPEN c1;
OPEN c2 (empleado);
OPEN c2 (7902);

FETCH
Asocia los valores de cada una de las filas devueltas con determinadas variables PL/SQL. Se
puede ejecutar tantas veces como filas hayan sido devueltas por la sentencia SELECT, pero no
puede volver a la fila anterior. La sintaxis es:
FETCH nombre_cur INTO var1 [,var2 ...];
Ejemplos:
FETCH c1 INTO nombre_var;
FETCH c2 INTO nomb,salar,comis;

CLOSE
Cierra el cursor, liberando los recursos que este hubiera obtenido.
CLOSE nombre
Ejemplo:
CLOSE c1;


Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 192 - Mario Juncos Murcia
ATRIBUTOS PREDEFINIDOS PARA CURSORES
Todos los cursores declarados explcitamente por el programador disponen de cuatro atributos
predefinidos:
%NOTFOUND
nombre_cursor%NOTFOUND devuelve TRUE si el ltimo FETCH ejecutado ha fallado, puesto
que se han agotado las filas devueltas por la consulta.
LOOP
FETCH c3 INTO nombre, num_dept;
EXIT WHEN c3%NOTFOUND;
...
END LOOP;

%FOUND
nombre-cursor%FOUND es el atributo lgico contrario al anterior. Devuelve TRUE si el ltimo
FETCH ha tenido xito, pues aun quedan filas por evaluar.
LOOP
FETCH c3 INTO nombre, num_dept;
IF c3%FOUND THEN
INSERT INTO tabla ...
...
ELSE
EXIT;
END IF;
...
END LOOP;

%ROWCOUNT
nombre-cursor%ROWCOUNT devuelve el nmero de filas que ya se han tratado con FETCH.
LOOP
FETCH c3 INTO nomb, dept;
IF c3%ROWCOUNT > 10 THEN
....
END LOOP;


Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 193 - Mario Juncos Murcia
%ISOPEN
nombre cursor%ISOPEN devuelve TRUE si el cursor esta abierto (OPEN), y FALSE en caso
contrario. Ejemplo:
IF c3%ISOPEN THEN
FETCH c3 INTO nombre, salario;
ELSE
OPEN c3;
END IF;

DECLARE
num1 [Link]%TYPE;
num2 tabla1.n2%TYPE;
num3 tabla1.n3%TYPE;
resultado temp.col1%TYPE;
CURSOR c1 IS
SELECT n1, n2, n3 FROM tabla1 WHERE num = 1;
BEGIN
OPEN c1;
LOOP
FETCH c1 INTO num1, num2,num3;
EXIT WHEN c1%NOTFOUND;
resultado := num2/(num1+num3);
INSERT INTO temp VALUES (resultado);
END LOOP;
CLOSE c1;
COMMIT;
END;

BUCLES FOR para CURSORES
Los BUCLES FOR para CURSORES provocan implcitamente la apertura del cursor (OPEN), el
barrido de todas las filas asociadas (FETCH) y el cierre de este (CLOSE). La informacin se
almacena implcitamente en un registro que es conveniente definir.
Su utilizacin esta recomendada desde el punto de vista de simplificacin de cdigo.
Ejemplo:


Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 194 - Mario Juncos Murcia
DECLARE
resul temp.col1%TYPE;
CURSOR c1 IS
SELECT n1, n2, n3
FROM tabla1
WHERE num = 1;
BEGIN
FOR c1_rec IN c1 LOOP
resul := c1_rec.n2/(c1_rec.n1 + c1_rec.n3);
INSERT INTO temp VALUES (resul);
END LOOP;
COMMIT;
END;

EL CURSOR IMPLICITO SQL
Cada vez que ejecutamos una sentencia SQL desde un bloque PL/SQL, y esta no esta asociada a
un cursor explcito, ORACLE genera un cursor implcito. PL/SQL permite referirse a el con la
nomenclatura 'SQL%' .
Lgicamente, con los cursores implcitos, no se pueden utilizar las instrucciones OPEN, FETCH,
CLOSE, pero si los atributos de cualquier cursor, con la siguiente semntica:
SQL%NOTFOUND
Devuelve TRUE si una sentencia INSERT, DELETE o UPDATE no ha afectado a ninguna fila, o
cuando una sentencia SELECT no ha devuelto ninguna fila.
SQL%FOUND
Devuelve TRUE si INSERT, DELETE o UPDATE han afectado a alguna fila, o si una SELECT
ha devuelto informacin.
SQL%ROWCOUNT
Devuelve el nmero de filas afectadas por un INSERT, DELETE o UPDATE, o el nmero de
filas devueltas por una SELECT.
SQL%ISOPEN
ORACLE cierra automticamente un cursor implcito una vez que se ha ejecutado la sentencia
SQL. Es por ello que, SQL%ISOPEN siempre devuelve FALSE.

Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 195 - Mario Juncos Murcia
USO DE CURSORES PARA ACTUALIZAR FILAS
Cursor FOR UPDATE. Hasta el momento hemos venido utilizando los cursores slo para
seleccionar datos, pero tambin se puede usar el nombre de un cursor que apunta a una fila
para realizar una operacin de actualizacin en esa fila. Cuando se prevea esa posibilidad, a la
declaracin del cursor habr que aadirle FOR UPDATE al final.
CURSOR nombrecursor <declaracin del Cursor> FOR UPDATE [NO wait]
FOR UPDATE indica que las filas seleccionadas por el cursor van a ser actualizadas o
borradas. Todas las filas seleccionadas sern bloqueadas tan pronto se abra (OPEN) el cursor
y sern desbloqueadas al terminar las actualizaciones (al ejecutar COMMIT explcita o
implcitamente).
Una vez declarado un cursor FOR UPDATE, se incluir el especificador CURRENT OF
nombredecursor en la clusula WHERE para actualizar (UPDATE o borrar (DELETE) la
ultima fila recuperada mediante la Orden FETCH.
{UPDATE / DELETE} ... WHERE CURRENT OF nombrecursor
El siguiente procedimiento subir el salario a todos los empleados del departamento indicado
en la llamada. La subida ser el porcentaje indicado en la llamada:

CREATE OR REPLACE PROCEDURE subir_salario_dpto
(Vp_num_dpto NUMBER, Vp_pct subida NUMBER)
AS
CURSOR c_emple IS SELECT oficio, salario FROM emple
WHERE dept_no = vp_num_dpto
FOR UPDATE;
Vc_reg_emple c_emple%ROWTYPE;
V_inc NUMBER(8,2);
BEGIN
OPEN c_emple;
FETCH c_emple INTO vc reg_emple;
WHILE c emple%FOUND LOOP
V_inc := (vc_reg_emple.salario /100) * Vp_pct_subida;
UPDATE emple SET salario = salario + v_inc
WHERE CURRENT OF c_emple;
FETCH c_emple INTO vc_reg_emple;
END LOOP;
END subir_ salario_dpto;

La clusula FOR UPDATE bloquea las filas afectadas por el cursor. Al cerrar el cursor no es
necesario hacer COMMIT.
Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 196 - Mario Juncos Murcia
Con NO WAIT si las filas estn ya bloqueadas devuelve un error, si no lo ponemos espera hasta
que se desbloqueen las filas
WHERE CURRENT hace referencia a la fila actual del cursor especificado.
Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 197 - Mario Juncos Murcia
Prctica 7
1.- Cree un bloque PLSQL que determine los empleados con sueldos ms altos.
Acepte un nmero n como entrada de usuario con un parmetro de sustitucin SQL.
En un bucle, obtenga los apellidos y sueldos de los n empleados con sueldos ms altos de
la tabla EMP.
Almacene los nombres y sueldos en la tabla AYUDA.
Suponga que no hay dos empleados con el mismo sueldo.
Compruebe varios casos, como un n = 0, o donde n es mayor que el nmero de empleados
de la tabla EMP. Vace la tabla AYUDA despus de cada prueba.
Introduzca el numero de empleados que quiere listar: 5
NAME SALARY
KING 5000
FORD 3000
SCOTT 3000
JONES 2975
BLAKE 2850
2.- Considere el caso de que varios empleados tienen el mismo salario. Si se incluye a
una persona, deber incluirse tambin a todas las personas con el mismo sueldo.
Por ejemplo, si el usuario introduce un valor de 2 para n, apareceran King, Ford y Scott.
(Estos dos ltimos empleados tienen el segundo sueldo ms alto).
Si el usuario introduce un valor de 3, aparecern King, Ford, Scott y Jones.
Suprima todas las filas de AYUDAy pruebe el ejercicio.

Introduzca el numero de empleados que quiere listar: 2
NAME SALARY
KING 5000
FORD 3000
SCOTT 3000

Introduzca el numero de empleados que quiere listar: 3
NAME SALARY
KING 5000
FORD 3000
SCOTT 3000
JONES 2975
Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 198 - Mario Juncos Murcia
Prctica 8
1. Ejecute una consulta para recuperar todos los departamentos y empleados de cada
departamento.
Inserte los resultados en la tabla MENSAJES. Utilice un cursor para recuperar el nmero
de departamento y transfiralo a un cursor para recuperar los empleados de ese departamento.
RESULTADOS .
KING Departamento 10
CLARK Departamento 10
MILLER Departamento 10
DOE Departamento 10
JONES Departamento 20
FORD Departamento 20
SMITH Departamento 20
SCOTT Departamento 20
ADAMS Departamento 20
BLAKE Departamento 30
MARTIN Departamento 30
ALLEN Departamento 30
TURNER Departamento 30
JAMES Departamento 30
WARD Departamento 30
15 rows selected.

2. Modifique [Link] para incorporar la funcionalidad FOR UPDATE y WHERE
CURRENT OF al procesamiento de cursores.
EMPNO SAL ASTERISCOS
8000
7900 950 **********
7844 1500 ***************
Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 199 - Mario Juncos Murcia
MANEJO DE ERRORES
PL/SQL como muchos otros lenguajes de programacin de los ltimos aos, proporciona un
mecanismo para el manejo de errores basado en EXCEPCIONES. Una EXCEPCION se podra
definir como un evento que se produce cuando la ejecucin del cdigo provoca una situacin
anmala.
El manejo de errores basado en EXCEPCIONES permite mantener una legibilidad de cdigo
desconocida en lenguajes de generaciones anteriores.
PL/SQL dispone de un conjunto de sentencias que permiten manejar las EXCEPCIONES que se
pudieran provocar durante la ejecucin del cdigo.
Existe una coleccin de excepciones predefinidas en el lenguaje como ZERO_DIVIDE, que se
produce cuando se intenta dividir por cero. Adems, el programador puede generar sus propias
excepciones (no predefinidas en el lenguaje) y provocar que se produzcan (o elevan) bajo
determinadas circunstancias.
La gran ventaja del tratamiento de errores por excepciones, radica en el aumento de la legibilidad
del cdigo, y su ms eficiente mantenimiento, ya que las acciones a tomar cuando se eleva una
excepcin, se escriben aparte en el cdigo fuente; no mezclando as el tratamiento habitual de la
informacin con las acciones a tomar en casos anmalos.
Formalmente existen tres acciones asociadas con el manejo de EXCEPCIONES:

DECLARACION:
Las excepciones no predefinidas se declaran en el segmento DECLARE de un bloque PL/SQL.
DECLARE
com_cero EXCEPTION;
salario NUMBER(7,2);
Lgicamente, las excepciones predefinidas no se declaran.

ELEVACION:
Las excepciones no predefinidas se pueden elevar explcitamente con la sentencia RAISE:
IF comisin = 0 OR comisin IS NULL THEN
RAISE com_cero;
END IF;
Las excepciones predefinidas se elevan cuando se produce el evento al que estn asociadas.
Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 200 - Mario Juncos Murcia
MANEJO:
La captura y tratamiento de las excepciones se realiza en los MANEJADORES DE
EXCEPCIONES. Es en estos donde se expresan las acciones a tomar en cada caso. Los
MANEJADORES DE EXCEPCIONES siempre se colocan al final del bloque PL/SQL.
EXCEPTION
WHEN com_cero THEN
-- proceso del error aqu
WHEN excepcion2 THEN
.....
END;

Clusula WHEN OTHERS. La clusula WHEN OTHERS se puede utilizar en un manejador de
excepciones con la finalidad de tratar todas aquellas que no dispongan de su clusula WHEN
particular.
EXCEPTION
WHEN excepcion1 THEN
.....
WHEN OTHERS THEN
-- tratamiento de cualquier otro error
END;
La sentencia nula (NULL) es especialmente til en estos casos. WHEN OTHERS THEN NULL;
Cuando se eleva una excepcin, ya sea implcitamente o utilizando el comando RAISE, el flujo de
control continua por el manejador de estas, situado en el bloque actual. Si dicho bloque no
contuviera manejador (o la excepcin elevada no esta contemplada en este), entonces la excepcin
se propaga hacia afuera, al bloque que contuviera al actual, y as sucesivamente, hasta que se
encontrara un manejador adecuado. Una vez que la excepcin ha sido tratada, la ejecucin
continua por la instruccin siguiente al bloque que la ha tratado.
Si ningn manejador consigue tratar una excepcin, entonces esta se propaga al entorno que
invoc a PL/SQL, ya sea SQL*Plus, SQL*Forms o un lenguaje precompilado.
Por ello es recomendable por claridad que cada instruccin en la que pueda producirse una
EXCEPTION tenga asociado un manejo de excepciones
BEGIN
BEGIN
...
EXCEPTION
...
END;

Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 201 - Mario Juncos Murcia
BEGIN
....
EXCEPTION
...
END;
.........
END;EXCEPCIONES PREDEFINIDAS
Las siguientes excepciones se encuentran predefinidas en el lenguaje y se elevan en los casos
indicados.
Cdigo error
Oracle
Valor de
SOL CODE
Excepcin Se disparan cuando...
ORA_06530 -6530 ACCESS_INTO_NULL Se intenta acceder a los atributos de un objeto no inicializado.
ORA_06531 -6531 COLLECTION_IS_NULL Se intenta acceder a elementos de una coleccin que no ha sido
inicializada.
ORA_06511 -6511 CURSOR_ALREADY_OPEN Intentamos abrir un cursor que ya se encuentra abierto.
ORA_00001 -1 DUP_VAL_ON_INDEX Se intenta almacenar un valor que crearla duplicados en la clave
primaria o en una columna con la restriccin UNIQUE.
ORA_01001 -1001 INVALID_CURSOR Se intenta realizar una operacin no permitida sobre un cursor (por
ejemplo, cursor que no se ha abierto).
ORA_01722 -1722 INVALID_NUMBER Fallo al intentar convertir una cadena a un valor numrico.
ORA_01017 -1017 LOGIN_DENIED Se intenta conectar a ORACLE con un usuario o una clave no
validos.
ORA_01012 -1012 NOT_LOGGED_ON Se intenta acceder a la base de datos sin estar conectado a Oracle.
ORA_01403 -100 NO_DATA_FOUND Una sentencia SELECT ... INTO ... no devuelve ninguna fila.
ORA_06501 -6501 PROGRAM_ERROR Hay un problema interno en la ejecucin del programa.
ORA_06504 -6504 ROWTYPE_MISMATCH La variable del cursor del HOST y la variable del cursor PLSQL
pertenecen a tipos incompatibles.
ORA_06533 -6533 SUBSCRIPT_OUTSIDE_LIMIT Se intenta acceder a una tabla anidada o a un array con un valor de
ndice ilegal ( por ejemplo, negativo).
ORA_06500 -6500 STORAGE_ERROR El bloque PLSQL se ejecuta fuera de memoria (o hay algn otro
error de memoria)
ORA_00051 -51 TIMEOUT_ON_RESOURCE Se excede el tiempo de espera para un recurso.
ORA_01422 -1422 TOO_MANY_ROWS Una sentencia SELECT ... INTO ... devuelve mas de una fila.
Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 202 - Mario Juncos Murcia
ORA_06502 -6502 VALUE_ERROR Un error de tipo aritmtico, de conversin, de truncamiento...
ORA_01476 -1476 ZERO_DIVIDE Se intenta la divisin entre cero.

OTRAS EXCEPCIONES
Existen otros errores internos de Oracle, similares a los asociadas a las excepciones internas pero
que no tienen asignada una excepcin, sino un cdigo de error y un mensaje d e e r r o r , a los
que se accede mediante las funciones SQLCODE y SQLERRM. Cuando se produce uno de estos
errores se transfiere el control a la seccin EXCEPTION, donde se tratara el error en la clusula
WHEN OTHERS:
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(Error: || SQLCODE || SQLERRM );
.........
END;
En este ejemplo se muestra al usuario el texto 'ERROR' con el CODIGO DE ERROR y el
MENSAJE DE ERROR utilizando las funciones correspondientes.
Estas dos funciones, SQLCODE y SQLERRM, no son accesibles desde rdenes SQL*Plus, pero
se pueden pasar a este entorno a travs de soluciones como la siguiente:

WHEN OTHERS THEN
:cod_err := SQLCODE;
:msg_err := SQLERRM;
ROLLBACK;
EXIT;
END;
Tambin podemos asociar una excepcin a alguno de estos errores internos que no TIENEN
excepciones predefinidas asociadas. Para ello procederemos as:
1. Definimos una excepcin en la seccin de declaraciones Como si fuese una excepcin definida
por el. usuario:
<nombreexcepcin> EXCEPTION;
2. Asociamos esa excepcin a un determinado cdigo de error mediante la directiva del
compilador PRAGMA EXCEPTION_INIT, segn el formato siguiente:
PRAGMA EXCEPTION_INIT(<nombre excepcin>, <nmero_de_error_oracle>)
3. Indicamos el tratamiento que recibir la excepcin en la seccin EXCEPTION como si se
Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 203 - Mario Juncos Murcia
tratase de cualquier otra excepcin definida o predefinida.




DECLARE
err_externo EXCEPTION; __ Se define la excepcin de usuario
PRAGMA EXCEPTION_INIT (err_externo, _1547); __ Se asocia con un error de Oracle
..................
BEGIN
/*. no hay que levantar la excepcin, ya que llegado el caso Oracle lo har */
..........
EXCEPTION
.........
WHEN err_externo THEN __ Se trata como cualquier otra.
<tratamiento>;
END;

Utilizacin de RAISE_APPLICATION_ERROR
En el paquete DBMS_STANDARD se incluye un procedimiento muy til llamado
RAISE_APPLICATION_ERROR que sirve para levantar errores y definir y enviar mensajes de
error. Su formato es el siguiente:
RAISE APPLICATION ERROR(nmero_de_error, mensaje_de_error)
Donde nmero de error es un nmero comprendido entre -20000 y -20999, y Mensaje_de_error
es una cadena de hasta 512 bytes.
Cuando un subprograma hace esta llamada, se levanta la excepcin y se deshacen los cambios
realizados por el subprograma.
Ejemplos de aplicacin
PROCEDURE subir_sueldo
(Num emple NUMBER, incremento NUMBER)
IS
Salario_actual NUMBER;
BEGIN
SELECT salario INTO salario_actual FROM empleados
WHERE Emp_no = Num_emple;
IF salario_actual IS NULL THEN
Raise_ application_error (_20010, Salario Nulo);
ELSE
Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 204 - Mario Juncos Murcia
UPDATE empleados
SET sueldo = Salario_actual + incremento
WHERE Empno = Num_emple;
ENDIF;
END subir_sueldo;
Control de transacciones
Una transaccin se puede definir corno un conjunto de operaciones que se realizan en la base de
datos. Una transaccin, por tanto, no se circunscribe al mbito de una orden SQL o al de un
bloque PL/SQL, sino que es el usuario (el programador, en este caso) quien decide cuales sern
las operaciones que compondrn la transaccin.
Oracle garantiza la consistencia de los datos en una transaccin en trminos de VALE TODO o
NO VALE NADA, es decir, o se ejecutan todas las operaciones que componen una transaccin o
no se ejecuta ninguna. as pues, la base de datos tiene un estado antes de la transaccin y un
estado despus de la transaccin, pero no hay estados intermedios.
Una transaccin comienza con la primera orden SQL de la sesin del usuario o con la primera
orden SQL posterior a la finalizacin de la transaccin anterior.
La transaccin finaliza cuando se ejecuta un comando de control de transacciones (COMMIT o
ROLLBACK), una orden de definicin de datos (DDL) o cuando finaliza la sesin.

BEGIN
UPDATE cuentas SET saldo = saldo v_importe_tranfer
WHERE num_cta = v_cta_origen;
UPDATE cuentas SET saldo = saldo + v_importe_tranfer
WHERE num_cta = v_cta_destino;
COMMIT WORK;
..........
EXCEPTION
WHEN OTHERS THEN
ROLLBACK WORK;
END;

En el ejemplo anterior se garantiza que la transferencia se llevar a cabo totalmente o que no se
realizar ninguna operacin, pero en ningn caso se quedar a medias.

El comando COMMIT. Da por concluida la transaccin actual y hace definitivos los cambios
efectuados, liberando las files bloqueadas. Slo despus de que se ejecute el COMMIT los demos
usuarios tendrn acceso a los datos modificados.

El comando ROLLBACK. Da por concluida la transaccin actual y deshace los cambios que se
pudiesen haber producido en la misma, liberando las files bloqueadas. Se utiliza especialmente
Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 205 - Mario Juncos Murcia
cuando no se puede concluir una transaccin porque se levanta una excepcin.

ROLLBACK implcitos. Cuando un subprograma almacenado falla y no se controla la excepcin
que produjo el fallo, Oracle automticamente ejecuta ROLLBACK sobre todo lo realizado por el
subprograma, salvo que en el subprograma hubiese algn COMMIT, en cuyo caso lo confirmado
no sera deshecho.
SAVEPOINT. Se utiliza para poner marcas o puntos de salvaguarda al procesar transacciones. Se
utiliza en conjuncin con ROLLBACK TO. Esto permite deshacer parte de una transaccin

CREATE OR REPLACE PROCEDURE prueba savepoint
(numfilas POSITIVE)
AS
BEGIN
SAVEPOINT NIGUNA;
INSERT INTO temp1 (col1) VALUES ('PRIMERA FILA');
SAVEPOINT UNA;
INSERT INTO temp1 (col1) VALUES ('SEGUNDA FILA');
SAVEPOINT DOS;
IF numfilas = 1 THEN
ROLLBACK TO UNA;
ELSIF numfilas = 2 THEN
ROLLBACK TO DOS;
ELSE
ROLLBACK TO NINGUNA;
END IF;
COMMIT;
EXCEPTION
WHEN OTHERS THEN
ROLLBACK;
END;

Oracle establece un punto de salvaguarda implcito cada vez que se ejecuta una sentencia de
manipulacin de dates. En el caso de que la sentencia falle, Oracle restaurara automticamente los
dates a sus valores iniciales.

Podemos observar que ROLLBACK TO <punto de salvaguarda> deshace el trabajo realizado
sobre la base de datos despus del punto indicado, incluyendo posibles bloqueos. No obstante,
tampoco se confirma el trabajo hecho hasta el punto de salvaguarda. La transaccin no finaliza
hasta que se ejecuta un comando de control de transacciones COMMIT o ROLLBACK, o hasta
que finaliza la sesi6n (o se ejecuta una orden de definicin de datos DDL).

El mbito de los puntos de salvaguarda es el definido por la transaccin desde que comienza hasta
que termina, por tanto, trasciende de las reglas de mbito y visibilidad de otros identificadores.

Por omisin, el nmero de SAVEPOINT est limitado a cinco por sesin, pero se puede cambiar
Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 206 - Mario Juncos Murcia
en el parmetro SAVEPOINTS del fichero de inicializacin de Oracle hasta 255.

Cuando se ejecuta un ROLLBACK TO <marca>, todas las marcas despus del punto indicado
desaparecen (la indicada no desaparece). Tambin desaparecen todas las marcas cuando se ejecuta
un COMMIT.

Los nombres de las marcas son identificadores no declarados y se pueden reutilizar.
SET TRANSACTION READ ONLY. Establece el comienzo de una transaccin de solo
lectura. Se utiliza para garantizar la consistencia de los datos recupererados entre distintas
consultas. Todas las consultas que se ejecutan a continuacin solamente vern aquellos
cambios confirmados antes del comienzo de la transaccin: es como si se hiciese una
fotografa de la base de datos:
DECLARE
Num ventas dia REAL;
Num_ventas semana REAL;
BEGIN
COMMIT;
SET TRANSACTION READ ONLY;
SELECT count(*) INTO ventas_dia
FROM ventas
WHERE fecha = SYSDATE;
SELECT count(*) INTO ventas_semana
FROM ventas
WHERE fecha > SYSDATE _ 7;
COMMIT;
END;
Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 207 - Mario Juncos Murcia
Prctica 9
1. Escriba un bloque PLSQL para seleccionar el nombre del empleado con un valor
concreto de sueldo. Le preguntaremos el sueldo al usuario a travs de un pararnetro SQL.
Si el sueldo introducido devuelve ms de una fila, gestione la excepcin con un manejador
de excepciones apropiado e inserte en la tabla MENSAJES "Ms de un empleado con un
salario <sueldo>.
Si el sueldo introducido no devuelve ninguna fila, gestione la excepcin con un manejador
de excepciones apropiado e inserte en la tabla MENSAJES "Ningn empleado con salario
<sueldo> .
Si el sueldo introducido slo devuelve una fila, inserte en la tabla MENSAJES el nombre
del empleado y el importe del sueldo.
Gestione cualquier otra excepcin con un manejador de excepciones apropiado e inserte
en la tabla MENSAJES "Se produjo algn otro error.
Pruebe el bloque con varios casos.
RESULTADOS
SMITH 800
Ms de un empleado con un salario 3000
Ningn empleado con salario 6000
2. Modifique [Link] para aadir un manejador de excepciones.
Escriba un manejador para que comunique un mensaje al usuario diciendo que el
departamento especificado no existe.
Ejecute el bloque PLSQL introduciendo un departamento que no existe.
Introduzca el nmero de departamento: 50
Introduzca la poblacin del departamento: HOUSTON
PL/SQL procedure successfully completed.
G MESSAGE
Departamento 50 es un Departamento no valido
[Link] un bloque PLSQL que imprima cuantos empleados hay que ganan 100 ms o
menos del valor del salario introducido.
Si no hay ningn empleado dentro de ese rango de sueldo, muestre un mensaje al usuario
indicando cul es el caso. Utilice una excepcin para este caso.
Si hay uno o ms empleados dentro de ese rango, el mensaje debera indicar cuntos
empleados hay en ese rango de sueldo.
Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 208 - Mario Juncos Murcia
Gestione cualquier otra excepcin con un manejador de excepciones apropiado, el
mensaje debera indicar que se ha producido otro error.
Introduzca el salario: 800
PL/SQL procedure successfully completed
G_MESSAGE
Hay 1 empleado(s) con un salario entre 700 y 900

Introduzca el salario: 3000
PL/SQL procedure successfully completen
G_MESSAGE
Hay 3 empleado(s) con un salario entre 2900 y 3100

Introduzca el salario: 6000
PL/SQL procedure successfully completen
G_MESSAGE
No hay ningun empleado con un salario entre 5900 y 6100
Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 209 - Mario Juncos Murcia
SUBPROGRAMAS
Los subprogramas PL/SQL son bloques con nombre. Pueden recibir parmetros y ser invocados
desde aquellos puntos en los que haya visibilidad sobre ellos. Las caractersticas principales son:
Modularidad
Reusabilidad
Mantenimiento
Abstraccin funcional
Existen dos tipos de subprogramas:
Procedimientos
Funciones

PROCEDIMIENTOS
Un procedimiento, en general, recibe parmetros, y realiza una accin determinada, cualificada
por los valores de sus parmetros. Se declaran en la regin declarativa del bloque PL/SQL con la
siguiente sintaxis:
PROCEDURE nombre [(parmetro [,parmetro, ... l)] IS
[declaracin de objetos locales]
BEGIN
...
[EXCEPTION
...]
END [Nombre];

donde 'parmetro' equivale a:

IN :=
nombre_par OUT tipo valor
IN OUT DEFAULT

IN, OUT e IN OUT
IN... Un parmetro IN es de solo lectura; puede ser consultado dentro del procedimiento, pero
no asignarlo. Es el tipo por defecto
OUT... Puede ser asignado, pero no consultado
IN OUT ... Puede ser asignado y consultado

Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 210 - Mario Juncos Murcia
PROCEDURE nuevo_salario
( numero_emp empleados.num_emp%TYPE,
nuevo_sal [Link]%TYPE,
realizado OUT BOOLEAN ) IS
tmp BOOLEAN;
BEGIN
UPDATE empleados SET salario = nuevo_sal
WHERE num_emp = numero_emp; -- OK
nuevo_sal := O; -- ilegal. Parmetro IN
realizado := TRUE; -- correcto
tmp := realizado; --ilegal. Parametro OUT
END;
Desde la regin ejecutable podemos invocar a nuestros procedimientos:
DECLARE
OK BOOLEAN;
PROCEDURE borra_emp.......
PROCEDURE nuevo_salario.........

BEGIN
....
nuevo_salario(7902,6500,0K);
borra_emp (7902);
borra_emp (un_entero);
END;

FUNCIONES
Una funcin es un subprograma que, adems de realizar una accin determinada devuelve un
nico valor. La sintaxis es:
FUNCTION nombre [( argumento [, argumento, ...])]
RETURN tipo IS
[declaracin de objetos locales]
BEGIN
....
[EXCEPTION
....
....]
END [Nombre];
Igual que los procedimientos, las funciones se declaran en la regin declarativa del bloque.
La declaracin de argumentos es igual a la de los procedimientos.
Sentencia RETURN
Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 211 - Mario Juncos Murcia
Dado que las funciones han de devolver un valor, es necesaria la existencia de una sentencia que
detenga el flujo de ejecucin de la funcin y provoque la devolucin del valor mencionado.
Ejemplo:
FUNCTION prima_anual
(sal [Link]%TYPE,
com [Link]%TYPE)
RETURN NUMBER IS
prima NUMBER;
BEGIN
prima := (( sal * 14 )+( com * 14 )) * 0.05;
RETURN prima;
END prima_anual;

Igual que los procedimientos, las funciones son invocadas desde la regin ejecutable del bloque:
DECLARE
la_Prima NUMBER;
FUNCTION prima_anual......
BEGIN
...
la_prima := prima_anual (3500,600);
...
END;

DECLARACION DIFERIDA
En los bloques PL/SQL no es posible referenciar a un subprograma que no est previamente
declarado. La declaracin diferida resuelve dicho problema: Ejemplo:
DECLARE
PROCEDURE subida_comision( .... );
PROCEDURE aumento_sueldo IS
BEGIN
....
subida_comisin( .....); --todava no esta declarado;
END aumento_sueldo;
PROCEDURE subida_comision IS
BEGIN
.....
END;
NOTACION POSICIONAL Y NOMINAL
Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 212 - Mario Juncos Murcia
Por defecto los valores de una llamada a un subprograma se asocian con los argumentos por su
posicin. Ejemplo:
PROCEDURE prima_anual
(sal NUMBER,
com NUMBER) IS...
........................................................
prima_anual (3500,600)
conforme esta asigna 3500 a sal y 600 a com pero tambin est disponible la notacin nominal:
prima_anual (com => 600, sal => 3500)
Ambas notaciones se pueden utilizar simultneamente en la misma llamada:
PROCEDURE fija_sal
(num-emp NUMBER,
sal NUMBER,
com NUMBER) IS ...
fija_sal (7902, com=>600, sal=>3500);
Una vez que un parmetro ha sido utilizado con la notacin nominal, los siguientes deben usar
tambin esta notacin:
Ejemplo incorrecto: fija_sal (sal=>3500, 7902, com=>600);

VALORES POR DEFECTO PARA LOS ARGUMENTIOS
Los parmetros de tipo IN pueden tomar valores por defecto, para aquellos caso en los que el
subprograma sea invocado, sin ofrecer valor para todos los parmetros. Ejemplo:
FUNCTION prima_anual
(sal NUMBER DEFAULT 0,
com NUMBER DEFAULT 0) ...
en la llamada a := prima_anual(3500,600); sal recibe el valor 3500 y com el valor 600,
pero en la llamada: a:= prima_anual (3500) com toma el valor 0
Sin utilizar la notacin nominal solo es posible dejar a una valor por defecto los parmetros finales
de la declaracin. Ejemplo:
Si queremos poner com a 600 no podemos hacer a:= prima_anual(600); cargara 600 en 'sal' y
dejara 'com' a 0. La solucin sera usar la notacin nominal a:= prima_anual (com=>600);
SOBRECARGA
Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 213 - Mario Juncos Murcia
Como algunos lenguajes de los ltimos aos PL/SQL admite la sobrecarga de identificadores, en
especial para aquellos que denotan a los subprogramas.
Dos subprogramas pueden llamarse igual, si los tipos de sus argumentos permiten diferenciarlos.
En otro caso la sobrecarga no es posible, ya que la ambigedad no es resoluble. Ejemplo:
DECLARE
mi_emp [Link]%TYPE;
mi_dpt NUMBER(2);
PROCEDURE borrar
(nom [Link]%TYPE) IS
BEGIN
DELETE FROM empleados WHERE nombre = nom;
END borrar;
PROCEDURE borrar
(d NUMBER(2)) IS
BEGIN
DELETE FROM departamentos WHERE num_dept = d;
END borrar;
BEGIN -- del bloque principal
mi_emp := 'MILLER';
mi_dpt := 10;
borrar(mi_emp);
borrar (mi_dept);
COMMIT;
END; -- del bloque principal

RECURSIVIDAD
Un programa recursivo es aquel que se llama a si mismo.
Ejemplo:
FUNCTION factorial (n POSITIVE)
RETURN POSITIVE IS
BEGIN
IF n = 0 THEN RETURN 1;
ELSE RETURN n * factorial (n-1l);
END IF;
END factorial;


SUBPROGRAMAS ALMACENADOS
Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 214 - Mario Juncos Murcia
Los subprogramas (procedimientos y funciones) qua hemos visto hasta ahora se compilan
independientemente y almacenan en la base de datos Oracle.
Cuando creamos procedimientos o funciones almacenados desde SQL*Plus utilizan comandos
CREATE PROCEDURE o CREATE FUNCTION, Oracle automticamente compila el cdigo
fuente, genera el cdigo objeto (llamado P_cdigo) y los guarda en el diccionario de datos. De
este modo quedan disponibles para su utilizacin.
Los programas almacenados tienen dos estados: disponible (valid) y no disponible (invalid). Si
alguno de los objetos referenciados por el programa ha sido borrado o alterado desde la ltima
compilacin del programa quedara en situacin de "no disponible" y se compilara de nuevo
automticamente en la prxima llamada. Al compilar de nuevo, ORACLE determina si hay qua
compilar algn otro subprograma referido por el actual, y se puede producir una cascada de
compilaciones.
Estos estados se pueden comprobar en la vista USER OBJECTS:
SQL> SELECT OBJECT_NAME, OBJECT_TYPE, STATUS
FROM USER_OBJECTS
WHERE OBJECT_NAME='CAMBIAR_OFICIO';

OBJECT_NAME OBJECT_TYPE STATUS
CAMBIAR OFICIO PROCEDURE VALID

La estructura completa de la vista utilizada es
SQL> DESCRIBE USER_OBJECTS:
Name Null? Type
OBJECT_NAME VARCHAR2(128)
SUBOBJECT_NAME VARCHAR2(30)
OBJECT_ ID NUMBER
DATA_OBJECT_ID NUMBER
OBJECT_TYPE VARCHAR2(15)
CREATED DATE
LAST_ DDL_TIME DATE
TIMESTAMP VARCHAR2(19)
STATUS VARCHAR2(7)
TEMPORARY VARCHAR2(1)
GENERATED VARCHAR2(1)

Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 215 - Mario Juncos Murcia
Tambin se puede encontrar el cdigo fuente en la vista USER_SOURCE:
SQL> SELECT LINE, SUBSTR(TEXT,1,60)
FROM USER_SOURCE
WHERE name ='CAMBIAR_OFICIO';

Line SUBSTR(TEXT,1,60)
____ ______________________________________________________________________
1 PROCEDURE cambiar_oficio
2 (Num empleado NUMBER,
3 Nuevo oficio VARCHAR2)
4 IS
5 Anterior_oficio [Link]%TYPE;
6 BEGIN
7 SELECT oficio INTO anterior_oficio FROM emple
8 WHERE emp no =num_empleado;
9
10 UPDATE emple SET oficio = nuevo_oficio
11 WHERE emp_no = num_empleado;
12 DBMS_OUTPUT.PUT_LINE(num_empleado ||
13 *oficio Anterior: || anterior_oficio ||
14 *oficio Nuevo : || Nuevo_oficio );
15 END cambiar_oficio;


SQL> DESCRIBE USER_SOURCE
Name Null? Type
NAME NOT NULL VARCHAR2(30)
TYPE VARCHAR2(12)
LINE NOT NULL NUMBER
TEXT VARCHAR2(4000)

Para volver a compilar un subprograma almacenado en la base de datos se emplea la Orden
ALTER, indicando PROCEDURE o FUNCTION, segn el tipo de subprograma:
ALTER {PROCEDURE/FUNCTION} nombresubprograma COMPILE;
Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 216 - Mario Juncos Murcia
SUBPROGRAMAS LOCALES
Dentro de un subprograma se puede declarar y crear otro subprograma:
CREATE OR REPLACE pr_ejeml /* programa que contiene el subprograma local */
......................
AS
.............. /* lista de declaraciones: variables, etc. */

PROGRAM sprlocl /* comienza el subprograma local
........... /*lista de parametros del subprograma local
IS
............................ /*declaraciones locales al subprograma local */
BEGIN
............................. /*instrucciones del subprograma local */
END;
BEGIN
............
sprlocl; /* llamada al subprograma local */
..............
END;
Estos subprogramas reciben el nombre de subprogramas locales y tienen las siguientes
particularidades:
Se declaran al final de la seccin declarativa de otro subprograma o bloque.
Se les aplica las mismas reglas de mbito y visibilidad que a las variables declaradas en el
mismo bloque.
Se utilizara este tipo de subprogramas cuando no se contemple su reutilizacin otros
subprogramas (distintos a aquel en el que se declaran).
En el caso de subprogramas locales con referencias cruzadas o de subprogramas
mutuamente recursivos, hay que realizar declaraciones anticipadas, tal como se explica a
continuacin.
PL/SQL necesita que todos los identificadores, incluidos los subprogramas, estn declarados antes
de usarlos. Por eso, la llamada que aparece en el siguiente subprograma es ilegal:
Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 217 - Mario Juncos Murcia
DECLARE
..........
PROCEDURE subprograma1 ( .......) IS
BEGIN
..........
Subprograma2( ... ); __ > ERR. identificador no declarado
.......
END;
PROCEDURE subprograma2 (......) IS
BEGIN
......
END;
Se poda haber invertido el orden de declaracin de los procedimientos anteriores, lo cual
hubiera resuelto este caso, pero no sirve para procedimientos mutuamente recursivos. El problema
se resuelve utilizando declaraciones anticipadas de subprogramas
Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 218 - Mario Juncos Murcia
Prctica 10
1.-Crear y llamar al Procedimiento ADD_PROD y considerar los resultados.
- Crear un procedimiento llamado ADD_PROD para insertar un departamento nuevo en la
tabla DEPARTAMENTOS.
- Compilar el cdigo, llamar al procedimiento y consultar la tabla DEPARTAMENTOS
para ver los resultados.
- Llamar al procedimiento otra vez, pasando un identificador de DEPARTAMENTO de 10
Qu ocurre y por qu?.

2.- Crear un procedimiento llamado UPD_DEP para modificar un departamento en la
tabla DEPARTAMENTOS.
- Crear un procedimiento llamado UPD_DEP para actualizar el nombre del departamento.
Incluir el manejo de excepciones necesario.
- Compilar el cdigo, llamar al procedimiento y consultar la tabla DEPARTAMENTOS
para ver los resultados. Tambin comprobar el manejo de excepciones intentando
actualizar un departamento que no existe.

3.- Crear un procedimiento llamado DEL_DEP para borrar un departamento en la tabla
DEPARTAMENTOS
- Crear un procedimiento llamado DEL_DEP para borrar un departamento. Incluir el
manejo de excepciones necesario.
- Compilar el cdigo, llamar al procedimiento y consultar la tabla DEPARTAMENTOS
para ver los resultados. Tambin comprobar el manejo de excepciones intentando borrar
un departamento que no existe.

4. Crear un procedimiento para consultar la tabla EMP, recuperando el salario y cargo del
empleado 7839.
- Crear un procedimiento que devuelve el valor de las columnas SAL y JOB de un
empleado especificado (utilizar EMPNO).
- Utilizar variables host para los dos parmetros OUT.
- Proporcionar el manejo de error apropiado si el usuario llama al procedimiento sin que
exista valor para EMPNO.
- Compilar el cdigo, llamar al procedimiento y visualizar el salario y el cargo del empleado
7839.
- Llamar al procedimiento otra vez, pasando un EMPNO de 9898. Qu ocurre y por qu?.
Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 219 - Mario Juncos Murcia
Prctica 11
1.- Crear y llamar a la funcin Q_DEP para devolver un nombre de departamento.
- Crear una funcin llamada Q_DEP para devolver un nombre de departamento a una
variable host.
- Compilar el cdigo, llamar a la funcin y despus consultar la variable host para ver el
resultado.

2. Crear una funcin almacenada ANNUAL_COMP para devolver el salario anual cuando
se pasa el salario mensual y la comisin de un empleado. Asegurarse de que la funcin controla
valores NULL.
Crear y llamar a la funcin ANNUAL_COMP, pasando los valores del salario mensual y
de la comisin. La funcin debera devolver el salario anual, definido por: (sal * 12) +
comision
Utiliza la funcin almacenada en una sentencia SELECT contra la tabla EMP.

3.- Crear un procedimiento, NEW_EMP para insertar un empleado nuevo dentro de la
tabla EMP. El procedimiento debera contener una llamada a la funcin VALID_DEPTNO para
comprobar si existe en la tabla el departamento especificado para el nuevo empleado.
Crear una funcin VALID_DEPTNO para validar un nmero de departamento
especificado. La funcin debera devolver un BOOLEAN.
Crear el procedimiento NEW EMP para aadir un empleado a la tabla EMP. Debera
aadirse un nuevo registro a EMP si la funcin devuelve TRUE. Si la funcin devuelve
FALSE, el procedinento debera alertar al usuario con un mensaje apropiado
Definir valores DEFAULT para la mayora de argumentos. La comisin por defecto es 0,
el salario por defecto es 1000, el nmero de departamento por defecto es 30, el puesto por
defecto es SALESMAN y el nmero de gestor por defecto es 7839.
Comprobar el procedimiento NEW_EMP aadiendo un nuevo nombre de empleado al
departamento 99 (HARRIS). Dejar el resto de los parmetros con sus valores por
defecto. Cual es el resultado?.
Comprobar el procedimiento NEW_EMP aadiendo un nuevo nombre de empleado al
departamento 30 (HARRIS). Dejar el resto de los parmetros con sus valores por
defecto. Cual es el resultado?.
Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 220 - Mario Juncos Murcia
VISIN GENERAL SOBRE LOS PAQUETES
Los paquetes agrupan conceptos PLSQL relacionados, tipos, items, subprogramas. Por ejemplo
un paquete de recursos humanos puede contener procedimientos de contratacin y despido,
funciones de comisiones, variables de exencin de impuestos, etc.
Normalmente un paquete tiene una especificacin y un cuerpo, los cuales estan almacenados por
separado en la base de datos.
La especificacin es el interface de nuestras aplicaciones. Esta declara los conceptos,
variables, excepciones, constantes, cursores y subprogramas disponibles para el usuario.
El cuerpo define completamente cursores y subprogrames, implementando as la
especificacin.
El paquete en si mismo no puede ser llamado. El formato de un paquete es similar al de un
subprograma; una vez escrito y compilado, el contenido puede ser compartido por varias
aplicaciones.
Cuando llamamos por primera vez al programa PLSQL empaquetado, se carga el paquete
completo en memoria, por lo que llamadas posteriores a los programas relacionados no necesitan
hacer I/O en el disco.
El uso de paquetes es una alternativa a la creacin de procedimientos y funciones ofreciendo las
siguientes ventajas:
Modularidad.- Encapsulamos en un paquete las estructuras de programa relacionadas
Informacin oculta.- Podemos decidir qu programas son pblicos o privados. El paquete
oculta la definicin de los programas privados de forma que slo se vea afectado el
paquete ( no la aplicacin). Tambin, protegemos la integridad del paquete ocultando
detalles de implementacin.
Funcionalidad aadida.- Durante la sesin persisten las variables y cursores pblicos
empaquetados, de modo que pueden ser compartidos por todos los subprogramas que se
ejecutan en el entorno, adems nos permite mantener los datos en las transacciones sin
tener que almacenarlos en la base de datos.
Mejor rendimiento.- Al llamar por primera vez a un subprograma empaquetado, se carga
en memoria el paquete completo.
Sobrecarga.- Los paquetes permiten sobrecargar procedimientos y funciones.
Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 221 - Mario Juncos Murcia
DESARROLLO DE UN PAQUETE
Creamos un paquete en dos partes: primero la especificacin y despus el cuerpo. Los programas
pblicos de un paquete son aquellos que se declaran en la especificacin y que se definen en el
cuerpo. Los programas privados de un paquete son aquellos que se definen slo en el cuerpo y
solamente pueden ser referenciados por otros programas que estn dentro del mismo paquete
CREACIN DE LA ESPECIFICACIN DE UN PAQUETE

CREATE [ OR REPLACE ] PACKAGE nombre_paquete
IS
Declaracin de variables, constantes, cursores, excepciones o tipos pblicos
Declaracin de los subprogramas pblicos
END nombre_paquete;

CREATE OR REPLACE PACKAGE paquete_comisiones IS
G_comision NUMBER:= 10;
PROCEDURE reset_comision (V_comision IN NUMBER);
END paquete_comisiones;
Declaramos una variable global para mantener el valor de la comisin para la sesin de usuario,
que puede ser cambiada por el usuario directamente. O podemos declarar un procedimiento
pblico para permitir al usuario resetear la comisin en cualquier momento durante la sesin

CREACIN DEL CUERPO DE UN PAQUETE
CREATE [OR REPLACE] PACKAGE BODY nombre_paquete
IS
Declaracin de variables, constantes, cursores, excepciones y tipos privados
Definicin de los subprogramas PLSQL

Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 222 - Mario Juncos Murcia
CREATE OR REPLACE PACKAGE BODY paquete_comisiones IS
FUNCTION validar_comision (v_comision IN NUMBER) RETURN BOOLEAN IS
V_max_comision NUMBER;
BEGIN
SELECT MAX(comision) INTO v_max_comision
FROM emp;
IF v_comision > v_max_comision THEN
RETURN (FALSE);
ELSE
RETURN (TRUE);
END IF;
END validar_comision;

PROCEDURE reset_comision ( v_comision IN NUMBER) IS
V_valido BOOLEAN;
BEGIN
V_valido := validar_comision(v_comision);
IF v_valido = TRUE THEN
G_comision := v_comision;
ELSE
RAISE APLICATION_ERROR (-20210, Comision invalida)
END IF;
END reset_comision;
END paquete_comisiones;
Para llamar a un procedimiento empaquetado debemos de hacer referencia al nombre del paquete
SQL> EXECUTE paquete_comisiones.reset_comision(1500)
Si fuese de un usuario distinto
SQL> EXECUTE usuario.paquete_comisiones.reset_comision(1500)

Declaracin de cursores en paquetes
Para declarar cursores en paquetes de forma que estn accesibles en la especificacin deberemos
separar la declaracin del cursor del cuerpo (en este es donde va la clusula SELECT).
La declaracin del cursor se incluir en la cabecera del paquete indicando el nombre del cursor, los
parmetros (si procede) y el tipo devuelto. Este ultimo se indicara mediante RETURN
tipodedato; para cursores que devuelven filas enteras normalmente se usara %ROWTYPE.
Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 223 - Mario Juncos Murcia
CREATE PACKAGE empleados_acc AS
.
CURSOR C1 RETURN emple%ROWTYPE;
..
END empleados_acc;

CREATE PACKAGE BODY empleados_acc AS
CURSOR C1 RETURN emple%ROWTYPE
SELECT * FROM emple WHERE salario > 100000;
.......
END empleados_ acc;

mbito y otras caractersticas de las declaraciones
Los objetos declarados en la especificacin del paquete son globales al paquete y locales al contexto.
Asimismo, todas las variables declaradas en la especificacin del paquete mantienen su valor durante la
sesin, por tanto, el valor no se pierde entre las llamadas de los subprogramas.
Tambin cabe mencionar respecto a las variables constantes y cursores declarados en un paquete lo
siguiente:
El propietario es la sesin.
En la sesin no se crean los objetos hasta que se referencia el paquete.
Cuando se crean los objetos su valor ser nulo (salvo que se inicialice).
Durante la sesin los valores pueden cambiarse.
Al salir de la sesin los valores se pierden.

Caractersticas de almacenamiento y compilacin
Tanto el cdigo fuente como el cdigo compilado de los paquetes se almacena en la base de
datos. Al igual que ocurra con los subprogramas almacenados, el paquete (la especificacin)
puede tener dos estados:
- Disponible (valid).
- No disponible (invalid).
Cuando se borra o modifica alguno de los objetos referenciados el paquete pasar a invalid. Si la
especificacin del paquete se encuentra "no disponible", Oracle invalida (pasa a invalid) cualquier
objeto que haga referencia al paquete.

Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 224 - Mario Juncos Murcia
Cuando recompilamos la especificacin, todos los objetos que hacen referencia al paquete pasan a
"no disponible" hasta que sean compilados de nuevo. Cualquier referencia o llamada a uno de
estos objetos antes de ser recompilados producir que Oracle automticamente los recompile.
Esto ocurre con el cuerpo del paquete, pero en este caso se puede recompilar el paquete sin
invalidar la especificacin. Esto evita las recompilaciones en cascada innecesarias.
Si se cambia la definicin (cuerpo) de una funcin o procedimiento incluido en un paquete, no hay
que recompilar todos los programas que llaman al subprograma (como ocurre con los
subprogramas almacenados), a no ser que tambin se cambie la especificacin de dicha funcin o
procedimiento.
Paquetes suministrados por Oracle
Oracle incluye con su gestor de bases de datos diversos paquetes como STANDARD,
DBMS_OUTPUT, DBMS_STANDARD, DBMS_SQL, y muchos otros que incorporan diversas
funcionalidades. A continuacin veremos una breve resea del contenido de estos paquetes:
- En STANDARD se declaran tipos, excepciones, funciones, etc., disponibles desde el
entorno PL/SQL. Por ejemplo, en el paquete STANDARD estn definidas las funciones:
FUNCTION ABS (n number) RETURN NUMBER;
FUNCTION TO_CHAR (right DATE) RETURN VARCHAR2;
FUNCTION TO_CHAR (left NUMBER) RETURN VARCHAR2;
FUNCTION TO_CHAR (left DATE, right VARCHAR2) RETURN VARCHAR2;
FUNCTION TO_CHAR (left NUMBER, right VARCHAR2) RETURN VARCHAR2;
Si, por alguna circunstancia, volvemos a declarar alguna de esas funciones desde un programa
PL/SQL, siempre podremos hacer referencia a la original mediante la notacin de punto. Por
ejemplo, . . . [Link] ( ... ) ...
- DBMS_STANDARD incluye utilidades, come, el procedimiento RAISE_APLICATION
ERROR, que facilitan la interacci6n de nuestras aplicaciones con Oracle.
- En DBMS_OUTPUT se encuentra el procedimiento PUT_LINE que hemos venido uti-
lizando para visualizar datos, y otros como ENABLE y DISABLE, que permiten con-
figurar y purgar el buffer utilizado por PUT_LINE.
- DBMS_SQL incorpora procedimientos y funciones que permiten utilizar SQL dinmico
en nuestros programas, tal come, veremos en el apartado siguiente.

SQL DINMICO
Cuando se compila un procedimiento PL/SQL, comprueba en el diccionario de datos y completa
todas las referencias a objetos de la base de datos (tablas, columnas, usuarios, etc.). De esta
forma, si algn objeto no existe en el momento de la compilacin, el proceso fallar, indicando el
error correspondiente.
Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 225 - Mario Juncos Murcia
Esta manera de trabajar tiene importantes ventajas, especialmente en cuanto a velocidad en la
ejecucin y a la seguridad de que las referencias a los objetos han sido comprobadas previamente;
pero tambin tiene algunos inconvenientes:
Todos los objetos tienen que existir en el momento de la compilacin.
No se pueden crear objetos nuevos con el programa.
No se puede cambiar la definicin de los objetos.
Cualquier referencia a un objeto debe ser conocida y resuelta en tiempo de compilacin.
Esta forma de trabajar con SQL se denomina SQL esttico, por razones obvias.
El paquete DBMS_SQL permite superar estas limitaciones y ejecutar instrucciones de definicin
de datos, as como resolver referencias a objetos en el momento de la ejecucin. A esta forma de
trabajar se le denomina SQL dinmico.
El siguiente programa es capaz de ejecutar rdenes de definicin y manipulacin sobre objetos
que solo se conocern al ejecutar el programa, ya que el comando se pasar en la llamada al
procedimiento:
CREATE OR REPLACE PROCEDURE ejsqldin
(instruccin VARCHAR2)
AS
Id_cursor INTEGER;
V_dummy INTEGER;
BEGIN
Id_cursor := DBMS_SQL.OPEN_CURSOR; /*Abrir*/
DBMS_SQL.PARSE(id_cursor, instruccin, DBMS_SQL.V7); /*Analiz*/
V_dummy := DBMS_SQL.EXECUTE(id_cursor); /*Ejecut*/
DBMS_SQL.CLOSE CURSOR(id_cursor); l*Cerrar*/
EXCEPTION
WHEN OTHERS THEN
DBMS_SQL.CLOSE CURSOR(id_cursor); /*Cerrar/
RAISE;
END ejsqldin;
En este ejemplo podemos observar resaltadas las lneas correspondientes a las cuatro operaciones
ms frecuentes que se suelen realizar al programar con SQL dinmico, as como los subprogramas
que se encargan de realizar dichas operaciones, incluidos en DBMS_SQL:
- DBMS_SQL.OPEN_CURSOR abre el cursor y devuelve un numero de identificacin
para poder utilizarlo. Recordemos que todos los comandos SQL se ejecutan dentro de un
cursor.
- DBMS_SQL.PARSE analiza la instruccin que se va a ejecutar. Este paso es necesario,
ya que cuando se compil el programa, la instruccin no pudo ser analizada, pues aun no
se habr construido.
- DBMS_SQL.EXECUTE se encarga de la ejecucin.
Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 226 - Mario Juncos Murcia
- DBMS_SQL.CLOSE CURSOR cierra el cursor utilizado.
Es muy importante tener en cuenta que, cuando se definen objetos dinmicamente, el propietario
del procedimiento deber tener concedidos los privilegios necesarios (CREATE USER, CREATE
TABLE, etc.) de forma directa, no mediante un rol.
SQL> EXECUTE EJSQLDIN('CREATE USER DUMM1 IDENTIFIED BY DUMM1')
begin EJSQLDIN('CREATE USER DUMM1 IDENTIFIED BY DUMM1'); end;
*
ERROR en lnea 1:
ORA_01031: privilegios insuficientes
ORA_06512: en "[Link]", lnea 14
ORA_06512: en lnea 1
Observemos que se trata del usuario SYSTEM, pero tiene el privilegio CREATE USER mediante
un rol. Para solucionar el problema se concede el privilegio de forma directa:
SQL> GRANT CREATE USER TO SYSTEM;
Concesin terminada con xito.

SQL> EXECUTE EJSQLDIN('CREATE USER DUMM1 IDENTIFIED BY DUMM1')
Procedimiento PL/SQL terminado con xito.
A continuacin podemos observar otros ejemplos de ejecucin:
SQL> EXECUTE EJSQLDIN('CREATE TABLE PR1 (C1 CHAR)');
Procedimiento PL/SQL terminado con xito.

SQL> EXECUTE EJSQLDIN('ALTER TABLE PR1 ADD COMENTARIO VARCHAR2(20)')
Procedimiento PL/SQL terminado con xito.

SQL> DESCRIBE PR1
Name Null? Type
______________________ ________ _______________
C1 CHAR (1)
COMENTARIO VARCHAR2(20)

Pasos para utilizar SQL dinmico
Aunque hay diferencias dependiendo del tipo de instruccin que se va a procesar, los pasos que
hay que seguir son los siguientes:
Abrir el cursor (OPEN_CURSOR) y guardar su numero de identificacin para posteriores
referencias.
Analizar (PARSE) el comando que se va a procesar.
Si se van a pasar valores al comando, acoplar las variables de entrada (BIND).
Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 227 - Mario Juncos Murcia
o Si el comando es una consulta:
o Definir columnas (DEFINE_COLUMN).
o Ejecutar (EXECUTE).
Recuperar los valores con FETCH_ROWS y COLUMN_VALUE
Si se trata de un comando de manipulacin, ejecutar (EXECUTE).
Cerrar el cursor (CLOSE CURSOR).

Comandos de definicin de datos
Como ya hemos visto, utilizando los procedimientos y funciones incluidos en el paquetes
DBMS_SQL, podemos crear objetos en tiempo de ejecucin. Por ejemplo, el siguiente
procedimiento crear una tabla de una sola columna cuyos datos se pasarn en la llamada al
procedimiento
CREATE OR REPLACE PROCEDURE creartabla
(nombretabla VARCHAR2,
nombrecol VARCHAR2,
longitudcol POSITIVE)
AS
Id_cursor INTEGER;
V_ comando VARCHAR2(2000);
BEGIN
Id_cursor := DBMS_SQL.OPEN CURSOR; /*Abre el cursor*/
V_comando := CREATE TABLE || nombretabla || (
|| nombrecol || VARCHAR2( || longitudcol || ));
DBMS_SQL.PARSE(id_ cursor, v_comando, DBMS_SQL.V7);/*Analiza y ejecuta*/
DBMS_SQL.CLOSE_CURSOR(id_cursor); /*Cierra el cursor*/
EXCEPTION
WHEN OTHERS THEN
DBMS_SQL.CLOSE_CURSOR(id_cursor);
RAISE;
END creartabla;

OPEN_CURSOR. Esta funcin abre un cursor nuevo y retorna un identificador del
mismo, que se guarda en una variable y servir para hacer referencia al cursor desde el
programa.
PARSE. Analiza el comando comprobando posibles errores. Si se trata de un
comando DDL (como en este caso), PARSE, adems, lo ejecuta. Recibe tres
parmetros:
El identificativo del cursor.
La cadena que contiene el comando (sin el ;).
El indicador del lenguaje, que determina la manera en que Oracle manejar
el comando SQL. Estn disponibles las siguientes opciones:
Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 228 - Mario Juncos Murcia
V6: estilo Oracle versin 6.
V7: estilo Oracle versin 7 (es el mismo para la versin 8).
NATIVE: estilo normal de la base en la que este conectado el
programa.
- CLOSE CURSOR. Cierra el cursor especificado y libera la memoria utilizada por el
cursor.
Los objetos se crearn por defecto en el esquema del usuario propietario del procedimiento.
Si se pretende crearlos en otro esquema, se deber indicar explcitamente.
Comandos de manipulacin de datos
El siguiente ejemplo muestra la utilizacin de PL/SQL dinmico para introducir datos en una
tabla que se indicar en la llamada (las llamadas a PUT_LINE se utilizan para ilustrar el fun-
cionamiento del programa):
CREATE OR REPLACE PROCEDURE introducir_fila
(nombretabla VARCHAR2,
valor VARCHAR2)
AS
Id
_
cursor INTEGER;
v_comando VARCHAR2(2000);
v_filas INTEGER;
BEGIN
Id_cursor := DBMS_SQL.OPEN_CURSOR;
V_comando := INSERT INTO || nombretabla || VALUES (:val_1)';
DBMS_OUTPUT.PUT_LINE(v_comando);
DBMS_SQL.PARSE (id_cursor, v_comando, DBMS_SQL.v7);
DBMS_SQL.BIND_VARIABLE(id_cursor, :val 1, valor); /*Acopla la
variable que pasara el valor de entrada*/
v_filas := DBMS
_
[Link](id_cursor); /*Ejecuta el comando*/
DBMS_SQL.CLOSE_CURSOR(id_cursor);
DBMS_OUTPUT.PUT_LINE( Filas introducidas: || v_filas);
EXCEPTION
WHEN OTHERS THEN
DBMS_SQL.CLOSE_CURSOR(id_cursor);
RAISE;
END introducir_fila;
En este ejemplo podemos apreciar que, para introducir dinmicamente comandos de manipulacin
de datos, utilizamos los procedimientos y funciones estudiados en el apartado anterior:
OPEN_CURSOR, PARSE y CLOSE_CURSOR. Pero, adems, utilizaremos el procedimiento
EXECUTE (necesario para comandos de manipulacin y consulta). Tambin se utiliza en este
caso el procedimiento BIND_VARIABLE para acoplar la variable con el valor de entrada.
Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 229 - Mario Juncos Murcia
A continuacin podemos observar un ejemplo de ejecucin del procedimiento cuyo resultado es
insertar una fila en la tabla mitabla que suponemos creada previamente:
SQL> execute introducir_fila( mitabla, HOLA MUNDO);
INSERT INTO mitabla VALUES (:val_1)

Filas introducidas: 1
Procedimiento PL/SQL terminado con xito.
Podemos comprobar el resultado de la ejecucin introduciendo la siguiente consulta:
SQL> select * from mitabla;
COL1
HOLA MUNDO

CONSULTAS
El siguiente ejemplo permite obtener el nmero de empleado, el apellido y el oficio de los
empleados que cumplan la condicin que se especificar en la llamada:
CREATE OR REPLACE PROCEDURE consultar emple
(condicin VARCHAR2,
valor VARCHAR2)
AS
Id_cursor INTEGER;
v_comando VARCHAR2(2000);
v_dummy NUMBER;
v_emp_no emple.emp_no%TYPE;
v_apellido [Link]%TYPE;
v_oficio [Link]%TYPE;
BEGIN
id cursor := DBMS
_
SQL.OPEN_CURSOR;
v_comando := SELECT emp_no, apellido, oficio
FROM emple
WHERE || condicion || :val_1;
DBMS_OUTPUT.PUT_LINE(v_comando);
DBMS_SQL.PARSE(id_cursor, v_comando, DBMS_SQL.V7);
DBMS_SQL.BIND_VARIABLE(id_cursor, :val_1, valor);

/* A continuacin se especifican las variables que recibirn los valores de la seleccion*/
DBMS_SQL.DEFINE
_
COLUMN(id_cursor, 1, vemp_no);
DBMS_SQL.DEFINE
_
COLUMN(id_cursor, 2, v_apellido,14);
DBMS_SQL.DEFINE_COLUMN(id_cursor, 3, v_oficio, 14);
v_dummy := DBM_SQL.EXECUTE(id_cursor);

/* La funcin FETCH ROWS recupera filas y retoma el numero de filas que quedan */
Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 230 - Mario Juncos Murcia
WHILE DBMS_SQL.FETCH_ROWS(idcursor)>0 LOOP
/* A continuacin se depositaran los valores recuperados en las variables PL/SQL */
DBMS_SQL.COLUMN_VALUE(id_cursor, 1, v_emp_no);
DBMS_SQL.COLUMN_VALUE(id_cursor, 2, v_apellido);
DBMS_SQL.COLUMN_VALUE(id_cursor, 3, v_oficio);
DBMS_OUTPUT.PUT
_
LINE (v_emp_no || * || vapellido || * || v_oficio);
END LOOP;
DBMS_SQL.CLOSE_CURSOR(id_cursor);
EXCEPTION
WHEN OTHERS THEN
DBMS_SQL.CLOSE_CURSOR(id_cursor);
RAISE;
END consultar_emple;
La principal diferencia de este programa con los anteriores es que, en este caso, como ocurre en
todas las consultas, hay que recoger los valores obtenidos por la consulta. Para ello se utilizan los
siguientes procedimientos y funciones:
DEFINE _COLUMN: sirve para especificar las variables que recibirn los valores de la
seleccin. Se utilizar una llamada para cada variable indicando:
o El identificador del cursor.
o El numero de la columna de la clusula SELECT de la que recibir el valor.
o El nombre de la variable.
o Si la variable es de tipo CHAR, VARCHAR2 o RAW, hay que especificar la
longitud.
FETCH_ROWS: es similar al comando FETCH de PL/SQL esttico, pero con dos par-
ticularidades muy importantes:
o Devuelve un valor numrico que indica el numero de files que quedan por
recuperar en el cursor. Puede servir, como en el ejemplo, para controlar el numero
de iteraciones del bucle.
o Para introducir los datos recuperados en las variables PL/SQL todava hay que uti-
lizar el siguiente procedimiento.
COLUMN_VALUE: deposita el valor de un elemento del cursor (recuperado con FETCH
ROWS) cuya posicin se especifica en una variable PL/SQL. Normalmente se trata de la
variable indicada en COLUMN_VALUE para el mismo elemento del cursor.



Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 231 - Mario Juncos Murcia
SQL> EXECUTE CONSULTAR EMPLE(SALARIO > ,38500)
SELECT emp_no, apellido, oficio
FROM emple
WHERE SALARIO > :val l

7566*JIMNEZ*DIRECTOR
7788*GIL*ANALISTA
7839*REY*PRESIDENTE
7902*FERNANDEZ*ANALISTA
Procedimiento PL/SQL terminado con xito.

SQL> EXECUTE CONSULTAR_EMPLE('APELLIDO LIKE ', '%EZ')
SELECT emp_no, apellido, oficio
FROM emple
WHERE APELLIDO LIKE :val_1

7369*SANCHEZ*EMPLEADO
7566*JIMENEZ*DIRECTOR
7902*FERNANDEZ*ANALISTA
Procedimiento PL/SQL terminado con xito.

ELIMINACIN DE UN PAQUETE
DROP PACKAGE nombre_paquete
DROP PACKAGE BODY nombre_paquete
Al igual que en los subprogramas se permite la sobrecarga y la declaracin avanzada

Creacin de un Procedimiento "One_Time_Only"
Un procedimiento "one_time_only" se ejecuta una sola vez, la primera vez que se llama al
paquete dentro de la sesin de usuario. En el ejemplo de arriba, el valor de la comisin que
prevalece est definido al principio de la sesin para hacer la media de comisin entre los
empleados.
Es aconsejable inicializar las variables pblicas o privadas con un procedimiento automtico
one_time_only cuando la derivacin es demasiado compleja para definirse dentro de la
declaracin. En este caso, no inicializar la variable en la declaracin, ya que el valor ser
redefinido por el procedimiento one_time_only.

Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 232 - Mario Juncos Murcia

CREATE OR REPLACE PACKAGE BODY comision_Package IS
FUNCTION validar_comision
......................
END validar_comision;
PROCEDURE reset_comision
.......................................
END reset_comision;
BEGIN
SELECT AVG(comision) INTO g_comision
FROM emp;
END comision_package;

Restricciones sobre las Funciones de un Paquete utilizadas en SQL
No se permiten INSERT, UPDATE, o DELETE.
Slo funciones locales pueden modificar variables de un paquete.
Las funciones remotas no pueden leer o escribir variables remotas de un paquete.
Las funciones que leen o escriben variables de un paquete no pueden usar la opcin de
consultas en paralelo (parallel query)
Las llamadas a subprogramas que rompan las restricciones anteriores no se permiten.
Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 233 - Mario Juncos Murcia
VISIN GENERAL DE LOS TRIGGERS
Un trigger es un bloque PLSQL que se ejecuta implcitamente cuando ocurre un evento.
Un trigger puede ser "de la base de datos" o "de la aplicacin".
Los triggers de la base de datos se ejecutan de forma implcita cuando se lanza una sentencia
INSERT, UPDATE, o DELETE (sentencias de triggers) contra la tabla asociada, sin importar
qu usuario est conectado o qu aplicacin se est utilizando.
Los triggers de la aplicacin se ejecutan de forma implcita cuando ocurre un evento en particular
dentro de la aplicacin. Un ejemplo de una aplicacin que usa triggers, es una aplicacin
desarrollada con Oracle Developer Form Builder.
Los triggers de la base de datos pueden definirse solamente sobre tablas, no sobre vistas. Sin
embargo, si se lanza una operacin DML contra una vista, se ejecutan los triggers sobre las tablas
de la vista.

Guia para el Diseo de Triggers
Realizar acciones relacionadas a la operacin especfica.
Utilizar triggers de la base de datos para las operaciones globales centralizadas que seran
ejecutadas por la sentencia de trigger, independientemente de qu usuario o aplicacin emita la
sentencia
No reinventar la rueda. No definir triggers para duplicar o reemplazar la funcionalidad ya
construida dentro de la base de datos Oracle. Por ejemplo no definir triggers para implementar las
reglas de integridad que puede hacerse utilizando restricciones declarativas.
Prestar atencin a los excesos, pueden causar dependencias complejas El uso excesivo de
triggers puede dar lugar a interdependencias complejas, lo que podra dificultar el mantenimiento
en aplicaciones largas. Utilizar triggers solo cuando sea necesario, y tener cuidado con los efectos
recursivos y en cascada.

Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 234 - Mario Juncos Murcia
Creacin de Triggers
CREATE [OR REPLACE] TRIGGER nombre_trigger
momento evento1 [OR evento2 OR evento3]
ON table name
PL/SQL block;
Antes de codificar el cuerpo del trigger hay que decidir sobre los componentes del trigger: tiempo,
evento y tipo.
Momento: Cundo debera dispararse?
BEFORE: El cdigo del cuerpo del trigger se ejecutar antes del evento [Link] tipo de
trigger se utiliza frecuentemente en las siguientes situaciones:
Cuando la accin del trigger debera determinar si se tendra que permitir que se complete
la sentencia de trigger. Esto nos permite eliminar el proceso innecesario de sentencias y
su posible rollback en casos donde se produce una excepcin en la accin del trigger.
Para derivar valores de columna antes de completar una sentencia INSERT o UPDATE.
AFTER: El cdigo del cuerpo del trigger se ejecutar despues del evento [Link] tipo de
trigger se utiliza frecuentemente en las siguientes situaciones:
Cuando queremos que la sentencia se complete antes de ejecutar la accin del trigger.
Si ya hay un "BEFORE trigger" y un "AFTER trigger" podemos realizar diferentes
acciones sobre la misma sentencia.
Evento: Qu operacin DML provocar la ejecucin trigger?
El evento puede ser una sentencia INSERT, UPDATE, o DELETE sobre una tabla. Cuando el
evento es UPDATE, podemos incluir una lista de columnas para identificar que columna(s) deben
cambiarse para ejecutar el trigger. No podemos especificar una lista de columnas para una
sentencia INSERT o DELETE, ya que siempre afectan a los registros enteros.
El evento puede contener mltiples sentencias DML. De esta forma, podemos diferenciar qu
cdigo ejecutar dependiendo de la sentencia que hace que se ejecute el trigger.

Tipo de Trigger:
Podemos especificar el nmero de veces que se va a ejecutar la accin de un trigger: una vez para
cada registro afectado por la sentencia del trigger (como un UPDATE de mltiples registros), o
una vez para la sentencia del trigger, sin importar a cuantos registros afecte.


Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 235 - Mario Juncos Murcia
Sentencia
Un trigger a nivel de sentencia se ejecuta una vez cuando se produce el evento, incluso si no se
ve afectado ningn registro.
Los triggers a nivel de sentencia son tiles si la accin del trigger no depende de datos o de los
registros que son afectados por los datos proporcionados por el evento mismo. Por ejemplo, un
Trigger que realiza una comprobacin completa de seguridad sobre el usuario actual.
Fila
Un trigger a nivel de fila se ejecuta cada vez que la tabla es afectada por el evento. Si el evento
no afecta a ningn registro, el trigger no se ejecuta.
Los triggers a nivel de fila son tiles si la accin del disparador depende de los datos de los
registros que estn afectados o de los datos proporcionados por el evento mismo.
Cuando la manipulacin de los datos de la sentencia afecta a un registro nico, el trigger a nivel
de sentencia y el trigger a nivel de registro se ejecutan exactamente una vez.

Cuerpo del Trigger:
La accin del trigger define qu se necesita hacer cuando se emite el evento. Puede contener
sentencias SQL Y PL/SQL, definir construcciones PL/SQL como pueden ser variables, cursores,
excepciones, etc.
Adicionalmente, los registros tienen acceso a los valores de columna nuevos y viejos del registro
que se est procesando, utilizando nombres de correlacin.

Trigger "Before Statement".
Podemos crear un trigger BEFORE a nivel de sentencia con el fin de prevenir que suceda la
operacin del trigger si se viola cierta condicin. Por ejemplo vamos a crear un disparador para
restringir las inserciones en la tabla EMP a ciertas horas, de Lunes a Viernes. Si un usuario intenta
insertar un registro en la tabla EMP en Sbado, por ejemplo, el usuario ver el mensaje, fallar el
trigger y se har rollback sobre las sentencias del Trigger.
RAISE_APPLICATION_ERROR es un procedimiento que imprime un mensaje para el usuario
y provoca que falle el bloque PL/SQL. Cuando falla un trigger de la base de datos, Oracle Server
hace rollback sobre las sentencias del trigger.


Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 236 - Mario Juncos Murcia
SQL> CREATE OR REPLACE TRIGGER secure_emp
2 BEFORE INSERT ON emp
3 BEGIN
4 IF (TO_CHAR (sysdate,DY) IN (SAT','SUN'))
5 OR (TO_CHAR(sysdate,HH24) NOT BETWEEN '08' AND '18'
6 THEN RAISE_APPLICATION_ERROR (_20500, 'You may only 7
insert into EMP during normal hours);
7 END IF;
8 END;

Uso de Predicados Condicionales
Podemos combinar varios eventos de trigger en uno slo aprovechando los predicados
condicionales INSERTING, UPDATING y DELETING dentro del cuerpo del trigger. Por
ejemplo vamos a crear un trigger para restringir todos los eventos de manipulacin de datos en la
tabla EMP a ciertas horas, de Lunes a Viernes.
CREATE OR REPLACE TRIGGER secure_emp
BEFORE INSERT OR UPDATE OR DELETE ON emp
BEGIN
IF(TO_CHAR (sysdate,DY) IN ('SAT,SUN))
OR (TO_CHAR(sysdate, HH24) NOT BETWEEN '08' AND '18') THEN
IF DELETING THEN
RAISE_APPLICATION_ERROR (_20502,
'You may only delete from EMP during normal hours.');
ELSIF INSERTING THEN
RAISE_APPLICATION_ERROR (_20500,
You may only insert into EMP during normal hours.);
ELSIF UPDATING ('SAL') THEN
RAISE_APPLICATION_ERROR (_20503,
'You may only update SALARIOduring normal hours.);
ELSE
RAISE_APPLICATION_ERROR (_20504,
'You may only update EMP during normal hours.);
END IF;
END IF;
END;
Utilizar tambin triggers BEFORE a nivel de sentencia para inicializar las variables globales o
flags, y para validar reglas de negocio complejas.


Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 237 - Mario Juncos Murcia
Trigger After Sentencia: Ejemplo
Crear un trigger AFTER a nivel de sentencia con el fin de auditar la operacin de trigger o realizar
un clculo despus que se ha completado la operacin.
Supongamos que tenemos una tabla de auditoria definida por el usuario (usuario, tabla, columna,
inserciones, actualizaciones, borrados, max_inser, max_act, max_borrados) que relaciona los
usuarios y cuenta sus operaciones de manipulacin de datos. Despus de que cualquier usuario
haya actualizado la columna SALARIO en la tabla EMP, utilizaremos la tabla de auditoria para
asegurarnos que el nmero de cambios del salario no excede del mximo permitido para ese
usuario.
CREATE OR REPLACE TRIGGER check_salario_count
AFTER UPDATE OF salarioON emp
DECLARE
V_salario_changes NUMBER;
V_max_changes NUMBER;
BEGIN
SELECT actualizaciones, max_act INTO v_salario_changes, v_max_changes
FROM audit_table
WHERE user_name = user
AND table_name = EMP
AND column_name = 'SAL';
IF v_salario_changes > v max_changes THEN
RAISE_APPLICATION_ERROR (_20501,
You may only make a maximum of || TO_CHAR (v_max_changes) ||
changes to the SALARIOcolunm' );
END IF;
END;

Creacin de un Trigger a Nivel de Registro
CREATE [OR REPLACE] TRIGGER trigger_name
momento eventol [OR evento2 OR evento3]
ON table_name
[REFERENCING OLD AS old / NEW AS new ]
FOR EACH ROW
[WHEN condition]
PL/SQL block;

Referencing Especifica los nombres de correlacin de los valores nuevo y antigo del registro
actual. (Por defecto son OLD y NEW)
FOR EACH ROW Designa el trigger a nivel de registro.
Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 238 - Mario Juncos Murcia
WHEN Especifica la restriccin del trigger. (Este predicado condicional es evaluado por cada
registro para determinar si se ejecuta o no el cuerpo del trigger)
PL/SQL block Es el cuerpo del trigger que define la accin realizada por el trigger, comenzando
con DECLARE or BEGIN, y finalizando con END

Trigger After a nivel fila: ejemplo
Crear un trigger de registro para mantenter un contador de las operaciones de manipulacin de
datos en las tablas de la base de datos por diferentes usuarios.
Si la rutina de un trigger no tiene lugar antes de la operacin de trigger, crear un trigger
"AFTER row" en lugar de un trigger "BEFORE row".
CREATE OR REPLACE TRIGGER audit_emp
AFTER DELETE OR INSERT OR UPDATE ON emp
FOR EACH ROW
BEGIN
IF DELETING THEN
UPDATE audit_table SET del = del + 1
WHERE user_name = user AND table_name = EMP
AND column_name IS NULL;
ELSIF INSERTING THEN
UPDATE audit_table SET ins = ins + 1
WHERE user_name = user AND tabla name = EMP
AND column_name IS NULL;
ELSIF UPDATING ('SAL') THEN
UPDATE audit_table SET upd = upd + 1
WHERE user_name = user AND table_name = EMP
AND colunm_name = 'SAL';
ELSE /* The data manipulation operation a general UPDATE*/
UPDATE audit_table SET upd = upd + 1;
WHERE user_name = user AND table_name = EMP
AND column name IS NULL;
END IF;
END;

Uso de los calificadores 0LD y "NEW
Crear un trigger sobre la tabla EMP para aadir registros a la tabla de auditora,
AUDIT_EMP_VALUES, que contiene la actividad del usuario contra la tabla EMP. El trigger
registra los valores de varias columnas antes y despus del cambio de datos utilizando
cualificadores OLD y NEW con el respectivo nombre de columna.
Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 239 - Mario Juncos Murcia
Dentro de un trigger a nivel de fila, referenciamos el valor de una columna antes y despus del
cambio de los datos, prefijndolo con los cualificadores OLD y NEW.
CREATE OR REPLACE TRIGGER audit_emp_values
AFTER DELETE OR INSERT OR UPDATE ON emp
FOR EACH ROW
BEGIN
INSERT INTO audit_emp_values (usuario, fecha, empleado, nombre_ant,
nombre_nuevo, oficio_ant, oficio_nuevo, salario_ant, salario_nuevo)
VALUES (USER, SYSDATE, :[Link], :[Link], :[Link], :[Link],
:[Link], :[Link], :[Link]);
END;

Operacin de Datos Valor Antiguo Valor Nuevo
INSERT NULL Valor insertado
UPDATE Valor antes de actualizar Valor despus de actualizar
DELETE Valor antes de borrar NULL

Los cualificadores OLD y NEW solo estn disponibles en triggers a nivel de fila
Prefijar estos cualificadores con dos puntos en cada sentencia PL/SQL y SQL.
No se ponen los dos puntos si estn referenciados en la condicin de restriccin WHEN.

Condicionando un Trigger de Registro
Para restringir la accin del trigger slo a aquellos registros que satisfacen cierta condicin,
proporcionar una clasula WHEN.
Crear un trigger en la tabla EMP para calcular la comisin de un VENDEDOR cuando se aade
un registro a la tabla EMP o cuando se modifica el salario del VENDEDOR.
El cualificador NEW no necesita ir prefijado con dos puntos en la clasula WHEN.
Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 240 - Mario Juncos Murcia
CREATE OR REPLACE TRIGGER derive_comision_pct
BEFORE INSERT OR UPDATE OF salario ON emp
FOR EACH ROW
WHEN ([Link] = 'VENDEDOR')
BEGIN
IF INSERTING THEN
:[Link]:= 0;
ELSE -- UPDATE of salario
IF :[Link] NULL THEN
:[Link] :=0;
ELSE
:[Link]:= :[Link]* (:[Link]/:[Link]);
END IF;
END IF;
END;

Diferenciando entre Triggers y Procedimientos Almacenados
TRIGGER PROCEDURE
Usa CREATE TRIGGER Usa CREATE PROCEDURE
El Dic. de datos contiene el cdigo fuente y el P_Code
Invocados implcitamente Invocados explcitamente
NO se permite: COMMIT,SAVEPOINT,
ROLLBACK
Si se permite COMMIT,SAVEPOINT,
ROLLBACK

Los triggers se compilan completamente cuando se lanza el comando CREATE TRIGGER y se
almacena el p_code en el Diccionario de Datos. Por lo tanto, la ejecucin del trigger ya no
requiere la apertura de un cursor compartido para realizar la accin. En su lugar, el trigger se
ejecuta directamente.
Aun habiendo algn error durante la compilacin de un trigger, ste se crea.

RESTRICCIONES PARA LA CREACIN DE TRIGGERS
El cdigo PL/SQL del cuerpo del trigger puede contener instrucciones de consulta y de
manipulacin de datos, as como llamadas a otros subprogramas. No obstante, existen
restricciones que deben ser contempladas:
Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 241 - Mario Juncos Murcia

El bloque PL/SQL no puede contener sentencias de control de transacciones como
COMMIT, ROLLBACK o SAVEPOINT.
Tampoco se pueden hacer llamadas a procedimientos que transgredan la restriccin
anterior.
No se pueden utilizar comandos DDL.
Un trigger no puede contener instrucciones que consulten o modifiquen tablas mutan-
tes. Una tabla mutante es aquella que esta siendo modificada por una sentencia
UPDATE, DELETE o INSERT en la misma sesin.
No se pueden cambiar valores de las columnas que sean claves primaria, nica o ajena
de tablas de restriccin. Una tabla de restriccin es una tabla que debe ser consultada
o actualizada directa o indirectamente por el comando que dispar el trigger
(normalmente, debido a una restriccin de integridad referencial) en la misma sesin.
Los triggers a nivel de comando (FOR EACH STATEMENT) no se vern afectados por las
restricciones que acabamos de enunciar para las tablas mutantes y tablas de restriccin,
excepto cuando el trigger se dispare como resultado de una restriccin ON DELETE
CASCADE.
Disparadores de sustitucin
Se pueden crear triggers que no se ejecuten ni antes ni despus, sino en lugar de (INSTEAD
OF) la orden de manipulacin que da lugar al disparo del trigger. Se denominan disparadores
de sustitucin.
El formato genrico para la creacin de estos disparadores de sustitucin es:
CREATE [OR REPLACE] TRIGGER nombretrigger
INSTEAD OF {DELETE / INSERT / UPDATE [OF <lista columnas> }
[OR {DELETE / INSERT / UPDATE [OF <lista columnas> }] ..
ON nombrevista
[FOR EACH ROW]
/* aqu comienza el bloque PL/SQL */
[DECLARE
<declaraciones>]
BEGIN
<acciones>
[EXCEPTION
<gestin de excepciones>]
END;
Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 242 - Mario Juncos Murcia
Los disparadores de sustitucin tienen estas caractersticas diferenciales:
Solamente se utilizan en triggers asociados a vistas, y son especialmente tiles para
realizar operaciones de actualizacin complejas.
Actan siempre a nivel de fila, no a nivel de orden, por tanto, a diferencia de lo que
ocurre en los disparadores asociados a una tabla, la opcin por omisin es FOR
EACH ROW
No se puede especificar una restriccin de disparo mediante la clusula WHEN (pero
se puede conseguir una funcionalidad similar utilizando estructuras alternativas dentro
del bloque PL/SQL).

Activar, desactivar, compilar y eliminar un trigger
Un trigger puede estar activado o desactivado. Cuando se crea est activado, pero podemos
variar esta situacin mediante: ALTER TRIGGER nombretrigger DISABLE.
Para volver a activarlo utilizamos: ALTER TRIGGER nombretrigger ENABLE.
Para volver a compilar emplearemos: ALTER TRIGGER nombretrigger COMPILE
Para eliminar un trigger escribiremos: DROP TRIGGER nombretrigger.

Vistas con informacin sobre los triggers
Las vistas dba_triggers y user_triggers contienen toda la informacin sobre los triggers. La
estructura de estas vistas se muestran a continuacin con algunos ejemplos.
SQL> SELECT TRIGGER_NAME, TABLE_NAME, TRIGGERING_EVENT,
TRIGGER_TYPE, STATUS FROM USER_TRIGGERS;

TRIGGER_NAME TABLE_NAME TRIGGERING_EVENT TRIGGER_TYPE STATUS
AUDIT_SUBIDA_SALARIO EMPLEADOS UPDATE AFTER EACH ROW ENABLED
T_GES_ EMPLEAD EMPLEAD INSERT OR UPD... INSTEAD OF ENABLED


Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 243 - Mario Juncos Murcia
SQL> SELECT TRIGGER_BODY FROM USER_TRIGGERS;

TRIGGER_BODY
BEGIN
insert INTO auditaremple VALUES ( SUBIDA SALARIO EMPLEADO || :old.e
....
DECLARE
V_dept depart.dept_no

%TYPE;
BEGIN
IF DELETING THEN
.

SQL> describe dba_triggers
Name Null? Type
OWNER NOT NULL VARCHAR2(30)
TRIGGER NAME NOT NULL VARCHAR2(30)
TRIGGER TYPE VARCHAR2(16)
TRIGGERING_EVENT VARCHAR2(26)
TABLE OWNER NOT NULL VARCHAR2(30)
TABLE NAME NOT NULL VARCHAR2(30)
REFERENCING NAMES VARCHAR2(87)
WHEN_CLAUSE VARCHAR2(2000)
STATUS VARCHAR2(8)
DESCRIPTION VARCHAR2(2000)
TRIGGER BODY LONG

Modos de Trigger: Activado o Desactivado
Cuando se crea por primera vez un trigger, ste se activa automticamente. Oracle Server
comprueba las restricciones de integridad de los triggers activados y garantiza que los triggers no
pueden violar restricciones de integridad. Adems, Oracle Server proporciona vistas de lectura
consistente para consultas y restricciones, gestiona las dependencias y proporciona commit en dos
fases si un trigger actualiza tablas remotas en una base de datos distribuida.
Utilizando la sentencia ALTER TRIGGER se desactiva un trigger especfico y utilizando la
sentencia ALTER TABLE se desactivan todos los triggers en una tabla.
Desactivar un trigger para mejorar el rendimiento o para evitar comprobaciones de la integridad
de los datos cuando se cargan cantidades masivas de datos a travs de utilidades como
SQL*Loader. Podramos desear desactivar el trigger cuando ste referencia a un objeto de la
base de datos que actualmente no est disponible, debido a un fallo en la conexin de la red,
rotura de disco, fichero de datos off_line, o tablespace off_line.
Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 244 - Mario Juncos Murcia
Compilar un Trigger
Utilizar el comando ALTER TRIGGER para recompilar explcitamente un trigger invlido.
Cuando lanzamos una sentencia ALTER TRIGGER con la opcin RECOMPILE, el trigger se
recompila independientemente si ste es vlido o invlido.

Eliminacin de Triggers
Para borrar un trigger de la B.D, utilice la sintaxis DROP TRIGGER trigger_name
Pruebas sobre Triggers
Pruebe cada una de las operaciones de datos sobre los triggers, as como las operaciones sobre
otros datos.
Pruebe cada posibilidad de la clusula WHEN.
Provoque el disparo del trigger directamente desde una operacin bsica de datos, as como
de forma indirecta desde un procedimiento.
Pruebe el efecto del triggers sobre otros triggers.
Pruebe el efecto de otros triggers sobre el trigger actual.
Asegurarse que el trigger funciona de forma apropiada comprobando un nmero de casos por
separado.
Aprovechar los procedimientos DBMS_OUTPUT para depurar triggers.

Modelo de Ejecucin de un Trigger y Comprobacin de Constraints
1. Ejecutar todos los triggers. BEFORE STATEMENT
2. Hacer un loop para los registros afectados:
Ejecutar todos los triggers BEFORE ROW
Ejecutar la sentencia DML y efectuar comprobaciones en cuanto al chequeo de la
integridad.
Ejecutar todos los triggers AFTER ROW
3. Completar el chequeo de las restricciones de integridad diferidas.
Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 245 - Mario Juncos Murcia
4. Ejecutar todos los triggers AFTER STATEMENT
Una nica sentencia DML puede ejecutar potencialmente hasta cuatro tipos de triggers: a nivel de
sentencia y de fila , BEFORE y AFTER. Un evento trigger o una sentencia dentro del trigger
puede producir una o mas restricciones que hay que comprobar. Los triggers tambin pueden
producir que se ejecuten otros triggers (triggers en cascada).
Todas las acciones y comprobaciones hechas como resultado de una sentencia SQL deben
realizarse con xito. Si aparece una excepcin dentro de un trigger y la excepcin no se maneja
explcitamente, se hace roll back sobre todas las acciones realizadas a causa la la sentencia SQL
original, incluyendo las acciones realizadas por la ejecucin de los triggers. Esto garantiza que los
triggers no puedan violar nunca las restricciones de integridad.
Cuando se ejecuta un trigger, las tablas referenciadas en la accin del trigger podran sufrir
cambios por las transacciones de otros usuarios. En todos los casos, se garantiza una imagen de
lectura consistente para los valores modificados que el trigger necesita leer (consulta) o escribir
(actualizacin).

Reglas que Gobiernan los Trigger
La lectura y la escritura de datos utilizando triggers estn sujetas a ciertas reglas.
Regla 1: No lea datos de una tabla mutante.
Regla 2: No cambie datos de la clave primaria, clave foranea, o columnas de clave nica de una
tabla referenciada

Lectura de Datos de una Tabla Mutante
Una tabla mutante es una tabla que est siendo actualmente modificada por una sentencia
UPDATE, DELETE o INSERT, o una tabla que podra necesitar ser actualizada por los efectos
de una accin de integridad referencial ON DELETE CASCADE. Una tabla no se considera
mutante para los STATEMENT triggers.
La tabla del trigger en si misma es una tabla mutante, as como cualquier otra tabla que la
referencia con la restriccin FOREIGN KEY. Esta restriccin previene al trigger de ver un
conjunto inconsistente de datos.

Tabla Mutante: Ejemplo
CREATE OR REPLACE TRIGGER chequea_salario
Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 246 - Mario Juncos Murcia
BEFORE INSERT OR UPDATE OF sal,oficio, ON emp
FOR EACH ROW
WHEN (new_oficio <> PRESIDENTE)
DECLARE
V_minsalario [Link]%TYPE;
V_maxsalario [Link]%TYPE;
BEGIN
SELECT MIN(sal), MAX(sal) INTO V_minsalario, v_maxsalario FROM emp
WHERE oficio = :[Link];
IF :[Link]< v_minsalario OR :[Link]> v_maxsalario THEN
RAISE_APPLICATION_ERROR(_20505, 'Out of range);
END IF;
END;
Este trigger, chequea_salario, garantiza que siempre que se aada un empleado a la tabla EMP o
se cambie un salario o puesto de un empleado existente, el salario del empleado caiga dentro del
rango del salario establecido para el puesto del empleado.
UPDATE emp SET salario= 1500
WHERE ename = SMITH;
ERROR at line 2
ORA_4091 : Table EMP is mutating, trigger/function may not see it
ORA_06512: at line 4
ORA_04088: error during execution of trigger chequea_salario
Tratar de restringir el salario dentro del rango entre el valor mnimo y el valor mximo existentes
produce un error en tiempo de ejecucin. La tabla EMP es mutante, o est en estado de cambio,
por lo tanto el trigger no puede leerla.

Cambiando Datos de una Tabla Restrictiva
Una tabla restrictiva es una tabla que el evento de trigger podra tener la necesidad de leer,
directamente por una sentencia SQL, o indirectamente por una restriccin de integridad
referencial. Los STATEMENT triggers no consideran restrictivas a las tablas.
Ejemplo
Cuando cambia el valor de DEPTNO en la tabla padre DEPT, si intentamos actualizar en cascada
los registros correspondientes en la tabla hija EMP, se producir un error en tiempo de ejecucin.
CREATE OR REPLACE TRIGGER cascade_updates
AFTER UPDATE OF deptno on DEPT
FOR EACH ROW
BEGIN
UPDATE emp
SET [Link] = :[Link]
Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 247 - Mario Juncos Murcia
WHERE [Link] = :[Link];
END;
Este trigger intenta actualizar en cascada la clave foranea para los registros hijos en la tabla EMP,
a partir del cambio de la clave primaria de la tabla DEPT.
UPDATE dept
SET deptno = 1
WHERE deptno = 30;
*
ERROR at line 1:
ORA_04091: table DEPT is mutating, trigger/function may not see it
Cuando un usuario intenta modificar la tabla DEPT se produce un error. La tabla del trigger,
DEPT, referencia a EMP a travs de una restriccin FOREIGN KEY. Por lo tanto, decimos que
EMP es una tabla restrictiva. El trigger CASCADE_UPDATES intenta cambiar los datos en la
tabla restrictiva, lo cual no est permitido.

lmplementacin de Triggers
Desarrollar triggers de base de datos con el fin de realzar las caractersticas que no se pueden ser
mejoradas de otra forma por Oracle Server.
Caracterstica Mejora
Seguridad Oracle Server permite a los usuarios o roles el acceso a las tablas. Los
triggers pemiten el acceso a las tablas segn el valor de los datos
Auditoras Oracle Server audita las operaciones de datos sobre las tablas. Los
triggers auditan los valores de las operaciones de datos sobre las
tablas.
Integridad de datos Oracle Server refuerza las restricciones de integridad. Los triggers
implementan las reglas complejas de integridad.
Integridad referencial Oracle Server refuerza las reglas de integridad. Los triggers
implementan la funcionalidad no standard.
Replicacin de tablas Oracle Server copia tablas de forma asncrona dentro del mecanismo
de snapshots. Los triggers copian tablas de manera sincronizada a
travs de rplicas
Datos derivados Oracle Server calcula manualmente los valores de datos derivados.
Los triggers calculan automticamente los valores de los datos
derivados.
Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 248 - Mario Juncos Murcia
Control de eventos Oracle Server controla eventos explcitamente. Los triggers controlan
eventos de forma transparente
Prctica 12
1.- Crear la especificacin y el cuerpo de un paquete llamado PROD_PACK que
contenga los procedimientos ADD_DEP, UPD_DEP, DEL_DEP y la funcin Q_DEP.
Hacer todos los programas pblicos.
Llamar al procedimiento DEL_DEP.
Consultar la tabla DEPARTAMENTOS para ver el resultado.

2.- Crear y llamar a un paquete que contenga programas privados y pblicos.
Crear la especificacin y el cuerpo de un paquete llamado EMP_PACK que contenga el
procedimiento NEW_EMP como un programa pblico, y la funcin VALID_DEPTNO
como un programa privado.
Llamar al procedimiento NEW_EMP utilizando 99 como nmero de departamento.
Llamar al procedimiento NEW_EMP utilizando 30 como nmero de departamento.

3. Crear un paquete llamado CHK_PACK que contenga los procedimientos
CHK_HIREDATE y CHK_DEPT_MGR. Hacerlos como programas pblicos.
El procedimiento CHK_HIREDATE comprueba si la fecha de contratacin de un
empleado est dentro del siguiente rango: [sysdate - 50 years, sysdate + 3 months]
o Si la fecha es invalida, aparecera un mensaje de error en la aplicacin indicando
por que no se acepta la fecha.
o Asegurese que se ignora el componente del tiempo en el valor de la fecha.
o Utilizar una constante para referirse al lmite de 50 aos.
o Si el valor de la fecha de contrato es un valor nulo, sera considerada como una
fecha de contrato invlida.
El procedimiento CHK_DEPT_MGR comprueba la combinacin del departamento y del
director para un empleado dado. Esto significa que el nmero de director facilitado debe
ser igual al nmero de director que supervisa el departamento del empleado.
Si la combinacin nmero/director del departamento es invlida, aparecera un
mensaje de error en la aplicacin.
Asegurese de controlar el caso en el que no hay director para el departamento.
Comprobar el procedimiento CHK_HIREDATE con los siguientes comandos.

SQL> execute chk_pack.chk_hiredate(01-JAN-47)
SQL> execute chk_pack.chk_hiredate(NULL)
SQL> execute chk_pack.chk_hiredate(01-JAN-98)
Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 249 - Mario Juncos Murcia
Prctica 13
1. Crear un paquete para implementar una nueva regla de negocio.
Crear un procedimiento llamado chk_dept_job para verificar si una combinacin dada de
nmero de departamento y oficio es vlida. En ese caso "vlida" significa que debe ser
una combinacin que actualmente existe en la tabla EMP.
o Utilizar una tabla PLSQL para almacenar las combinaciones vlidas de
departamento y oficio.
o La tabla PLSQL necesita ser rellenada solamente una vez.
o Si la combinacin no es vlida, emitir un mensaje de error en la aplicacin.
Probar el procedimiento CHK_DEPT_JOB ejecutando

SQL> execute chk_pack.chk_dept_job(20, CLERK);
SQL> execute chk_pack.chk_dept_job(40, 'CLERK)

2. Crear dos funciones, cada una llamada PRINT_IT para imprimir una fecha, un nmero
dependiendo de cmo se llam a la funcin.
Para imprimir el valor de fecha, utilizar como formato de entrada "DD-MON-YY" y como
formato de salida "FmMonth/dd/yyyy". Asegurarse de que se manejan entradas invlidas.
Para imprimir el nmero, utilizar como formato de salida "999,999.00".
Comprobar la primera versin de PRINT_IT con el siguiente comando.

SQL> variable todays_date varchar2(20)
SQL> execute :todays_date := over_load.print_it(sysdate)
PL/SQL Procedure successfully completas.
SQL> print todays_date
TODAYS_DATE
January,29/1998
Comprobar la segunda versin de PRINT_IT con el siguiente comando.
SQL> variable g_emp_sal number
SQL> execute :g_emp_sal := over_load.print_it(33,600)
PL/SQL procedure successfully completas.
SQL> print g_emp_sal
G_EMP_SAL
33600
Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 250 - Mario Juncos Murcia
Prctica 14
1.- Solo se permitir DML en las tablas durante horas normales de oficina, de 8,45 de la
maana a 5,30 de la tarde, de Lunes a Viernes.
Cree un procedimiento almacenado llamado SECURE_DML que muestre un mensaje de
error, en caso de no cumplir la regla especificada anteriormente, como "Slo puede
modificar datos durante las horas oficiales de trabajo".

2.-Crear un trigger en la tabla DEPARTAMENTOS que llame al procedimiento de arriba.
Comprobar el procedimiento modificando temporalmente las horas del procedimiento e
intentando insertar un registro en DEPARTAMENTOS. Despus de la comprobacin,
volvamos a definir las horas del procedimiento como se especifica en el paso 1.
3.- La comisin de un vendedor cambiara con cualquier pedido nuevo o por cambios en
los pedidos existentes. Su comisin se almacena en la columna COMM de la tabla EMP. En la
tabla CUSTOMER se asigna un vendedor a un cliente en particular.
Crear un procedimiento que actualizar la comisin de un vendedor. Utilizaremos
parmetros para enviar el identificador del cliente, el total antiguo del pedido y el total
nuevo del pedido, desde el trigger que hace la llamada. El procedimiento necesitar
localizar el nmero del empleado en la tabla CUSTOMER y actualizar el registro del
vendedor en la tabla EMP, aadiendo una nueva comisin al valor existente. Para este
ejercicio pondremos una porcentaje de comisin del 5%.
Crear un trigger en la tabla ORD el cual llamar al procedimiento, pasando los parmetros
necesarios.
Modificar el pedido 601, para asignarle un total de 3. Verificar que la comisin de
WARD se ha incrementado en 0.03. La comisin original era 500.

4. A las tablas EMP y DEPT se les aplica una serie de reglas de negocio.
Decidir cmo implementar cada regla: por medio de restricciones declarativas o triggers.
Reglas del Negocio
Los vendedores siempre deberan recibir una comisin. Los empleados que no son
vendedores nunca debern recibir una comisin.
La tabla EMP debera contener exactamente un PRESIDENT. Comprobar nuestra
respuesta.
Los salarios solo podran aumentarse, no disminuirse. Comprobar nuestra respuesta.
Si un departamento se traslada a otra parte, cada empleado de ese departamento tendr
automticamente un incremento de salario del 2%.
Desarrollo de Aplicaciones en Entornos de Cuarta Generacin y Herramientas CASE


PLSQL - 251 - Mario Juncos Murcia
Prctica 15
1.-Responder las siguientes preguntas:
Pueden una tabla o un sinnimo ser invlidos?
Supongamos el siguiente escenario:

El Procedimiento standalone MY_PROC depende del Procedimiento empaquetado
MY_PROC_PACK.
La definicin del procedimiento MY_PROQ_PACK se cambia mediante la
recompilacin del cuerpo del paquete.
La especificacin del Procedimiento MY_PROQ_PACK no se altera en la
modificacin del paquete.
Se invalida el Procedimiento standalone MY_PROC?

2. Supongamos que hemos perdido el cdigo del Procedimiento NEW_EMP y de la
funcin VALID_DEPTNO que creamos en la prctica 11. Para regenerar el cdigo, crear un
fichero SQL "spool" para consultar la vista apropiada del Diccionario de Datos.

3. Ejecutar el script utldtree. Imprimir una estructura de rbol que muestre todas las
dependencias relacionadas con nuestro procedimiento NEW_EMP y nuestra funcin
VALID_DEPTNO. Consultar la vista "ideptree" para ver los resultados

4.-Validar los objetos invlidos de forma dinmica.
Hacer una copia de la tabla EMP, llamada EMP_COP.
Modificar la tabla EMP y aadir la columnna TOTSAL(NUMBER(9,2))
Crear un fichero script para imprimir el nombre, tipo y status de los objetos invlidos.
Crear un procedimiento llamado COMPILE_OBJ que recompile todos los objetos
invlidos en nuestro esquema.
Utilizar el procedimiento ALTER_COMPILE en el paquete DBMS_DDL.
Ejecutar de nuevo el fichero script previo y comprobar el valor del status de la columna.

También podría gustarte