PL/SQL I
VERSIN 1 JPV-99 1 / 67
PPLL//SSQQLL II
Javier Prez-Vigo (Octubre 1999)
PL/SQL I
VERSIN 1 JPV-99 2 / 67
INTRODUCCIN
ORACLE es un sistema de base de datos relacional potente y flexible.
El lenguaje de programacin PL/SQL est diseado para manipular los
datos desde distintos entornos.
PL/SQL est integrado con el servidor de bases de datos y est en
algunas herramientas de cliente ORACLE, (Developer).
Su conocimiento es imprescindible para la manipulacin de informacin
almacenada en bases de datos ORACLE y para el desarrollo de
cualquier aplicacin en ese entorno.
En esta unidad didctica se definen las principales caractersticas de
este lenguaje y su sintaxis, se enumeran las principales funciones
predefinidas.
As mismo se estudian las rdenes SQL disponibles: de control, de
manipulacin de datos y transaccionales.
Posteriormente se introduce el concepto de cursor y por ltimo se explica
cmo se disea el tratamiento de errores.
PL/SQL I
VERSIN 1 JPV-99 3 / 67
CONTENIDO
1. DEFINICIN Y CARACTERSTICAS DE PL/SQL
2. EL BLOQUE PL/SQL
ZONA DE DECLARACIN: DECLARACIN DE VARIABLES YCONSTANTES
ZONA DE PROCESO
ZONA DE EXCEPCIONES
3. FUNCIONES SQL PREDEFINIDAS
FUNCIONES DE CARCTER QUE DEVUELVEN VALORESDE CARCTER
FUNCIONES DE CARCTER QUE DEVUELVEN VALORESNUMRICOS
FUNCIONES NUMRICAS
FUNCIONES DE FECHA
FUNCIONES DE CONVERSIN
FUNCIONES DE GRUPO
OTRAS FUNCIONES
4. SENTENCIAS DE CONTROL
5. SENTENCIAS DE DML
6 CURSORES
MANEJO DE CURSORES
BUCLES SOBRE CURSORES
EJEMPLO DE CURSORES
7. REGISTROS Y TABLAS
REGISTROS PL/SQL
TABLAS EN PL/SQL
8. SENTENCIAS TRANSACCIONALES
9 CONTROL DE ERRORES
10 RESUMEN
11 EVALUACIN
PL/SQL I
VERSIN 1 JPV-99 4 / 67
OBJETIVOS
El alumno tras el estudio de esta unidad didctica podr:
Conocer la sintaxis y los elementos que componen el lenguaje
PL/SQL.
Consultar y manipular la informacin almacenada en servidores de
Bases de Datos Oracle.
Desarrollar estructuras bsicas de programacin en PL/SQL.
EXPECTATIVAS
PL/SQL I
VERSIN 1 JPV-99 5 / 67
1. DEFINICIN Y CARACTERSTICAS DE PL/SQL
Combina la flexibilidad de SQL con la potencia y configurabilidad de un 3GL al integrar
tanto las necesarias estructuras procedimentales como el acceso a bases de datos.
Nos permite utilizar tcnicas procedurales como bucles, control de flujo, tratamiento de
variables y control de errores en el procesamiento de las filas devueltas en una
SELECT.
Permite tener cdigo ejecutable almacenado en el servidor de base de datos.
PL/SQL, (Procedural Language / SQL), es un lenguaje de programacin
procedural estructurado en bloques que amplia la funcionalidad del lenguaje
standard SQL a travs de estructuras como:
Variables y tipos, (predefinidos y definidos por el usuario)
Estructuras de control, (bucles y condiciones)
Procedimientos y funciones
Tipos de objetos y mtodos, (a partir de versin 8)
IMPORTANTE
DQL. Data Query Language (select)
DML Data manipulation language (insert)
DDL Data definition language (create table)
NOTA
PL/SQL I
VERSIN 1 JPV-99 6 / 67
Es un lenguaje estructurado en bloques: Bloque es la unidad bsica en PL/SQL
Incorpora sentencias DML (INSERT, UPDATE, DELETE)
Maneja diversas estructuras de datos (registros, arrays)
Dispone de:
Procedimientos y funciones (igual que en C por ejemplo).
Paquetes (Grupos de identificadores, variables y funciones y/o procedimientos
agrupados en una misma construccin, cuya finalidad es el encapsulamiento,
la abstraccin y el control de acceso).
Disparadores (Eventos que se ejecutan cuando ocurre una operacin de
manipulacin de datos sobre una tabla)
La versin objeto de estudio ser la 2.3.
NOTA
Tambin se pueden incorporar rdenes DDL mediante SQL Dinmico.
NOTA
PL/SQL I
VERSIN 1 JPV-99 7 / 67
2. EL BLOQUE PL/SQL
Todos los bloques tienen tres secciones diferenciadas:
Seccin declarativa.
Seccin ejecutable, (la nica obligatoria).
Seccin de excepciones.
EESSTTRRUUCCTTUURRAA::
[DECLARE]
Declaracin de variables y constantes
Variable
Constante Se inicializa con un valor que no se puede modificar.
Cursor Area de trabajo que contiene los datos de la fila de la tabla en
uso. El cursor es el resultado de una sentencia SELECT.
ExcepcinVariables para control de errores.
El Bloque PL/SQL es la unidad bsica en todo programa PL/SQL.
Un programa PL/SQL ser un conjunto de bloques PL/SQL, situados de
manera secuencial o anidados
IMPORTANTE
PL/SQL I
VERSIN 1 JPV-99 8 / 67
BEGIN
Sentencias ejecutables y sentencias DML
[EXCEPTION]
Control de excepciones
Es el punto al que se transfiere el control del programa siempre que exista un
problema. Los indicadores de excepcin pueden ser definidos por el usuario o por el
sistema, como es por ejemplo la excepcin ZERO_DIVIDE. Las excepciones se
activan automticamente al ocurrir un error, existiendo la definicin de la excepcin
OTHERS que considera aquellos errores no definidos y que siempre se ubica al final
de todas las excepciones.
END; [Nombre del bloque]
Fin del Bloque.
ZZOONNAA DDEE DDEECCLLAARRAACCIINN:: DDEE VVAARRIIAABBLLEESS YY CCOONNSSTTAANNTTEESS
Las variables son utilizadas para guardar valores devueltos por una consulta o
almacenar clculos intermedios.
Las constantes son campos que se definen y no alteran su valor en el proceso.
Nombre_campo [CONSTANT] Tipo de dato := valor_constante / expresin_pl_sql
Este tipo de bloque se le suele llamar annimo, y es el ms utilizado en Scripts.
NOTA
PL/SQL I
VERSIN 1 JPV-99 9 / 67
Otra manera de declarar las variables: identificador%TYPE.
Donde el identificador es un objeto accesible por el usuario. Normalmente una
columna de una tabla:
Se puede tambin declarar una fila variable cuyos campos tienen el mismo nombre y
tipo que las columnas de una tabla o fila recuperada de un cursor:
Es obligatorio slo en bloques PL/SQL annimos.
Var1 number(59);
Var2 Var1%TYPE;
Var3 tabla.identificador%TYPE;
registro tabla%ROWTYPE
PL/SQL I
VERSIN 1 JPV-99 10 / 67
TIPOS DE DATOS.
Number (n [, d]) numrico n
PL/SQL I
VERSIN 1 JPV-99 11 / 67
ZZOONNAA DDEE PPRROOCCEESSOO
Empieza con BEGIN.
En esta zona es donde se escriben todas las sentencias ejecutables: sentencias DML,
asignaciones, manejo de cursores, bucles, etc.
Es importante recordar que todas las SELECT ejecutadas dentro de un bloque PL/SQL
llevan asociado un INTO.
Una SELECT que no devuelva datos o que devuelva ms de uno provoca un ERROR,
saltando la ejecucin directamente al EXCEPTION.
ASIGNACIN DE VALORES
Las dos formas que existen para asignar valores a variables de memoria, son:
- Con el operador de asignacin :=, como cuando calculamos el promedio de las
ventas asignndole valor a la variable xprom con la siguiente sentencia:
xprom:=xtotal/xcant;
- Con la sentencia SELECT que contiene la orden INTO, como se muestra, es la
asignacin de valores a las variables xtotal y xcant con el siguiente cdigo:
SELECT SUM(valor),
COUNT(valor)
INTO xtotal,xcant
FROM ventas
WHERE fecha=sysdate;
FIN DE BLOQUE PL/SQL
Todo bloque PL/SQL termina con END.
PL/SQL I
VERSIN 1 JPV-99 12 / 67
COMENTARIOS
Hay dos tipos de comentarios:
Con el signo -- se indica comentario de una sola lnea.
Mediante /* al principio del comentario y */ al final de ste.
ZZOONNAA DDEE EEXXCCEEPPCCIIOONNEESS
Las excepciones saltan cuando se ha producido un error en la ejecucin.
Es seccin no obligatoria. Esta seccin termina con un END.
Es la parte del bloque PL/SQL donde se realiza el control de errores.
Manejo directo de excepciones ya tratadas con el uso de un WHEN:
Excepciones que pueden incluirse directamente despus del WHEN:
Excepcin Nmero de error
CURSOR_ALREADY_OPEN ORA06511 6511
DUP_VAL_ON_INDEX ORA00001 1
INVALID_CURSOR ORA01001 1001
INVALID_NUMBER ORA01722 1722
LOGIN_DENIED ORA01017 1017
NO_DATAFOUND ORA01403 +100
NOT_LOGGED_ON ORA01012 1012
PROGRAM_ERROR ORA06501 6501
PL/SQL I
VERSIN 1 JPV-99 13 / 67
ROWTYPE_MISMATCH ORA06504 6504
STORAGE_ERROR ORA06500 6500
TIMEOUT_ON_RESOURCE ORA00051 51
TOO_MANY_ROWS ORA01422 1422
VALUE_ERROR ORA06502 6502
ZERO_DIVIDE ORA01476 1476
EJERCICIO N 1
Crear un bloque PL/SQL con las siguientes caractersticas:
Definir una constante de tipo numrico, de nombre x, a la que le vamos aasignar el valor de 12.
Definir una variable, y, del mismo tipo que el campo hiredate, de la tablaEMP, de la base de datos DEMO.
Definir una variable de tipo numrico que se llame z.
Asignar a la variable y la fecha actual. Asignar a la variable z el resultadode multiplicar x por 10.
Mostrar por pantalla el contenido de las variables y e z.
EJERCICIO
PL/SQL I
VERSIN 1 JPV-99 14 / 67
EJERCICIO N 2
Se trata de hacer una consulta a la tabla EMP, concretamente del campoename de tal forma que el usuario introduzca un nombre por teclado y el bloquePL/SQL sea capaz de recuperar el campo job de dicho empleado a travs dedicha consulta.
Pedir que se introduzca por teclado un nombre, el cual loalmacenaremos en la variable nombre.
Una vez introducido el nombre, lanzar un bloque PL/SQL (previamentecreado) de tal forma que sea capaz de seleccionar la fila de la tabla EMPcuyo ename sea igual al introducido por teclado y mostrar el campo jobcorrespondiente a ese empleado por pantalla.
EJERCICIO
PL/SQL I
VERSIN 1 JPV-99 15 / 67
3. FUNCIONES SQL PREDEFINIDAS
FFUUNNCCIIOONNEESS DDEE CCAARRCCTTEERR QQUUEE DDEEVVUUEELLVVEENN VVAALLOORREESS DDEE
CCAARRCCTTEERR
CHR Chr(x)
Devuelve el carcter dado su nmero ASCII .
CONCAT Concat (cadena1, cadena2)
Devuelve las dos cadenas encadenadas (Es idntico a usar ||).
INITCAP Initcap (cadena)
Devuelve la misma cadena, con el primer carcter de cada palabra en
mayscula y el resto en minscula.
LOWER Lower (cadena)
Devuelve la misma cadena con todos los caracteres en minscula.
LPAD Lpad (cadena1,x [,cadena2])
Devuelve la cadena1 rellena hacia la izquierda con los caracteres de la
cadena2 hasta completar la longitud x
Existen diversas funciones predefinidas a las que se puede llamar desde
una orden SQL.
IMPORTANTE
PL/SQL I
VERSIN 1 JPV-99 16 / 67
LTRIM Ltrim(cadena1, cadena2)
Devuelve la cadena1, quitando los caracteres de la izquierda contenidos
en cadena2.
REPLACE Replace (cadena, cad_busc [,cad_subst])
Devuelve cadena, reemplazando todas las apariciones de la cadena
cad_busc con la cadena cad_subst. Si no se especifica cad_subst, se
elimina todas las apariciones de cad_busc.
RPAD Rpad (cadena1, x [,cadena2])
Devuelve la cadena1 rellena por la derecha con los caracteres de la
cadena2 hasta completar la longitud x
RTRIM Ltrim(cadena1, cadena2)
Devuelve la cadena1, quitando los caracteres de la derecha contenidos
en cadena2.
SUBSTR Substr (cadena, a [,b])
Devuelve una porcin, de b caracteres de longitud, de la cadena
proporcionada como argumento, empezando a partir de la posicin a. S
a es cero, se trata como si fuera 1. Si a es positivo, se devuelven los
caracteres contando a partir de la izquierda. Si a fuera negativo, se
contara desde el final de la cadena.
UPPER Upper (cadena)
Devuelve la cadena proporcionada con todas las letras en maysculas.
PL/SQL I
VERSIN 1 JPV-99 17 / 67
FFUUNNCCIIOONNEESS DDEE CCAARRCCTTEERR QQUUEE DDEEVVUUEELLVVEENN VVAALLOORREESS
NNUUMMRRIICCOOSS
ASCII ASCII (cadena)
Devuelve la representacin decimal del primer byte de la cadena.
INSTR INSTR (cadena1, cadena2 [,a[,b]])
Devuelve la posicin de la cadena1 donde est contenida la cadena2.
(La cadena se explora desde la izquierda, empezando a partir de la
posicin a. S a es negativo, entonces la cadena1 se explora desde la
derecha. El valor devuelto es el de la aparicin nmero b de la cadena
de la bsqueda).
SQL> SELECT LPAD (Short String, 20, XY) Cadena FROM dual;
> XYXYXYXYShort String
SQL> SELECT LTRIM (xxxFin de la cadena, x) Cadena FROM dual;
> Fin de la cadena
SQL> SELECT REPLACE (This and That, Th, B) Cadena FROM dual;
> Bit and Bat
SQL> SELECT SUBSTR (abc123def, 5, 4) Cadena FROM dual;
> 23de
PL/SQL I
VERSIN 1 JPV-99 18 / 67
LENGTH Length (cadena)
Devuelve la longitud de la cadena.
FFUUNNCCIIOONNEESS NNUUMMRRIICCAASS
ABS ABS (x)
Devuelve el valor absoluto de x
ACOS ACOS (x)
Devuelve el arco coseno de x
ASIN ASIN (x)
Devuelve el arco seno de x
ATAN ATAN (x)
Devuelve el arco tangente de x
CEIL CEIL (x)
Devuelve el menor entero que sea mayor o igual que x
COS COS (x)
Devuelve el coseno de x (en radianes)
SQL> SELECT INSTR(Scotts spot, ot, 1, 2) Cadena FROM dual;
> 11
PL/SQL I
VERSIN 1 JPV-99 19 / 67
COSH COSH (x)
Devuelve el coseno hiperblico de x
EXP EXP (x)
Devuelve e elevado a la potencia x
FLOOR FLOOR (x)
Devuelve el mayor entero que sea menor o igual que x
LN LN (x)
Devuelve el logaritmo natural de x
LOG LOG (x,y)
Devuelve el logaritmo de y en base x
MOD MOD (x)
Devuelve el resto resultante de dividir z por y
POWER POWER (x,y)
Devuelve el nmero x elevado a la potencia de y
ROUND ROUND (x [,y])
Devuelve x redondeado a y posiciones a la derecha del punto decimal.
SIN SIN (x)
Devuelve el seno de x (en radianes)
SINH SINH (x)
Devuelve el seno hiperblico de x
SQRT SQRT (x)
Devuelve la raiz cuadrada de X
PL/SQL I
VERSIN 1 JPV-99 20 / 67
TAN TAN (x)
Devuelve la tangente de x (en radianes)
TANH TANH (x)
Devuelve la tangente hiperblica de x (en radianes)
TRUNC TRUNC (x)
Devuelve el valor x truncado a y posiciones decimales
FFUUNNCCIIOONNEESS DDEE FFEECCHHAA
ADD_MONTHS ADD_MONTHS (d,x)
Devuelve la fecha d ms x meses
LAST_DAY LAST_DAY (d)
Devuelve la fecha del ltimo da del mes al que d pertenece
MONTHS_BETWEEN MONTHS_BETWEEN (fecha1, fecha2)
Devuelve el nmero de meses existentes entre fecha1 y fecha2
SQL> SELECT TRUNC(15.79,1) Truncate FROM DUAL ;
> 15.7
SQL> SELECT MIN(hiredate) Minimum Date FROM emp ;
> 17-DEC-80
PL/SQL I
VERSIN 1 JPV-99 21 / 67
NEXT_DAY NEXT_DAY(d, cadena)
Devuelve la fecha del da nombrado en cadena que es posterior a la
fecha d
ROUND ROUND (d [, formato])
Redondea la fecha d a la unidad especificada.
SYSDATE SYSDATE
Devuelve la fecha y hora actuales, de tipo DATE
TRUNC TRUNC (d [, formato])
Devuelve la fecha d, truncada a la unidad especificada.
SQL> SELECT TO_CHAR(ADD_MONTHS(hiredate,1),
'DD-MON-YYYY') "Next month"
FROM emp
WHERE ename = 'SMITH' ;
> 17-JAN-1981
SQL> SELECT TO_CHAR(
ADD_MONTHS(
LAST_DAY(hiredate),5),
'DD-MON-YYYY') "Five months"
FROM emp
WHERE ename = 'MARTIN' ;
> 28-FEB-1982
PL/SQL I
VERSIN 1 JPV-99 22 / 67
FFUUNNCCIIOONNEESS DDEE CCOONNVVEERRSSIINN
CONVERSIONES IMPLCITAS
PL/SQL Convierte automticamente entre los siguientes tipos de datos:
CONVERSIONES EXPLCITAS
Estas son las conversiones entre tipos que pueden hacerse:
TO_CHAR TO_CHAR (d [,formato [, paramls]])
Convierte la fecha d a una cadena de caracteres
TO_DATE TO_DATE (d [,formato [, paramls]])
Convierte la cadena de caracteres a una fecha
PL/SQL I
VERSIN 1 JPV-99 23 / 67
TO_NUMBER TO_NUMBER (d [,formato [, paramls]])
Convierte la cadena a un valor numrico.
SQL> SELECT TO_DATE(
'January 15, 1989, 11:00 A.M.',
'Month dd, YYYY, HH:MI A.M.',
'NLS_DATE_LANGUAGE = American')
FROM DUAL;
> 15/01/1989,11:00:00
SQL> SELECT TO_CHAR(HIREDATE, 'Month DD, YYYY')
"New date format"
FROM emp
WHERE ename = 'SMITH' ;
> December 17, 1980
SQL> SELECT TO_NUMBER('-AusDollars10000','L9G99999D99',
' NLS_NUMERIC_CHARACTERS = '',.''
NLS_CURRENCY = ''AusDollars'' ') "Amount"
FROM DUAL;
> -10000
PL/SQL I
VERSIN 1 JPV-99 24 / 67
FORMATOS NUMRICOS
Element Example Description
9 9999 significant digit
0 0999 leading zero instead of a blank
$ $999 leading dollar sign
B B999 leading blank instead of a zero
MI 999MI trailing minus sign
S S999 leading plus or minus sign
PR 999PR angle brackets for negative values
D 99D99 decimal character
G 9G99 group separator
C C999 ISO currency symbol
L L999 local currency symbol
, 9,999 comma
. 99.99 period
V 999V99 10n multiplier; n is the number of 9's after the V
EEEE 9.99EEEE scientific notation (you must have 4 E's)
RN, rn RN Upper or lower case roman numeral
PL/SQL I
VERSIN 1 JPV-99 25 / 67
FORMATOS DE FECHA:
CC, SCC Century (S prefixes BC dates with a minus sign)
YYYY, SYYYY Year (S prefixes BC dates with a minus sign)
IYYY Year based on ISO standard
YYY, YY, Y Last three, two or one digits of the year
IYY, IY, I Last three, two or one digits of the ISO year
Y,YYY (Four Y's with comma) put a comma in the year (1,995)
YEAR, SYEAR Year spelled out (S prefixes BC dates with a minus sign)
RR Last two digits of year in another century (allows for year 2000)
BC, AD BC or AD indicator
B.C., A.D. BC or AD indicators with periods
Q Numeric quarter of the year (1-4 with Jan-Mar=1)
MM 2 number month (Jan = 01)
RM Roman numeral month
MONTH Name of month spelled out (upper case - month is upper case)
MON abbreviated name of month (upper case - month is upper case)
WW Week of the year (1-53)
IW Week of the year (1-52, 1-53) based on ISO standard
W Week of month (1-5)
DDD day of year (1-366) (Don't forget leap years)
DD day of month (1-31)
PL/SQL I
VERSIN 1 JPV-99 26 / 67
D day of week (1-7)
DAY Name of day (upper case, day is upper case)
DY Abbreviated name of day
J Julian day (Number of days since January 1, 4712 BC)
AM,PM Meridian indicator
A.M., P.M. Meridian indicator with periods.
HH, HH12 Hour of day (0-12)
HH24 Use 24 hour clock for hours (1-24)
MI Minute (0-59)
SS Second (0-60)
SSSSS (five S's) seconds past midnight. (0-86399)
None Date must be in the format 'DD-MON-YY';
FFUUNNCCIIOONNEESS DDEE GGRRUUPPOO
AVG AVG ([Distinct | All] col)
Devuelve el promedio de los valores de la columna
COUNT COUNT (* | [Distinct |all] col)
Devuelve el nmero de filas en la consulta
MAX MAX ([Distinct | All] col)
Devuelve el valor mximo de la consulta de seleccin.
MIN MIN ([Distinct | All] col)
Devuelve el valor mnimo de la consulta de seleccin.
PL/SQL I
VERSIN 1 JPV-99 27 / 67
STDDEV STDDEV ([Distinct | All] col)
Devuelve la desviacin estndar del elemento de lista de seleccin.
SUM SUM ([Distinct | All] col)
Devuelve la suma de los valores para el elemento de lista de seleccin.
VARIANCE VARIANCE ([Distinct | All] col)
Devuelve la varianza estadstica del elemento de lista de seleccin.
OOTTRRAASS FFUUNNCCIIOONNEESS
DECODE DECODE (expr_base, compara1, valor1,
compara2, valor2
predeterminado)
La funcin DECODE es similar a una serie de rdenes IF-THEN-ELSE
anidadas. La expresin expr_base se compara sucesivamente con
compara1, compara2, etc. Si expr_base coincide con el elemento de
comparacin nmero i, se devuelve el valor i. Si expr_base no coincide
con ninguno de los valores de comparacin, se devuelve el valor
predeterminado.
GREATEST GREATEST (expr1 [expr2] )
Devuelve la expresin con mayor valor de todos sus argumentos. Cada
expresin es convertida de forma implcita al tipo de expr1 antes de
realizar las comparaciones. Si expr1 es de tipo carcter, se realizan
comparaciones de carcter sin relleno de blancos, y el resultado es de
tipo VARCHAR2.
PL/SQL I
VERSIN 1 JPV-99 28 / 67
LEAST LEAST (expr1 [expr2] )
Devuelve la expresin con menor valor de todos sus argumentos. Cada
expresin es convertida de forma implcita al tipo de expr1 antes de
realizar las comparaciones. Si expr1 es de tipo carcter, se realizan
comparaciones de carcter sin relleno de blancos, y el resultado es de
tipo VARCHAR2.
NVL NVL (expr1 ,expr2)
Si el valor de expr1 es NULL, la funcin devuelve el valor de expr2; si
no, devuelve el valor de expr1. El valor devuelto es del mismo tipo que
expr1, salvo si expr1 es una cadena de caracteres, en cuyo caso el
valor de retorno es del tipo VARCHAR2.
USER USER
Devuelve un valor VARCHAR2 que contiene el nombre del usuario
actual de Oracle.
USERENV USERENV (opcin)
Devuelve un valor VARCHAR2 que contiene informacin acerca de la
sesin actual, segn la opcin seleccionada.
OPCIONES
LANGUAGE Devuelve el idioma y pas utilizados
SESSIONID Devuelve el identificador del elemento de registro
de la sesin
TERMINAL Devuelve un identificador, dependiente del
sistema operativo, para el terminal de la sesin actual.
PL/SQL I
VERSIN 1 JPV-99 29 / 67
SQL> SELECT ename, NVL(TO_CHAR(COMM),'NOT APPLICABLE')
"COMMISSION"
FROM emp
WHERE deptno = 30;
>ENAME COMMISSION
---------- -----------------
ALLEN 300
WARD 500
MARTIN 1400
BLAKE NOT APPLICABLE
TURNER 0
JAMES NOT APPLICABLE
SQL> SELECT TEXT
FROM USER_SOURCE
WHERE NAME = UPPER('&1')
ORDER BY NAME, DECODE(TYPE,'PACKAGE','S','PACKAGE BODY','B',
'PROCEDURE','R','FUNCTION','F'),TYPE,LINE;
SQL> SELECT USERENV('sessionid'), USERENV ('terminal'), USER FROM
dual;
> 6234 JPVF SCOTT
PL/SQL I
VERSIN 1 JPV-99 30 / 67
EJERCICIO N 3
-Crear una tabla empleado como copia de la tabla emp. El nuevo nombre ser
emp + n de usuario.
-Modificar los registros de la tabla creada de modo que en lugar del nombre del
empleado aparezca el nombre del empleado terminado en @ para aquellos
empleados llamados JONES cuyo curso es el el 2
EJERCICIO N 4
-Hallar el da de la semana actual en castellano en letra mediante un DECODE
y sin utilizar la mscara d.
EJERCICIO N 5
- Obtener las nuevas comisiones de los empleados teniendo en cuenta que se
subirn un 5% el prximo ao y que aquellos que no tengan les correspondern
como tales la cuarta parte de su salario.
PRCTICA
PL/SQL I
VERSIN 1 JPV-99 31 / 67
4. SENTENCIAS DE CONTROL
SSEENNTTEENNCCIIAA IIFF
IF Condicin THEN sentencias_ejecutables
[ELSIF condicin THEN sentencias_ejecutables; ]
ELSE sentencias_ejecutables; ]
END IF;
SQL> DECLARE
v_NumberSeats rooms.number_seats%TYPE;
v_Comment VARCHAR2(35);
BEGIN
/* Recibe el nmero de asientos de la sala identificada por ID 99999.
Almacena resultado en v_NumberSeats. */
SELECT number_seats
INTO v_NumberSeats
FROM rooms
WHERE room_id = 99999;
IF v_NumberSeats < 50 THEN
v_Comment := 'Fairly small';
ELSIF v_NumberSeats < 100 THEN
v_Comment := 'A little bigger';
ELSE
v_Comment := 'Lots of room';
PL/SQL I
VERSIN 1 JPV-99 32 / 67
BBUUCCLLEE IINNFFIINNIITTOO::
LOOP
sentencias_ejecutables;
[EXIT when ....;]
END LOOP;
END IF;
END;
/
SQL> DECLARE
ranking_level NUMBER(3) := 1;
BEGIN
IF max_rank_in >= 1
THEN
LOOP
set_rank (ranking_level);
ranking_level := ranking_level + 1;
EXIT WHEN ranking_level > max_rank_in;
END LOOP;
END IF;
END;
/
PL/SQL I
VERSIN 1 JPV-99 33 / 67
BBUUCCLLEESS CCOONNDDIICCIIOONNAALLEESS::
WHILE condicin
LOOP
sentencias_ejecutables;
[EXIT when .... ;]
END LOOP;
SQL> DECLARE
v_Counter BINARY_INTEGER := 1;
BEGIN
-- Permanece dentro del bucle hasta
-- comprobar que se han hecho 50 iteraciones
WHILE v_Counter
PL/SQL I
VERSIN 1 JPV-99 34 / 67
BBUUCCLLEESS NNUUMMRRIICCOOSS::
FOR ndice IN [REVERSE] nmero_inicio..nmero_fin
LOOP
sentencias_ejecutables;
[EXIT when ....;]
END LOOP;
SQL> DECLARE
v_Counter NUMBER := 7;
BEGIN
Inserta el valor 7 en temp_table.
INSERT INTO temp_table (num_col)
VALUES (v_Counter);
Este bucle declara de nuevo v_Counter como BINARY_INTEGER, lo que
anula la declaracin NUMBER de v_Counter.
FOR v_Counter IN 20..30 LOOP
-- Dentro del bucle, el rango de v_Counter es de 20 a 30.
INSERT INTO temp_table (num_col)
VALUES (v_Counter);
END LOOP;
PL/SQL I
VERSIN 1 JPV-99 35 / 67
-- Inserta otro 7 en temp_table.
INSERT INTO temp_table (num_col)
VALUES (v_Counter);
END;
/
EJERCICIO 7
EJERCICIO SOBRE BUCLES CONDICIONALES
Crear una tabla DIAS con un campo de tipo numrico.
Introducir una fila por cada da del mes actual de tal forma que el resultado
final sea algo parecido a esto:
DAS
1
2
3
4
5
...
29
30
Realizar el ejercicio utilizando for...loop , loop...exit y while.
EJERCICIO
PL/SQL I
VERSIN 1 JPV-99 36 / 67
5. SENTENCIAS DE DML
Atributos de estos cursores:
SQL%NOTFOUND Devuelve TRUE si el INSERT, UPDATE o DELETE
no procesa ninguna fila.
SQL%FOUND Devuelve TRUE si un INSERT, UPDATE o DELETE ha
procesado alguna fila
SQL%ROWCOUNT Devuelve el nmero de fila leda procesadas por un
INSERT, UPDATE o DELETE.
Para el manejo de errores de una SELECT utilizaremos las excepciones
NO_DATA_FOUND, TOO_MANY_ROWS, etc.
PL/SQL puede incluir sentencias de manejo de datos.
Oracle abre un cursor implcito por cada sentencia SQL que tenga que
procesar.
Nos referiremos a l como SQL%
IMPORTANTE
PL/SQL I
VERSIN 1 JPV-99 37 / 67
SQL> update emp
set salary = salary + 100
where name = SMITH;
if SQL%NOTFOUND then
dbms_output.put_line(Smith no trabaja ya en la empresa);
end if;
EJERCICIO 8
EJERCICIO SOBRE SENTENCIAS DML
Introducir desde teclado el nmero de un departamento y mostrar por
pantalla el nombre de dicho departamento y domicilio.
Utilizar la tabla DEPT y un registro para recuperar los datos de dicha tabla.
Probar que ocurre si se introduce un nmero de departamento que no figura
en la tabla DEPT.
EJERCICIO
PL/SQL I
VERSIN 1 JPV-99 38 / 67
EJERCICIO 9
Crear un bloque PL/SQL que modifique la tabla EMP de tal forma aquellos
empleados cuyo nmero de empleado sea 1 pasen a tener como job
CLERK.
Si no existiera ningn empleado con nmero 1, insertar dicho empleado
con las siguientes caractersticas:
ENAME: PEDRO PEREZ
JOB: CLERK
MGR: 7934
DPTNO: 20
Capturar el error utilizando el cursor implcito SQL%.
EJERCICIO
PL/SQL I
VERSIN 1 JPV-99 39 / 67
6. CURSORES
El conjunto de filas resultantes de una consulta con la sentencia SELECT, puede estar
compuesto por ninguna, una o varias filas, dependiendo de la condicin que define la
consulta.
Para poder procesar individualmente cada fila de la consulta debemos definir un
cursor (que es un rea de trabajo de memoria) que contiene los datos de las filas de la
tabla consultada por la sentencia SELECT.
Cursor parametrizado: cursor que utiliza parmetros en la SELECT.
CURSOR NOMBRE_CURSOR (nombre_parametro tipo_parametro)
IS SENTENCIA SELECT utilizando los parmetros;
Variable de tipo %ROWTYPE.
Un cursor es un rea de trabajo que utiliza ORACLE para consultas que
devuelven ms de una fila, permitiendo la lectura y manipulacin de cada
una de ellas.
Declaracin:
CURSOR NOMBRE_CURSOR IS SENTENCIA SELECT;
Para recuperar los datos de un cursor primero hay que abrirlo (OPEN),
luego leerlo (FETCH), y por ltimo cerrarlo (CLOSE).
IMPORTANTE
PL/SQL I
VERSIN 1 JPV-99 40 / 67
MMAANNEEJJOO DDEE CCUURRSSOORREESS
Se declaran en la zona DECLARE.
Para recuperar todas las filas del cursor utilizaremos un bucle.
Atributos utilizados en el manejo:
Nombre_cursor%NOTFOUND Devuelve TRUE si falla y no tiene ms
filas que devolver
Nombre_cursor%FOUND Contrario de %notfound
Nombre_cursor%ROWCOUNT Devuelve el nmero de fila leda.
Nombre_cursor%ISOPEN Devuelve TRUE si el cursor est abierto.
Para abrir el cursor utilizamos la sentencia OPEN.
Si el cursor est parametrizado: OPEN nombre_cursor (parmetro).
Para cursores sin parmetros recuperamos una fila utilizando:
FETCH NOMBRE_CURSOR INTO VARIBLE1, VARIABLE2, VARIABLE3...
Cerramos un cursor utilizando la sentencia CLOSE.
BBUUCCLLEESS SSOOBBRREE CCUURRSSOORREESS
Realiza automticamente las siguientes acciones:
Abre el cursor.
Se realiza la lectura y se ejecutan las sentencias del bucle hasta que no haya
ms filas.
PL/SQL I
VERSIN 1 JPV-99 41 / 67
Cierra el cursor.
FOR Nombre_registro IN Nombre_cursor
LOOP
sentencias_ejecutables;
[EXIT when ....;]
END LOOP;
EEJJEEMMPPLLOO DDEE CCUURRSSOORREESS
A continuacin veremos un ejemplo de cursor con las siguientes caractersticas:
Objetivo: Consultar las ventas de una fecha dada ordenadas de mayor a
menor.
Nombre:CVENTAS.
Parmetros: cfecha, variable que contiene la fecha a consultar.
PL/SQL I
VERSIN 1 JPV-99 42 / 67
PROCEDURE VENTAS5 (xfecha DATE) is
BEGIN
DECLARE CURSOR cventas (cfecha DATE)
IS SELECT articulo,valor
FROM ventas
WHERE fecha=cfecha
ORDER BY valor DESC;
xarticulo ventas.articulo%TYPE;
xvalor ventas.valor%TYPE;
BEGIN
OPEN cventas(xfecha);
FOR i IN 1..5 LOOP
FETCH cventas INTO xarticulo,xvalor;
EXIT WHEN cventas%NOTFOUND;
INSERT INTO ventamayor VALUES
(xfecha,xarticulo,xvalor);
COMMIT;
END LOOP;
CLOSE cventas;
END;
END;
PL/SQL I
VERSIN 1 JPV-99 43 / 67
Para llamar al procedimiento ventas5 en una fecha dada, se puede escribir, por
ejemplo:
ventas5(to_date('15/11/95','DD/MM/YY')
ventas5(sysdate).
A continuacin detallaremos las sentencias usadas en este procedimiento:
DECLARE cursor
Define el cursor, su consulta y la lista de parmetros que se pasan a la orden
WHERE, es solo la declaracin del cursor y no la realizacin de la consulta.
xarticulo ventas.articulo%TYPE;
Define la variable xarticulo igual a la columna articulo de la tabla ventas, que
con el uso del atributo de variable %TYPE permite declarar una variable del
mismo tipo que una columna de la tabla. No es necesario conocer cmo est
definida esa columna en la tabla y, en caso que la definicin de la columna sea
modificada, automticamente se cambia la variable xarticulo.
OPEN cventas(xfecha);
Realiza la consulta asociada al cursor, pasando el valor del parmetro y
guardando sus resultados en un rea de la memoria, desde la cual,
posteriormente, se pueden leer estas filas.
FOR i IN 1..5 LOOP
Ciclo numrico de repeticin para poder consultar las 5 primeras ventas
devueltas por el cursor.
FETCH cventas INTO xarticulo,xvalor;
PL/SQL I
VERSIN 1 JPV-99 44 / 67
Lee la siguiente fila de datos del cursor cventas y pasa los datos de la consulta
a las variables xarticulo y xvalor.
EXIT WHEN cventas%NOTFOUND;
Garantiza la salida del ciclo antes de la ltima repeticin, en caso que para una
fecha dada se hayan efectuado menos de 5 ventas, ya que en esta situacin la
consulta del cursor devuelve menos de 5 filas.
%NOTFOUND es un atributo de cursor que es verdadero cuando la ltima
sentencia FETCH no devuelve ninguna fila.
INSERT INTO ventamayor
VALUES(xfecha,xarticulo,xvalor);
Insertar en la tabla ventamayor los valores ledos desde el cursor.
COMMIT;
Actualizacin de la tabla ventamayor.
END LOOP;
Fin del ciclo.
CLOSE cventas;
Cierra el cursor, eliminado sus datos del rea de memoria.
EJERCICIO 10
Insertar en la tabla nueva de empleado los valores de aquellos empleados que
pertenezcan a los departamentos 20 y 10 en este orden y aadirles 1000 al
campo salario.
EJERCICIO
PL/SQL I
VERSIN 1 JPV-99 45 / 67
EJERCICIO 11
EJERCICIO SOBRE CURSORES
Crear una tabla de totales por departamentos con dos campos: uno para los
nmeros de departamento y otro numrico para meter los totales por
departamento.
El proceso consiste en pedir por pantalla el nmero de departamento y
calcular el total de la suma de los salarios mas las comisiones. Utilizar un
cursor.
Insertar el resultado en la tabla recin creada. Si un departamento no tuviera
empleados introducir un 0 en el campo total.
EJERCICIO
EJERCICIO 12
EJERCICIO SOBRE CURSORES Y SENTENCIAS DML
Crear una tabla con los campos job y total_empleados.
Contar cuntos empleados hay de cada tipo de job. Utilizar un cursor para
obtener los distintos tipos de trabajo, y otro cursor parametrizado en el cual
se le pasa el trabajo recuperado con el cursor anterior.
Introducir en la tabla slo aquellos trabajos que tengan ms de 1 empleado.
EJERCICIO
PL/SQL I
VERSIN 1 JPV-99 46 / 67
7. REGISTROS Y TABLAS
RREEGGIISSTTRROOSS PPLL//SSQQLL
Una vez declarado un registro es necesario definir una variable de este tipo.
Podemos utilizar tambin %TYPE y %ROWTYPE.
Se puede asignar un registro a otro del mismo tipo o sus campo individualmente, con
la condicin de que ambos sean del mismo tipo.
Los registros PL/SQL son estructuras de datos complejas que permiten
tratar variables diferentes, pero relacionadas, como si fuera una unidad.
TYPE NOMBRE_REGISTRO IS RECORD
( campo1 tipo1 [:=expr1],
campo2 tipo2 [:=expr2],
.....
campon tipon [:=exprn])
IMPORTANTE
PL/SQL I
VERSIN 1 JPV-99 47 / 67
EJEMPLO:
DECLARE
TYPE t_Rec1Type IS RECORD (
Field1 NUMBER,
Field2 VARCHAR2(5));
TYPE t_Rec2Type IS RECORD (
Field1 NUMBER,
Field2 VARCHAR2(5));
v_Rec1 t_Rec1Type;
v_Rec2 t_Rec2Type;
BEGIN
/* Aunque v_Rec1 y v_Rec2 sean los mismos campos
y tipos, el tipo RECORD en s mismo es diferente
Sera una asignacin ilegal que elevara el error PLS-382. */
v_Rec1 := v_Rec2;
/* Estos campos, son del mismo tipo, por los que la asignacin seralegal. */
v_Rec1.Field1 := v_Rec2.Field1;
v_Rec2.Field2 := v_Rec2.Field2;
END;
/
PL/SQL I
VERSIN 1 JPV-99 48 / 67
TTAABBLLAASS EENN PPLL//SSQQLL
Las tablas en PL/SQL se asemejan a los arrays del lenguaje C.
Sintcticamente se las trata de la misma forma que a las matrices, aunque su
implementacin es distinta.
DEFINICIN DE UNA TABLA
Una tabla PL/SQL es similar a una tabla de base de datos pero como si
tuviera dos columnas una de ellas es el ndice y la otra el valor.
La clave es siempre BINARY_INTEGER y el tipo valor es el tipo que hubiera
especificado en la definicin.
El mximo nmero de filas viene especificado por el nmero mximo de
valores que se pueden representar mediante el tipo BINARY_INTEGER.
IMPORTANTE
PL/SQL I
VERSIN 1 JPV-99 49 / 67
Dispone de control automtico de asignacin de memoria, a diferencia de C, en el que
hay que reservarla antes.
TYPE NOMBRE_TABLA IS TABLE OF TIPO_DE_DATO
INDEX BY BINARY_INTEGER;
ATRIBUTOS DE UNA TABLA
TABLA.COUNT-> Devuelve el nmero de filas de una tabla.
TABLA.DELETE->Borra filas de la tabla.
TABLA.EXISTS-> Devuelve TRUE si existe en la tabla el elemento
especificado.
TABLA. FIRST-> Devuelve el ndice de la primera fila desde la tabla.
TABLA.LAST-> Devuelve el ndice de la ltima fila de la tabla.
TABLA.NEXT-> Devuelve el ndice de la fila de la tabla que sigue a la fila
especificada.
TABLA.PRIOR-> Devuelve el ndice de la fila de la tabla que antecede a la fila
especificada.
EJEMPLO
DECLARE
TYPE t_LastNameTable IS TABLE OF students.last_name%TYPE
INDEX BY BINARY_INTEGER;
v_LastNames t_LastNameTable;
v_Index BINARY_INTEGER;
BEGIN
Inserta filas en la tabla.
PL/SQL I
VERSIN 1 JPV-99 50 / 67
v_LastNames(43) := 'Mason';
v_LastNames(50) := 'Junebug';
v_LastNames(47) := 'Taller';
-- Asigna 43 a v_Index.
v_Index := v_LastNames.FIRST;
-- Asigna 50 a v_Index.
v_Index := v_LastNames.LAST;
END;
/
TABLAS DE REGISTROS
Una tabla puede contener datos de tipo registro.
EJEMPLO
DECLARE
TYPE t_StudentTable IS TABLE OF students%ROWTYPE
INDEX BY BINARY_INTEGER;
/* Cada elemento de v_Students es un registro */
v_Students t_StudentTable;
BEGIN
/* Obtiene el registro record con id = 10,001 and y lo almacena env_Students(10001) */
SELECT *
INTO v_Students(10001)
FROM students
WHERE id = 10001;
v_Students(10001).first_name := 'Larry';
DBMS_OUTPUT.PUT_LINE(v_Students(10001).first_name);
END;
/
PL/SQL I
VERSIN 1 JPV-99 51 / 67
EJERCICIO 13
EJERCICIO SOBRE REGISTROS
Crear un cursor parametrizado que recupere los campos nombre, trabajo,
salario y comision de la tabla EMP del trabajo introducido por teclado.
Recuperar los datos con un registro y mostrar por pantalla cada una de las
filas recuperadas en el cursor de la siguiente manera:
SMITH
------>CLERK 800
JAMES
------>CLERK 950
ADAMS
------>CLERK 1100
PEPE
------>CLERK 1300 750
PEDRO PEREZ
------>CLERK
Pedro Perez
------>CLERK
Utilizar solamente una sentencia dbms_output.put_line.
EJERCICIO
PL/SQL I
VERSIN 1 JPV-99 52 / 67
EJERCICIO 14
EJERCICIO SOBRE TABLAS
Crear un bloque PL/SQL que contenga un array de tipo varchar2(25).
Realizar las siguientes operaciones:
Insertar en la posicin 1 la cadena Uno
Insertar en la posicin 3 la cadena Tres
Insertar en la posicin 2 la cadena Menos dos
Insertar en la posicin 0 la cadena Cero
Insertar en la posicin 100 la cadena Cien
Mostrar un mensaje con el nmero total de filas de la tabla
Elimina la fila de la posicin 100
Mostrar un mensaje con el nmero de filas de la tabla
Borrar las filas desde la posicin 1 a la 3
Mostrar un mensaje con el nmero de filas de la tabla
Borrar el elemento que se encuentre en la primera posicin
Mostrar el contenido la ltima posicin
Mostrar el contenido de la penltima posicin
Mostrar el contenido de la posicin 1
Borrar toda la tabla
EJERCICIO
PL/SQL I
VERSIN 1 JPV-99 53 / 67
EJERCICIO 15
EJERCICIO SOBRE TABLAS DE REGISTROS
Crear una tabla (en el ncleo) VENDEDORES, compuesta por tres
columnas:
Empno - number(4),
sal number(7, 2) ,
comm number(7, 2).
Se trata de hacer un bloque PL/SQL capaz de cargar en un array de
registros todos aquellos empleados de la tabla emp que tengan comisin no
nula. Una vez realizada la carga del array se extraern en orden inverso al
que fueron introducidos y se insertarn en la tabla vendedores.
Utilizar un cursor para recuperar los campos empno, sal y comm
de la tabla EMP.
El registro de constar de los campos empno, sal y comm.
Sera interesante guardar los resultados en un fichero de texto
para comparar lo que devuelve la SELECT con lo que se ha
obtenido con el cursor.
Utilizar un cursor implcito.
EJERCICIO
PL/SQL I
VERSIN 1 JPV-99 54 / 67
8. SENTENCIAS TRANSACCIONALES
Savepoint:
Marcas que pone el usuario durante la transaccin para deshacer los cambios
por partes en vez de deshacer toda la transaccin.
SAVEPOINT ;
Commit:
Realiza todas las transacciones pendientes de la actual transaccin
hacindolas visibles para los dems usuarios.
COMMIT [WORK];
Rollback:
Deshace todos los cambios pendientes de la transaccin actual.
ROLLBACK [WORK] [ TO [SAVEPOINT] punto_salvaguarda; ]
Una transaccin es una serie de rdenes SQL que se completan o fallan
como una unidad. Es decir, todas las rdenes se ejecutan o bien todas
fallan.
Una transaccin termina con la orden COMMIT o ROLLBACK.
IMPORTANTE
PL/SQL I
VERSIN 1 JPV-99 55 / 67
EJEMPLO
DECLARE
v_NumIterations NUMBER;
BEGIN
-- Loop from 1 to 500, inserting these values into temp_table.
-- Commit every 50 rows.
FOR v_LoopCounter IN 1..500 LOOP
INSERT INTO temp_table (num_col) VALUES (v_LoopCounter);
v_NumIterations := v_NumIterations + 1;
IF v_NumIterations = 50 THEN
COMMIT;
v_NumIterations := 0;
END IF;
END LOOP;
END;
/
EJERCICIO 16
a) Crear una tabla temp, compuesta por estas columnas:
Codigo - number(4),
Mensaje varchar2(80)
b) Actualizar los vendedores con una comisin mayor que 350$ con un
incremento del 15% de su salario. Si la operacin afecta a ms de
tres empleados, deshacer la transaccin, en cualquier otro caso
validar la transaccin. Introducir en la tabla TEMP la operacin que
se ha realizado.
PRCTICA
PL/SQL I
VERSIN 1 JPV-99 56 / 67
EJERCICIO 17
EJERCICIO SOBRE UTILIZACIN DE SENTENCIAS TRANSACCIONALES
Crear un bloque PL/SQL que modifique el sal de los empleados que no
tienen comisin a 1000.
Dentro del mismos bloque PL/SQL actualizar los empleados con una
comisin mayor de 350 $ con un incremento del 15% de su salario. Si la
operacin afecta a ms de tres empleados, deshacer la transaccin, en
cualquier otro caso validar dicha transaccin.
Utilizar slo un commit en el bloque PL/SQL.
PRCTICA
PL/SQL I
VERSIN 1 JPV-99 57 / 67
9. CONTROL DE ERRORES
TTIIPPOOSS DDEE EEXXCCEEPPCCIIOONNEESS::
EXCEPCIONES PREDEFINIDAS:
NO_DATA_FOUND,
TOO_MANY_ROWS,
DUP_VAL_ON_INDEX....
El control de errores se realiza en la zona de excepciones del bloque
PL/SQL que es la parte final del bloque PL/SQL annimo o del
procedimiento almacenado.
WHEN NOMBRE_EXCEPCION1 [OR NOMBRE_EXCEPCION2....]
THEN SENTENCIAS;
IMPORTANTE
La zona de excepciones no es obligatoria.
NOTA
PL/SQL I
VERSIN 1 JPV-99 58 / 67
DEFINIDAS POR EL USUARIO:
Mediante:
a) Exception_init, basadas en errores ORACLE
PRAGMA EXCEPTION_INIT (nombre_excepcin, nmero_error);
b) Declarndola como excepcin con el tipo de dato EXCEPTION en el DECLARE.
EEJJEECCUUCCIINN DDEE EEXXCCEEPPCCIIOONNEESS
La ejecucin de excepciones se produce:
Automticamente: Cuando ORACLE detecta un error, para el proceso y
pasa automticamente a la zona de EXCEPTION (si existe).
Manualmente: Cuando el proceso llega a un punto en que interesa que
halla un error. La sentencia utilizada es el RAISE.
RAISE ;
Nombre_excepcin hay que definirlo antes con EXCEPTION.
El nmero de error es un sqlcode que no se halla definido para otra excepcin
de Oracle , (p. Ej. NO DATA FOUND).
NOTA
PL/SQL I
VERSIN 1 JPV-99 59 / 67
FFUUNNCCIIOONNEESS
La funcin SQLCODE nos devuelve el nmero de error producido. Slo tiene valor
cuando ocurre un error ORACLE
Slo se habilita en la zona de excepciones.
La funcin SQLERRM nos devuelve el mensaje del error del valor actual del
SQLCODE.
EEJJEEMMPPLLOOSS YY TTRRAATTAAMMIIEENNTTOO
PARA VER LOS ERRORES INTERNOS DE ORACLE E INSERTARLOS EN
UNA TABLA:
PREVIO: Creacin de tabla donde almacenarlos:
Se puede emplear la funcin predefinida RAISE_APPLICATION_ERROR para
la creacin de mensajes de error por parte del usuario.
Su sintaxis es:
RAISE_APPLICATION_ERROR (cdigo, Mensaje).
Donde cdigo es un nmero entre 20000 y 20999.
NOTA
PL/SQL I
VERSIN 1 JPV-99 60 / 67
REM
REM Creacin de tabla de errores
REM
create table errors (err_code number(6), err_msg varchar2(100));
DECLARE
err_msg VARCHAR2(100);
BEGIN
FOR err_num IN 1 .. 20000
LOOP
err_msg := SQLERRM (-err_num);
IF SQLERRM NOT LIKE '%MESSAGE %'
THEN
BEGIN
INSERT INTO errors
VALUES (-err_num, err_msg);
EXCEPTION
WHEN DUP_VAL_ON_INDEX
THEN
NULL;
END;
END IF;
END LOOP;
END;
/
PL/SQL I
VERSIN 1 JPV-99 61 / 67
USO HABITUAL DE LAS EXCEPCIONES:
DECLARE
pe_ratio NUMBER(3,1);
BEGIN
SELECT price / earnings
INTO pe_ratio
FROM stocks
WHERE symbol = 'XYZ'; -- puede causar error de divisinbyzero
INSERT INTO stats (symbol, ratio)
VALUES ('XYZ', pe_ratio);
COMMIT;
EXCEPTION -- COMIENZA EL BLOQUE DE EXCEPCIN
WHEN ZERO_DIVIDE THEN -- Maneja el error de divisin por cero
INSERT INTO stats (symbol, ratio)
VALUES ('XYZ', NULL);
COMMIT;
...
WHEN OTHERS THEN -- maneja todos los dems errores
ROLLBACK;
END; -- fin de las excepciones y del bloque.
/
PL/SQL I
VERSIN 1 JPV-99 62 / 67
CREACIN DE UN PRAGMA PARA EL MANEJO DE ERRORES:
DECLARE
insufficient_privileges EXCEPTION;
PRAGMA EXCEPTION_INIT(insufficient_privileges, -1031);
------------------------------------------------------
Oracle devuelve el error number -1031 si, por ejemplo,
intentas MODIFICAR una tabla para la que slo
tienes privilegios de consulta
-------------------------------------------------------
BEGIN
...
EXCEPTION
WHEN insufficient_privileges THEN
Maneja el error
...
END;
/
ELEVACIN DE MENSAJES DE ERROR PROPIOS DE USUARIO.
DECLARE
...
null_salary EXCEPTION;
/* Nmero de Error mapeado devuelto por raise_application_error
de una excepcin definida por el usuario. */
PRAGMA EXCEPTION_INIT(null_salary, 20101);
PL/SQL I
VERSIN 1 JPV-99 63 / 67
BEGIN
...
raise_salary(:emp_number, :amount);
EXCEPTION
WHEN null_salary THEN
INSERT INTO emp_audit
VALUES (:emp_number, ...);
...
END;
/
EJERCICIO 18
EJERCICIO SOBRE MANEJO DE EXCEPCIONES
Crear un bloque PL/SQL con una nica sentencia SELECT sobre la tabla
EMPLEADOS, de tal forma que va a ir recuperando el salario del empleado
del trabajo que se introduzca por teclado.
En el caso de recuperar un solo empleado elevar una excepcin que se va
a llamar SOLO_UN_EMPLEADO mostrando un mensaje por pantalla.
En el caso de recuperar ms utilizaremos la excepcin TOO_MANY_ROWS
y mostraremos un mensaje indicativo en la pantalla.
En el caso de no recuperar ninguno utilizaremos las excepcin
NO_DATA_FOUND y mostraremos el respectivo mensaje.
PRCTICA
PL/SQL I
VERSIN 1 JPV-99 64 / 67
10. RESUMEN
PL/SQL, (Procedural Language / SQL), es un lenguaje de programacin
procedural estructurado en bloques que amplia la funcionalidad del lenguaje
standard SQL a travs de estructuras como:
Variables y tipos, (predefinidos y definidos por el usuario)
Estructuras de control, (bucles y condiciones)
Procedimientos y funciones
Tipos de objetos y mtodos, (a partir de versin 8)
El Bloque PL/SQL es la unidad bsica en todo programa PL/SQL.
Un programa PL/SQL ser un conjunto de bloques PL/SQL, situados de
manera secuencial o anidados
Existen diversas funciones predefinidas a las que se puede llamar desde
una orden SQL.
PL/SQL puede incluir sentencias de manejo de datos.
Oracle abre un cursor implcito por cada sentencia SQL que tenga que
procesar.
Nos referiremos a l como SQL%
Un cursor es un rea de trabajo que utiliza ORACLE para consultas que
devuelven ms de una fila, permitiendo la lectura y manipulacin de cada
una de ellas.
PL/SQL I
VERSIN 1 JPV-99 65 / 67
Declaracin de un cursor:
CURSOR NOMBRE_CURSOR IS SENTENCIA SELECT;
Para recuperar los datos de un cursor primero hay que abrirlo (OPEN),
luego leerlo (FETCH), y por ltimo cerrarlo (CLOSE).
Los registros PL/SQL son estructuras de datos complejas que permiten
tratar variables diferentes, pero relacionadas, como si fuera una unidad.
Una tabla PL/SQL es similar a una tabla de base de datos pero como si
tuviera dos columnas una de ellas es el ndice y la otra el valor.
La clave es siempre BINARY_INTEGER y el tipo valor es el tipo que
hubiera especificado en la definicin.
El mximo nmero de filas viene especificado por el nmero mximo de
valores que se pueden representar mediante el tipo BINARY_INTEGER.
Una transaccin es una serie de rdenes SQL que se completan o fallan
como una unidad. Es decir, todas las rdenes se ejecutan o bien todas
fallan.
Una transaccin termina con la orden COMMIT o ROLLBACK.
El control de errores se realiza en la zona de excepciones del bloque
PL/SQL que es la parte final del bloque PL/SQL annimo o del
procedimiento almacenado.
PL/SQL I
VERSIN 1 JPV-99 66 / 67
11. EVALUACIN
1 En PL/SQL, pueden incorporarse rdenes DDL
a) Siempre
b) Slo a travs de SQL Dinmico
c) Nunca
2 En un bloque PL/SQL, la declaracon de variables se hace en:
a) En la zona declarativa
b) Tanto en la zona declarativa como en la zona de proceso
c) Solamente en el bloque de excepciones
3 Qu valor nos dara la variable resultado en la siguiente consulta?
declare a number:=2;
resultado varchar2(20);
begin
select decode(a,3,'Menor',4,'Siguiente',5,'Mayor','Otro') into resultado
from dual;
dbms_output.put_line(resultado);
end;
/
a) No compilara porque en la declaracin no puede asignarseuna variable a un nmero
b) Mayor
c) Otro
PL/SQL I
VERSIN 1 JPV-99 67 / 67
4 La sentencia ROLLBACK sirve para:
a) Volver al bloque BEGIN / END anterior al que pertenece
b) Reenva de nuevo la transaccin al usuario
c) Deshace todos los cambios pendientes de la transaccin actual
5 Defina bloque PL/SQL annimo:
...............................................................................................................
...............................................................................................................
...............................................................................................................
...............................................................................................................
6 Definicin y usos del tipo PLS_Integer:
...............................................................................................................
...............................................................................................................
...............................................................................................................
...............................................................................................................
7 Definicin, usos y declaracin de un cursor:
...............................................................................................................
...............................................................................................................
...............................................................................................................
...............................................................................................................
PL/SQL II
VERSIN 1 JPV-99 1 / 50
PPLL//SSQQLL IIII
Javier Prez-Vigo (Octubre 1999)
PL/SQL II
VERSIN 1 JPV-99 2 / 50
INTRODUCCIN
En la unidad didctica PL/SQL I se estudiaron los bloques PL/SQL
annimos que se compilaban cada vez que eran ejecutados.
Las estructuras que se vern en esta unidad didctica, (procedimientos,
funciones, paquetes y disparadores), son bloques nominados y pueden
ser almacenados en la base de datos para ser ejecutados tantas veces
como sea necesario.
PL/SQL slo puede contener rdenes DML y no DDL. Sin embargo esta
restriccin se supera a partir de la versin 2.1 con el paquete
DBMS_SQL. Este paquete implementa cdigo PL/SQL y SQL dinmico,
al que se llama desde otros bloques PL/SQL.
En el captulo 4 de esta unidad se ver cmo utilizar el paquete
DBMS_SQL y sus implicaciones.
PL/SQL II
VERSIN 1 JPV-99 3 / 50
CONTENIDO:
1. PROCEDIMIENTOS Y FUNCIONES
PROCEDIMIENTOS
FUNCIONES
SUBPROGRAMAS LOCALES.
CONTROL DE PROCEDIMIENTOS Y FUNCIONES.
2. DESARROLLO Y UTILIZACIN DE PAQUETES
PAQUETES (PACKAGES)
FUNCIONES DENTRO DE PAQUETES.
3. DISPARADORES (TRIGGERS)
CONCEPTO DE DISPARADORES (TRIGGERS)
CREACIN DE DISPARADORES
CONCEPTO DE TABLA MUTANTE
4. PL/SQL DINMICO
CONCEPTO
MTODOS DE IMPLEMENTACIN
5. EJERCICIO DE DESARROLLO
6. RESUMEN
7. EVALUACIN
PL/SQL II
VERSIN 1 JPV-99 4 / 50
OBJETIVOS
El alumno tras el estudio de esta unidad didctica podr:
Conocer y utilizar los procedimientos y funciones almacenados a
travs del lenguaje PL/SQL.
Crear y utilizar los paquetes, packages.
Conocer y utilizar los disparadores.
Entender los fundamentos del PL/SQL dinmico.
EXPECTATIVAS
PL/SQL II
VERSIN 1 JPV-99 5 / 50
1. PROCEDIMIENTOS Y FUNCIONES
CONCEPTO DE PROCEDIMIENTOS Y FUNCIONES
Los bloques PL/SQL forman una estructura de bloques annimos, es decir, se
compilan contra la Base de Datos y una vez ejecutados se pierden.
Se hace necesario tener estructuras de bloques nominados, tal que puedan
almacenarse en la Base de Datos y ser llamados cuando se necesiten.
Un procedimiento es un conjunto de instrucciones PL/SQL que puede ser
llamado usando el nombre que se le haya asignado.
Una funcin es un conjunto de instrucciones en PL/SQL, que pueden ser
llamados usando el nombre con que se le haya creado.
Se diferencian de los procedimientos, en que las funciones retornan un
valor al ambiente desde donde fueron llamadas.
IMPORTANTE
Una vez creados un procedimiento o una funcin pueden llamarse desde
multitud de lados: SQL*, Forms o cualquier otra herramienta ORACLE.
NOTA
PL/SQL II
VERSIN 1 JPV-99 6 / 50
PPRROOCCEEDDIIMMIIEENNTTOOSS
CREACIN DE PROCEDIMIENTOS
Utilizaremos la siguiente sentencia:
CREATE [OR REPLACE] PROCEDURE nombre_procedimiento
[(argumento1 TIPO tipo_dato1,..., argumentoN TIPO tipo_datoN)] IS O AS
Bloque PL/SQL
Su estructura es semejante a:
CREATE OR REPLACE PROCEDURE PROCEDIMIENTO IS
tmpVar NUMBER;
/****************************************************************************** NAME: PROCEDIMIENTO PURPOSE: To calculate the desired information. REVISIONS: Ver Date Author Description --------- ---------- --------------- ------------------------------------ 1.0 10/09/99 1. Created this procedure.******************************************************************************/
BEGIN
tmpVar := 0;
EXCEPTION
WHEN NO_DATA_FOUND THEN
Null;
WHEN OTHERS THEN
Null;
END PROCEDIMIENTO;
/
PL/SQL II
VERSIN 1 JPV-99 7 / 50
Los tipos de los argumentos son: IN, OUT, IN OUT
Indican si el parmetro es de entrada, salida o ambos.
Si no se pone nada se supone que es IN.
IS o AS llevan implcito el DECLARE, as que las variables se declaran
inmediatamente despus de IS o AS.
Un procedimiento termina con END o con END seguido del nombre del
procedimiento.
No puede haber declaracin de argumentos, es decir, en las declaraciones de
tipo NUMBER, VARCHAR2 o DATE no puede figurar ni la escala ni la precisin.
Es aconsejable utilizar los atributos %TYPE y %ROWTYPE para definir
argumentos y variables.
NOTA
El uso de OR REPLACE permite sobreescribir un procedimiento existente.
Si se omite, y el procedimiento ya existe, se producir un error.
Es conveniente utilizar al principio slamente CREATE, ya que de existir el
procedimiento en el ncleo podemos destruirlo.
NOTA
PL/SQL II
VERSIN 1 JPV-99 8 / 50
BORRADO
Para borrar un procedimiento se utiliza:
DROP PROCEDURE Nombre_procedimiento;
EJECUCIN
Los procedimientos (o funciones) que se declaran como locales a un bloque PL/SQL
se situarn al final del DECLARE.
Las formas de llamar a un procedimiento son las siguientes:
Exec nombre_procedimiento(var1, var2)
Exec nombre_procedimiento(var2 => xxx, var1 => yyy)
Un procedimiento se invoca con la sentencia EXEC[UTE] desde SQL*.
Desde un bloque PL/SQL simplemente es necesario nombrarlo para
ejecutarlo.
IMPORTANTE
Como argumentos en un procedimiento puede haber registros o tablas.
NOTA
PL/SQL II
VERSIN 1 JPV-99 9 / 50
EJERCICIO SOBRE PROCEDIMIENTOS
EJERCICIO 1
Crear un tabla, EMPLEADOS, con los campos: nombre, trabajo, salario.
Crear un bloque PL/SQL que extraiga de la tabla EMP aquellos empleados
con comisin nula (utilizando un cursor). Aumentar su salario un 10% e
introducir cada uno de ellos en la tabla EMPLEADOS utilizando un
procedimiento cuyos argumentos van a ser nombre, salario y trabajo.
EJERCICIO 2
Ampliar el procedimiento creado para el ejercicio anterior de tal manera que
si el empleado tiene como trabajo CLERK y su nmero de departamento es
el 20 se insertar en la tabla EMP con una comisin = 1000 y no se insertar
en la tabla EMPLEADOS. En cualquier otro caso introducir el empleado en
la tabla EMPLEADOS.
Modificar el nmero de argumentos pasados al procedimiento aadiendo
uno que sea insertados el cual va a indicar el nmero de elementos que se
han insertado en la tabla empleados. Mostrar dicho nmero desde el bloque
PL/SQL con un mensaje.
PRCTICA
PL/SQL II
VERSIN 1 JPV-99 10 / 50
FFUUNNCCIIOONNEESS
CREACIN DE FUNCIONES
Utilizaremos la siguiente sentencia:
CREATE [OR REPLACE] FUNCTION nombre_funcin
[(argumento1 TIPO tipo_dato1,...., argumentoN TIPO tipo_datoN)]
RETURN tipo_dato IS O AS
Bloque PL/SQL
Su estructura es semejante a:
CREATE OR REPLACE FUNCTION FUNCION RETURN NUMBER IS
tmpVar NUMBER;
/****************************************************************************** NAME: FUNCION PURPOSE: To calculate the desired information. REVISIONS: Ver Date Author Description --------- ---------- --------------- ------------------------------------ 1.0 10/09/99 1. Created this function.******************************************************************************/
BEGIN
tmpVar := 0;
EXCEPTION
WHEN NO_DATA_FOUND THEN
Null;
WHEN OTHERS THEN
Null;
RETURN tmpVar;
END FUNCION;
/
PL/SQL II
VERSIN 1 JPV-99 11 / 50
Como TIPO: IN, OUT, IN OUT
Return de una funcin no lleva ni escala ni precisin.
Return puede llevar expresiones.
El tipo de dato no puede incluir escala o precisin.
Una funcin puede tener ms de un return.
Si declaramos una sin return da un error.
BORRADO
Para borrar una funcin se utiliza:
DROP FUNCTION Nombre_procedimiento;
EJECUCIN
Los argumentos OUT o IN OUT son vlidos dentro de las funciones pero se
usan raramente.
NOTA
Una funcin se invoca con la sentencia EXECUTE, como ocurre en los
procedimientos, pero hay que tener en cuenta que tiene que asignarse a
alguna variable del mismo tipo que se devuelve.
IMPORTANTE
PL/SQL II
VERSIN 1 JPV-99 12 / 50
Una funcin se puede invocar desde una sentencia SELECT, WHERE, HAVING,
clusula VALUES de un INSERT y SET de un UPDATE.
Pueden pasarse y devolver REGISTROS y TABLAS.
FUNCIONES PL/SQL DENTRO DE SENTENCIAS SQL
Para incluir una funcin dentro de una sentencia SQL:
Debe de ser una funcin de fila nica (devuelven un nico valor). No pueden ser ni
registros ni tablas.
Todos los argumentos deber ser de tipo IN.
Los tipos de datos: BOOLEAN, RECORD o TABLE no estn permitidos (no son
tipo SQL).
El valor resultante tiene que ser: NUMBER, CHAR, VARCHAR2, DATE.
Las funciones no pueden modificar datos en las tablas. No se puede utilizar
INSERT, UPDATE, DELETE dentro de ellas.
Las funciones pueden incluirse tanto en el bloque WHERE de una SELECT
como directamente en una VISTA.
NOTA
PL/SQL II
VERSIN 1 JPV-99 13 / 50
SSUUBBPPRROOGGRRAAMMAASS LLOOCCAALLEESS..
Al igual que los procedimientos y funciones, es posible incluir en un bloque PL/SQL un
subprograma.
Los subprogramas se incluyen en el DECLARE del bloque y es necesario
incluir el subprograma entero.
IMPORTANTE
EJERCICIOS SOBRE FUNCIONES
EJERCICIO 3
Crear una funcin que nos permita realizar una consulta del salario del
empleado de la tabla EMP que se le pasa como parmetro desde SQL* (se
le pasa el nmero del empleado). Si la consulta ha sido satisfactoria la
funcin devuelve un SI, en caso contrario devuelve un NO.
Utilizar desde el SQL para llamar a la funcin: dbms_output.put_line(Existe
el empleado?||di_si_existe(&empleado));
PRCTICA
PL/SQL II
VERSIN 1 JPV-99 14 / 50
EJERCICIO 4
Utilizar una sentencia SELECT sobre la tabla EMP que nos permita ver los
campos empno, ename y el salario de los empleados. Si el empleado tiene
una salario mltiplo de 5 y mayor de 1500 mostrar su salario multiplicado por
15, en caso contrario su salario permanece invariable.
EJERCICIO 5
Utilizar una SELECT para extraer de la tabla EMP cada uno de los
empleados y su mximo jefe.
Obtener su mximo jefe utilizando una funcin.
EJERCICIO 6
Crear un bloque PL/SQL que sea capaz de cargar un array de registros
cuyos campos son nombre_empledo y ranking y muestre el contenido de
dicho array ordenado.
El campo ranking lo obtendremos a travs de un procedimiento a partir del
cual se va a obtener el puesto que ocupa cada empleado en la empresa en
cuestin de salario + comisin.
Utilizar un cursor para cargar la tabla.
PL/SQL II
VERSIN 1 JPV-99 15 / 50
CCOONNTTRROOLL DDEE PPRROOCCEEDDIIMMIIEENNTTOOSS YY FFUUNNCCIIOONNEESS..
DOCUMENTACIN DE PROCEDIMIENTOS Y FUNCIONES.
A travs de la vista del diccionario de datos USER_OBJECTS se pueden obtener los
nombres de los siguientes elementos de un esquema.
DATABASE LINK
FUNCTION
INDEX
PACKAGE
PACKAGE BODY
PROCEDURE
SEQUENCE
SYNONYM
TABLE
TRIGGER
VIEW
A travs de la vista del diccionario de datos USER_SOURCE se puede obtener el
cdigo de los siguientes elementos dentro de un esquema:
FUNCTION
PACKAGE
PACKAGE BODY
PROCEDURE
PL/SQL II
VERSIN 1 JPV-99 16 / 50
Para visualizar el nombre de un procedimiento o funcin y su lista de argumentos
utilizaremos el comando DESCRIBE.
DESC[RIBE] Nombre_procedimiento o Nombre_funcin;
Para mostrar el texto de los errores de compilacin utilizaremos la vista
USER_ERRORS.
Para visualizar los errores de compilacin utilizaremos la siguiente sentencia:
SHOW ERRORS PROCEDURE o FUNCTION o PACKAGE o
PACKAGE BODY o TRIGGER nombre_objeto;
DEPURACIN DE PROCEDIMIENTOS Y FUNCIONES.
Para activar este procedimiento utilizaremos la opcin
SET SERVEROUTPUT ON
Para preparar el texto del mensaje de salida se utiliza PUT.
DBMS_OUTPUT.PUT (Texto);
Para la depuracin de procedimientos y funciones se utiliza el
procedimiento suministrado por Oracle: DBMS_OUTPUT
IMPORTANTE
PL/SQL II
VERSIN 1 JPV-99 17 / 50
Para visualizar por pantalla el mensaje utilizamos NEW_LINE.
DBMS_OUTPUT.NEW_LINE;
Para preparar y visualizar el texto se utiliza PUT_LINE (opcin ms utilizada)
Estos procedimientos estn sobrecargados y pueden mostrar directamente datos
de los siguientes formatos:
DBMS_OUTPUT.PUT_LINE (varchar2)
DBMS_OUTPUT.PUT_LINE (number)
DBMS_OUTPUT.PUT_LINE (date)
No hace falta transformar un entero a varchar2 para utilizarlo en la sentencia
DBMS_OUTPUT.
NOTA
PL/SQL II
VERSIN 1 JPV-99 18 / 50
Este sera el diagrama en el que se explica el funcionamiento del DBMS_OUTPUT:
La salida DBMS_OUTPUT es independiente para cada sesin.
NOTA
Para que no nos d un error debido a que el buffer es muy pequeo, conviene
inicializarlo mediante el comando:
SET SERVEROUTPUT ON size 1000000
NOTA
PL/SQL II
VERSIN 1 JPV-99 19 / 50
2. DESARROLLO Y UTILIZACIN DE PAQUETES
PPAAQQUUEETTEESS ((PPAACCKKAAGGEESS))
Estructura de un paquete:
PBLICA
Variable Pblica
Declaracin del Procedimiento AProcedimiento Pblico
Variable Privada
Definicin del Procedimiento B
Definicin del Procedimiento A
Variable local
Procedimiento Privado
Procedimiento Pblico
PRIVADA
PACKAGE
PACKAGE
BODY
Zona de Especificacin
Cuerpo del paquete
Un paquete es un grupo de identificadores y rutinas agrupadas dentro de la
misma construccin.
IMPORTANTE
PL/SQL II
VERSIN 1 JPV-99 20 / 50
CREACIN DE PAQUETES
Para crear un paquete:
CREATE [OR REPLACE] PACKAGE Nombre_paquete IS O AS
Declaracin variable
Declaracin cursor
Declaracin excepcin
Declaracin procedimiento
Declaracin funcin
END Nombre_paquete
Para la creacin del cuerpo del paquete:
CREATE [OR REPLACE] PACKAGE BODY Nombre_paquete IS O AS
Declaracin variable
Declaracin cursor
Declaracin excepcin
Cdigo del procedimiento
Cdigo de la funcin
[BEGIN Cdigo de inicializacin del paquete]
END Nombre_paquete
Para borrar un paquete y el cuerpo del paquete se utiliza.
DROP PACKAGE Nombre_paquete
PL/SQL II
VERSIN 1 JPV-99 21 / 50
Para borrar el cuerpo del paquete se utiliza.
DROP PACKAGE BODY Nombre_paquete
Para invocar un procedimiento o funcin de un paquete desde fuera del mismo se
utiliza la orden EXECUTE desde SQL*, (desde un form no es necesario el
EXECUTE).
EXEC[UTE] Nombre_paquete.Nombre_funcin
Nombre_procedimiento
Siempre es posible declarar una variable en un bloque PL/SQL del mismo tipo que
uno que figure dentro del package:
DECLARE
V_hist ClassPackage.t_lista;
Cualquier objeto de la cabecera de un paquete est dentro del mbito y
visible desde fuera.
NOMBRE_PAQUETE.NOMBRE_OBJETO
NOTA
Dentro del cuerpo del paquete se puede hacer referencia a los objetos sin
necesidad del "."
NOTA
PL/SQL II
VERSIN 1 JPV-99 22 / 50
Los packages disponen de la opcin de sobrecarga de procedimientos y funciones,
es decir, con el mismo nombre y distintos argumentos.
No se pueden sobrecargar si difieren slo en el modo (IN OUT).
No se pueden sobrecargar si difieren slo en el tipo de dato devuelto.
No se pueden sobrecargar si difieren slo en la familia del tipo de dato.
NOTA
DECLARE
FUNCTION value_ok (date_in IN DATE)
RETURN BOOLEAN IS
BEGIN
RETURN date_in 0; Number Version
END;
BEGIN
IF value_ok (SYSDATE) THEN ... END IF;
IF value_ok (total_sales) THEN ... END IF;
END;
PL/SQL II
VERSIN 1 JPV-99 23 / 50
Podemos cambiar el cuerpo sin cambiar la cabecera.
Si cambiamos la cabecera y no el cuerpo ste queda invlido, siendo necesario
volver a compilarlo.
Para compilar los objetos invlidos utilizaremos la siguiente sentencia:
select
'alter '||
decode ( object_type, 'PACKAGE BODY', 'PACKAGE', object_type )||
' '||
object_name||
' compile'||
decode ( object_type, 'PACKAGE BODY', ' body;', ';' )
from
user_objects
where
status = 'INVALID'
/
FFUUNNCCIIOONNEESS DDEENNTTRROO DDEE PPAAQQUUEETTEESS..
Es necesario indicar el nivel de depuracin de una funcin dentro de un paquete
cuando se crea un paquete (en la especificacin).
El nivel de depuracin determina qu operaciones no van a ser realizadas por la
funcin del paquete.
No se puede utilizar una funcin que est dentro de un paquete en una sentencia
SQL. Es necesario indicar el nivel de depuracin.
PL/SQL II
VERSIN 1 JPV-99 24 / 50
Para ello utilizaremos la sentencia:
PRAGMA RESTRICT_REFERENCES (NOMBRE_FUNCION,
WNDS [,WNPS] [,RNDS] [,RNPS]);
El pragma se indica en la especificacin del paquete detrs de todas las
funciones.
El argumento WNDS debe indicarse SIEMPRE que se utilice
RESTRICT_REFERENCES.
WNDS -> (Writes No Database State) Indica que la funcin no va
modificar tablas de la base de datos
WNPS -> (Writes No Package Status) Indica que la funcin no va a
cambiar los valores de variables de un paquete pblico.
RNDS -> (Reads No Database State) Indica que la funcin no va
aconsultar ninguna tabla de la base de datos.
RNPS-> (Reads No Package Status) Indica que la funcin no va a
referenciar los valores de las variables de un paquete pblico.
CREATE OR REPLACE PACKAGE PAQUETE IS
FUNCTION MyFuncName ( inVal Number ) Return Number;
PROCEDURE MyProcName ( inVal Number, JobId VARCHAR2 );
pragma restrict_references ( MyFuncName, WNDS, WNPS, RNDS );
END PAQUETE;
/
PL/SQL II
VERSIN 1 JPV-99 25 / 50
CREATE OR REPLACE PACKAGE BODY PAQUETE AS
FUNCTION MyFuncName ( inVal Number ) Return Number IS
TmpVar NUMBER;
BEGIN
tmpVar := 0;
EXCEPTION
WHEN NO_DATA_FOUND THEN
Null;
WHEN OTHERS THEN
Null;
RETURN tmpVar;
END MyFuncName;
PROCEDURE MyProcName ( inVal Number, JobId VARCHAR2 ) IS
TmpVar NUMBER;
BEGIN
tmpVar := 0;
EXCEPTION
WHEN NO_DATA_FOUND THEN
Null;
WHEN OTHERS THEN
Null;
END MyProcName;
END PAQUETE;
/
PL/SQL II
VERSIN 1 JPV-99 26 / 50
EJERCICIOS SOBRE PAQUETES
EJERCICIO 7
Crear un paquete con los siguientes elementos: una tabla para almacenar
registros con los campos nombre, salario, un procedimiento
pr_insertar(nombre, salario) y un ndice.
Se tratara de recuperar desde un bloque PL/SQL los elementos de la tabla
EMP cuya suma de su salario + comisin > 2000 e ir introducindolos en la
tabla del paquete recin creado a partir de la funcin pr_insertar.
Consultar desde el bloque PL/SQL el ndice del paquete y obtener el nmero
de registros introducidos en dicha tabla.
EJERCICIO 8
Ampliar el paquete creado en el ejercicio con las funciones fu_recupera_sal
y fu_inicializa.
La nueva funcin, fu_recupera_sal, nos va a permitir recuperar el salario de
un empleado si se le pasa el nombre como argumento. En el caso de halla
varias personas con el mismo nombre recuperar la primera. En el caso de
que no hubiera ninguna mostrar por pantalla el mensaje de error ORA-
20001 Persona no encontrada. Probar esta funcin desde SQL*.
La funcin fu_inicializa borra la tabla y pone el ndice a 0.
PRCTICA
PL/SQL II
VERSIN 1 JPV-99 27 / 50
EJERCICIO 9
Crear un paquete con tres funciones que se van a llamar (las tres)
fu_recupera.
Si se le pasa un nmero me va a devolver el salario de la persona
que se encuentra en la posicin que se le est pasando como
argumento de la tabla del paquete anterior. En caso de no existir
dicho elemento en la tabla mostrar un mensaje por pantalla.
Si se pasa una cadena de caracteres tiene que hacer una
consulta sobre la tabla EMP de tal forma que nos tiene que contar
el nmero de personas con el mismo nombre que la cadena que
se le est pasando.
Si se le pasa una fecha tiene que introducir en una tabla (no
pblica) las personas con una antigedad mayor que la pasada
como parmetro de forma ordenada por fecha . Se trata de una
tabla de registros con los campos Nombre, antigedad. Extraer
cada uno de esos empleados de la tabla, visualizando el nombre
del empleado y el nmero de das que lleva en la empresa.
EJERCICIO 10
Ampliar el primer paquete creado con la funcin fu_media_comision la cual
nos va a dar la media de las comisiones de todos los empleados que tienen
tabajo CLERK.
Realizar una consulta en SQL* sobre la tabla EMP de forma que extraiga los
empleados cuya comisin sea mayor que el valor devuelto por la funcin
fu_media_comision.
PL/SQL II
VERSIN 1 JPV-99 28 / 50
3. DISPARADORES EN BASE DE DATOS
DDIISSPPAARRAADDOORREESS ((TTRRIIGGGGEERRSS))
Se asemejan con los procedimientos y funciones en que son bloques PL/SQL
nominados con secciones declarativa, ejecutable y de manejo de excepciones y en
que se almacenan en la base de datos.
Se diferencian en que se ejecutan implcitamente cuando se ejecuta una sentencia de
manipulacin de datos sobre una tabla (INSERT, UPDATE, DELETE), y en que el
disparador no admite argumentos.
Los disparadores se utilizan principalmente para:
Para el mantenimiento de restricciones de integridad compleja, que no sean
posibles con las restricciones declarativas definidas en el momento de crear la
tabla. (Comn en desnormalizaciones).
En la auditora de la informacin contenida en la tabla, registrando los cambios
realizados y la identidad de quien lo llev a cabo.
El aviso automtico a otros programas de que hay que llevar a cabo una
determinada accin, cuando se realiza un cambio en la tabla.
Tipos de disparadores:
Disparadores de sentencia: Se ejecutan una sola vez por cada sentencia.
Un disparador es un bloque PL/SQL asociado a una tabla que se ejecuta
cuando una determinada instruccin SQL se va a ejecutar sobre dicha
tabla.
IMPORTANTE
PL/SQL II
VERSIN 1 JPV-99 29 / 50
Disparadores de fila: Se activan una vez por cada fila afectada por la orden que
provoc el disparo.
Se pueden combinar diferentes acontecimientos en un nico disparador, utilizando los
predicados condicionales INSERTING, UPDATING y DELETING dentro del cuerpo del
disparador (devuelven un boolean TRUE o FALSE cuando se consultan).
Se puede visualizar el contenido de un disparador a travs de la vista del diccionario
de datos USER_TRIGGERS.
Clasificacin:
Segn el momento en el que salta el disparador *BEFORE
* AFTER
Segn el tipo de operacin que provoca su actuacin * INSERT
* UPDATE
* DELETE
Segn las veces que se ejecuta el cuerpo del disparador * Sentencia
* Fila
En la figura de abajo se disparan los triggers para la operacin que contiene la
clusula WHERE: WHERE ENAME LIKE 'J%':
Dentro de un disparador estn prohibidas sentencias transaccionales:
COMMIT, ROLLBACK y SAVEPOINT.
NOTA
PL/SQL II
VERSIN 1 JPV-99 30 / 50
Para borrar un trigger utilizaremos:
DROP TRIGGER Nombre_trigger
CCRREEAACCIINN DDEE DDIISSPPAARRAADDOORREESS
DISPARADORES DE SENTENCIA
Se utiliza las siguientes sentencia para los disparadores de sentencia:
CREATE [OR REPLACE] TRIGGER Nombre_disparador
MOMENTO ACONTECIMIENTO ON Nombre_tabla
BLOQUE PL/SQL
DISPARADORES DE FILA
Para los disparadores de fila se utiliza esta otra sentencia:
CREATE [OR REPLACE] TRIGGER Nombre_disparador
MOMENTO ACONTECIMIENTO ON Nombre_tabla
FOR EACH ROW [WHEN Condicin_restriccin]
[REFERENCING OLD O NEW AS Nombre_sustituto_old_o_new]
Dentro de un disparador de fila, se puede referenciar el valor de la columna antes
de ser modificado anteponiendo el cualificador :OLD y referenciar el nuevo valor de
la columna anteponiendo el cualificador :NEW.
Durante la insercin el valor antiguo es NULL, durante el borrado el valor nuevo es
NULL.
El cualificador :NEW puede aparecer a la izquierda de una asignacin en el cuerpo
PL/SQL solamente en disparadores de fila BEFORE. No puede aparecer en la
PL/SQL II
VERSIN 1 JPV-99 31 / 50
parte izquierda de una asignacin en el cuerpo PL/SQL de un disparador AFTER.
Ni en el predicado condicional DELETING.
El cualificador :OLD no puede aparecer nunca en la parte izquierda de una
sentencia de asignacin.
ACTIVACIN DE DISPARADORES
Para activar un disparador:
ALTER TRIGGER Nombre_disparador ENABLE;
Para desactivar un disparador:
ALTER TRIGGER Nombre_disparador
Aunque no surga un error de compilacin, hay que tener en cuenta que :OLD no
est definido para las rdenes INSERT, as como no lo estar :NEW para el
DELETE.
NOTA
A pesar de que :NEW y :OLD sean tratados sintcticamente como registros del
tipo tabladisparo%Rowtype, en realidad no son registros (por tanto no se
pueden asignar como registros completos); sino que son variables de
acoplamiento.
NOTA
PL/SQL II
VERSIN 1 JPV-99 32 / 50
ORDEN DE EJECUCIN DE LOS DISPARADORES
Los disparadores se ejecutan segn el siguiente orden:
1. Ejecutar, si existe, el disparador de tipo BEFORE (disparador previo) de tipo
sentencia.
2. Para cada fila a la que afecte la orden.
a) Ejecutar, si existe, el disparador BEFORE a nivel de fila.
b) Ejecutar la propia orden.
c) Ejecutar, si existe, el disparador de tipo AFTER con nivel de fila.
3. Ejecutar, si existe, el disparador AFTER, de tipo sentencia.
CCOONNCCEEPPTTOO DDEE TTAABBLLAA MMUUTTAANNTTEE
Un trigger de sentencia nunca provoca el error de tabla mutante.
Supongamos un trigger for each row que se dispara cuando se modifiquen datos de
una tabla. El trigger a su vez realiza una modificacin sobre la misma tabla. Esto
provoca que la tabla quede mutante por la incosistencia de la informacin en ese
instante y da un error por pantalla.
Una tabla mutante es una tabla que est modificndose actualmente por
una orden DML (INSERT, UPDATE, DELETE).
Para un disparador, sta es la tabla sobre la que est definido.
IMPORTANTE
PL/SQL II
VERSIN 1 JPV-99 33 / 50
La solucin del error de la tabla mutante consistira en crear un disparador de
sentencia BEFORE en el que se van almacenando los datos (no se consulta ni
modifica la misma tabla), y otro de fila AFTER que utilizarn los valores almacenados
por el disparador de sentencia:
BEFORE -> Inicializa
BEFORE EACH ROW -> Almacena
AFTER -> Procesa
Si una operacin INSERT afecta a una nica fila, entonces los disparadores de
fila previo y posterior por dicha fila no tratarn a la tabla como mutante.
NOTA
CREATE OR REPLACE TRIGGER DISPARADOR
BEFORE INSERT OR UPDATE ON MyTableName
FOR EACH ROW
tmpVar NUMBER;
BEGIN
tmpVar := 0;
Select MySeq.NextVal into tmpVar from dual;
:NEW.SequenceColumn := tmpVar;
:NEW.CreatedDate := Sysdate;
PL/SQL II
VERSIN 1 JPV-99 34 / 50
:NEW.CreatedUser := User;
EXCEPTION
WHEN OTHERS THEN
Null;
END DISPARADOR;
/
EJERCICIOS SOBRE TRIGGERS
EJERCICIO 11
Crear un trigger sobre EMP de forma que cuando se vaya a insertar un
nuevo registro verifique que no haya ms de 20 registros ya insertados. Si
ya los hubiera, mostrar un mensaje de error indicando la imposibilidad de
insertar el nuevo registro.
EJERCICIO 12
Hacer un disparador de base de datos sobre la tabla DEPT, en el cual
cuando se inserte o se actualice el nmero de departamento, compruebe
que este nmero sea mltiplo de diez.
PRCTICA
PL/SQL II
VERSIN 1 JPV-99 35 / 50
EJERCICIO 13
Crear la tabla CONTABILIDAD con los campos departamento, movimiento y
dinero.
Crear un disparador de fila de base de datos en el cual cada vez que se
hace una operacin sobre la tabla EMP (insercin, modificacin,borrado),
realice una insercin sobre la tabla CONTABILIDAD con el movimiento
realizado sobre EMP. Los movimientos a insertar son de tres tipo:
INSERCION, MODIFICACION, BORRADO.
EJERCICIO 14
Realizar un disparador de fila sobre la tabla EMP que se ejecute cuando se
actualiza o se inserte sobre la tabla EMP, comprobar que el salario se
encuentra entre el mximo y el mnimo de ese trabajo para un
departamento.
En el caso de que no exista ninguna fila en la tabla EMP cuyo
departamento sea igual al insertado, hay que comprobar que existe el
departamento en la tabla DEPT. En el caso de existir, insertar la fila en
EMP sin ms comprobaciones. En caso de no existir insertar el
departamento en la tabla DEPT con el campo dname a NULL y el campo
loc a NULL.
Si se modifica el departamento de un director hay que cambiar el
departamento a sus empleados.
EJERCICIO 15
Crear VIGENCIAS con los campos: empleado, f_desde y f_hasta.
Realizar un disparador sobre la tabla VIGENCIAS del manera que
compruebe que cada fila tratada no se solape con otra ya insertada.
PL/SQL II
VERSIN 1 JPV-99 36 / 50
EJERCICIO 16
Realizar un disparador de fila sobre la tabla emp que se ejecute cuando se
actualiza sobre la tabla emp el campo trabajo (JOB) y que compruebe que si
se trata de un vendedor (SALESMAN) su comisin no sea mayor que la
del jefe con menor comisin.
Modificar los empleados de la tabla emp que tienen trabajo CLERK y
sustituirlo por SALESMAN. Observar lo que pasa.
Sustituir el trigger de fila por dos, uno antes de modificar (for each row) y
otro after (de sentencia) y un paquete que solucione el error de la tabla
mutante.
PL/SQL II
VERSIN 1 JPV-99 37 / 50
4. PL/SQL DINMICO
CCOONNCCEEPPTTOO
Mediante el DBMS_SQL podemos manejar tambin rdenes DML.
Las rdenes SQL Dinmicas tienen muy pocas restricciones, porque si se desea, la
orden completa SQl se puede determinar en el momento de la ejecucin, en lugar de
en la compilacin.
Desventajas:
El SQL Dinmico no se ejecuta con la misma eficiencia que el esttico.
Aquellas tablas a las que se hace referencia no aparecern en
USER_DEPENDENCES.
El PL/SQL dinmico nace de la necesidad de implementar rdenes DDL
dentro de un bloque de PL/SQL.
Se implementa en el paquete DBMS_SQL
IMPORTANTE
En ocasiones, la necesidad de incluir rdenes DML dinmicamente surge al
hacer referencia a una tabla, que se crear en ejecucin; por lo que si la orden
que la refiere estuviera en SQL esttico, no compilara.
NOTA
PL/SQL II
VERSIN 1 JPV-99 38 / 50
Cuando se borra una tabla dinmicamente, es labor del usuario el cambiar el
estado de los paquetes que hagan referencia a dicha tabla.
PROCEDIMIENTOS DE SQL DINMICO:
Funcin DBMS_SQL.OPEN_CURSOR RETURN INTEGER;
Abre el puntero para el cursor
Procedure DBMS_SQL.PARSE (cursor IN INTEGER, sentencia_a_ejecutar IN
VARCHAR2, DBMS_SQL.NATIVE IN INTEGER);
Asocia el puntero con la sentencia SQL
Funcin DBMS_SQL.IS_OPEN (c IN INTEGER) RETUR
Top Related