SlideShare una empresa de Scribd logo
1 de 166
Descargar para leer sin conexión
PL/SQL I
VERSIÓN 1 JPV-99 1 / 67
PPLL//SSQQLL II
Javier Pérez-Vigo (Octubre 1999)
PL/SQL I
VERSIÓN 1 JPV-99 2 / 67
INTRODUCCIÓN
ORACLE es un sistema de base de datos relacional potente y flexible.
El lenguaje de programación PL/SQL está diseñado 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 manipulación de información
almacenada en bases de datos ORACLE y para el desarrollo de
cualquier aplicación en ese entorno.
En esta unidad didáctica se definen las principales características de
este lenguaje y su sintaxis, se enumeran las principales funciones
predefinidas.
Así mismo se estudian las órdenes SQL disponibles: de control, de
manipulación de datos y transaccionales.
Posteriormente se introduce el concepto de cursor y por último se explica
cómo se diseña el tratamiento de errores.
PL/SQL I
VERSIÓN 1 JPV-99 3 / 67
CONTENIDO
1. DEFINICIÓN Y CARACTERÍSTICAS DE PL/SQL
2. EL BLOQUE PL/SQL
ZONA DE DECLARACIÓN: DECLARACIÓN DE VARIABLES Y
CONSTANTES
ZONA DE PROCESO
ZONA DE EXCEPCIONES
3. FUNCIONES SQL PREDEFINIDAS
FUNCIONES DE CARÁCTER QUE DEVUELVEN VALORES
DE CARÁCTER
FUNCIONES DE CARÁCTER QUE DEVUELVEN VALORES
NUMÉRICOS
FUNCIONES NUMÉRICAS
FUNCIONES DE FECHA
FUNCIONES DE CONVERSIÓN
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 EVALUACIÓN
PL/SQL I
VERSIÓN 1 JPV-99 4 / 67
OBJETIVOS
El alumno tras el estudio de esta unidad didáctica podrá:
Conocer la sintaxis y los elementos que componen el lenguaje
PL/SQL.
Consultar y manipular la información almacenada en servidores de
Bases de Datos Oracle.
Desarrollar estructuras básicas de programación en PL/SQL.
EXPECTATIVAS
• ··························································································································
························································································································
• ··························································································································
························································································································
• ··························································································································
························································································································
PL/SQL I
VERSIÓN 1 JPV-99 5 / 67
1. DEFINICIÓN Y CARACTERÍSTICAS 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 técnicas 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 código ejecutable almacenado en el servidor de base de datos.
♦ PL/SQL, (Procedural Language / SQL), es un lenguaje de programación
procedural estructurado en bloques que amplia la funcionalidad del lenguaje
standard SQL a través 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 métodos, (a partir de versión 8)
IMPORTANTE
DQL. Data Query Language (select)
DML Data manipulation language (insert)
DDL Data definition language (create table)
NOTA
PL/SQL I
VERSIÓN 1 JPV-99 6 / 67
Es un lenguaje estructurado en bloques: Bloque es la unidad básica 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 construcción, cuya finalidad es el encapsulamiento,
la abstracción y el control de acceso).
• Disparadores (Eventos que se ejecutan cuando ocurre una operación de
manipulación de datos sobre una tabla)
La versión objeto de estudio será la 2.3.
NOTA
También se pueden incorporar órdenes DDL mediante SQL Dinámico.
NOTA
PL/SQL I
VERSIÓN 1 JPV-99 7 / 67
2. EL BLOQUE PL/SQL
Todos los bloques tienen tres secciones diferenciadas:
• Sección declarativa.
• Sección ejecutable, (la única obligatoria).
• Sección de excepciones.
EESSTTRRUUCCTTUURRAA::
[DECLARE]
Declaración 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.
ExcepciónVariables para control de errores.
♦ El Bloque PL/SQL es la unidad básica 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
VERSIÓN 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 excepción pueden ser definidos por el usuario o por el
sistema, como es por ejemplo la excepción ZERO_DIVIDE. Las excepciones se
activan automáticamente al ocurrir un error, existiendo la definición de la excepción
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 DDEECCLLAARRAACCIIÓÓNN:: DDEE VVAARRIIAABBLLEESS YY CCOONNSSTTAANNTTEESS
Las variables son utilizadas para guardar valores devueltos por una consulta o
almacenar cálculos intermedios.
Las constantes son campos que se definen y no alteran su valor en el proceso.
Nombre_campo [CONSTANT] Tipo de dato := valor_constante / expresión_pl_sql
Este tipo de bloque se le suele llamar anónimo, y es el más utilizado en Scripts.
NOTA
PL/SQL I
VERSIÓN 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 también 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 sólo en bloques PL/SQL anónimos.
Var1 number(59);
Var2 Var1%TYPE;
Var3 tabla.identificador%TYPE;
registro tabla%ROWTYPE
PL/SQL I
VERSIÓN 1 JPV-99 10 / 67
TIPOS DE DATOS.
Number (n [, d]) – numérico n <= 38
Binary_Integer – entero, desde –2147483647 a +2147483647
PLS_Integer – entero, desde –2147483647 a +2147483647
Char – de longitud fija, hasta 255 caracteres
Varchar – de tipo carácter (obsoleto)
Varchar2 – Tamaño variable hasta 2000 caracteres.
Date - Fechas
Boolean – TRUE o FALSE (no puede utilizarse en campos SQL)
Long- Cadena de caracteres de longitud variable hasta 2 Gigabytes
Raw- Datos binarios de longitud variable, hasta 255 caracteres (gráficos)
Longraw- Cadena binaria de longitud variable de hasta 2 Gigabytes (gráficos)
El tipo PLS_Integer se suele utilizar para contadores. Es idéntico al
Binary_integer pero añade la característica de dar un mensaje de error en caso
de error.
El tipo Binary_Integer se suele utilizar para tablas de PL/SQL
NOTA
PL/SQL I
VERSIÓN 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 más de uno provoca un ERROR,
saltando la ejecución directamente al EXCEPTION.
ASIGNACIÓN DE VALORES
Las dos formas que existen para asignar valores a variables de memoria, son:
- Con el operador de asignación :=, como cuando calculamos el promedio de las
ventas asignándole 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
asignación de valores a las variables xtotal y xcant con el siguiente código:
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
VERSIÓN 1 JPV-99 12 / 67
COMENTARIOS
Hay dos tipos de comentarios:
Con el signo -- se indica comentario de una sola línea.
Mediante /* al principio del comentario y */ al final de éste.
ZZOONNAA DDEE EEXXCCEEPPCCIIOONNEESS
Las excepciones saltan cuando se ha producido un error en la ejecución.
Es sección no obligatoria. Esta sección 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 después del WHEN:
Excepción Número de error
CURSOR_ALREADY_OPEN ORA–06511 –6511
DUP_VAL_ON_INDEX ORA–00001 –1
INVALID_CURSOR ORA–01001 –1001
INVALID_NUMBER ORA–01722 –1722
LOGIN_DENIED ORA–01017 –1017
NO_DATA–FOUND ORA–01403 +100
NOT_LOGGED_ON ORA–01012 –1012
PROGRAM_ERROR ORA–06501 –6501
PL/SQL I
VERSIÓN 1 JPV-99 13 / 67
ROWTYPE_MISMATCH ORA–06504 –6504
STORAGE_ERROR ORA–06500 –6500
TIMEOUT_ON_RESOURCE ORA–00051 –51
TOO_MANY_ROWS ORA–01422 –1422
VALUE_ERROR ORA–06502 –6502
ZERO_DIVIDE ORA–01476 –1476
EJERCICIO Nº 1
Crear un bloque PL/SQL con las siguientes características:
• Definir una constante de tipo numérico, de nombre x, a la que le vamos a
asignar el valor de 12.
• Definir una variable, y, del mismo tipo que el campo hiredate, de la tabla
EMP, de la base de datos DEMO.
• Definir una variable de tipo numérico que se llame z.
• Asignar a la variable y la fecha actual. Asignar a la variable z el resultado
de multiplicar x por 10.
• Mostrar por pantalla el contenido de las variables y e z.
EJERCICIO
PL/SQL I
VERSIÓN 1 JPV-99 14 / 67
EJERCICIO Nº 2
Se trata de hacer una consulta a la tabla EMP, concretamente del campo
ename de tal forma que el usuario introduzca un nombre por teclado y el bloque
PL/SQL sea capaz de recuperar el campo job de dicho empleado a través de
dicha consulta.
• Pedir que se introduzca por teclado un nombre, el cual lo
almacenaremos en la variable nombre.
• Una vez introducido el nombre, lanzar un bloque PL/SQL (previamente
creado) de tal forma que sea capaz de seleccionar la fila de la tabla EMP
cuyo ename sea igual al introducido por teclado y mostrar el campo job
correspondiente a ese empleado por pantalla.
EJERCICIO
PL/SQL I
VERSIÓN 1 JPV-99 15 / 67
3. FUNCIONES SQL PREDEFINIDAS
FFUUNNCCIIOONNEESS DDEE CCAARRÁÁCCTTEERR QQUUEE DDEEVVUUEELLVVEENN VVAALLOORREESS DDEE
CCAARRÁÁCCTTEERR
♦ CHR Chr(x)
Devuelve el carácter dado su número ASCII .
♦ CONCAT Concat (cadena1, cadena2)
Devuelve las dos cadenas encadenadas (Es idéntico a usar ||).
♦ INITCAP Initcap (cadena)
Devuelve la misma cadena, con el primer carácter de cada palabra en
mayúscula y el resto en minúscula.
♦ LOWER Lower (cadena)
Devuelve la misma cadena con todos los caracteres en minúscula.
♦ 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
VERSIÓN 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 porción, de b caracteres de longitud, de la cadena
proporcionada como argumento, empezando a partir de la posición 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
contaría desde el final de la cadena.
♦ UPPER Upper (cadena)
Devuelve la cadena proporcionada con todas las letras en mayúsculas.
PL/SQL I
VERSIÓN 1 JPV-99 17 / 67
FFUUNNCCIIOONNEESS DDEE CCAARRÁÁCCTTEERR QQUUEE DDEEVVUUEELLVVEENN VVAALLOORREESS
NNUUMMÉÉRRIICCOOSS
♦ ASCII ASCII (cadena)
Devuelve la representación decimal del primer byte de la cadena.
♦ INSTR INSTR (cadena1, cadena2 [,a[,b]])
Devuelve la posición de la cadena1 donde está contenida la cadena2.
(La cadena se explora desde la izquierda, empezando a partir de la
posición a. Sí a es negativo, entonces la cadena1 se explora desde la
derecha. El valor devuelto es el de la aparición número b de la cadena
de la búsqueda).
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
VERSIÓN 1 JPV-99 18 / 67
♦ LENGTH Length (cadena)
Devuelve la longitud de la cadena.
FFUUNNCCIIOONNEESS NNUUMMÉÉRRIICCAASS
♦ 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(‘Scott’’s spot’, ‘ot’, 1, 2) Cadena FROM dual;
> 11
PL/SQL I
VERSIÓN 1 JPV-99 19 / 67
♦ COSH COSH (x)
Devuelve el coseno hiperbólico 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 número 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 hiperbólico de x
♦ SQRT SQRT (x)
Devuelve la raiz cuadrada de X
PL/SQL I
VERSIÓN 1 JPV-99 20 / 67
♦ TAN TAN (x)
Devuelve la tangente de x (en radianes)
♦ TANH TANH (x)
Devuelve la tangente hiperbólica 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 más x meses
♦ LAST_DAY LAST_DAY (d)
Devuelve la fecha del último día del mes al que d pertenece
♦ MONTHS_BETWEEN MONTHS_BETWEEN (fecha1, fecha2)
Devuelve el número 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
VERSIÓN 1 JPV-99 21 / 67
♦ NEXT_DAY NEXT_DAY(d, cadena)
Devuelve la fecha del día 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
VERSIÓN 1 JPV-99 22 / 67
FFUUNNCCIIOONNEESS DDEE CCOONNVVEERRSSIIÓÓNN
CONVERSIONES IMPLÍCITAS
PL/SQL Convierte automáticamente entre los siguientes tipos de datos:
CONVERSIONES EXPLÍCITAS
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
VERSIÓN 1 JPV-99 23 / 67
♦ TO_NUMBER TO_NUMBER (d [,formato [, paramls]])
Convierte la cadena a un valor numérico.
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
VERSIÓN 1 JPV-99 24 / 67
FORMATOS NUMÉRICOS
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
VERSIÓN 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
VERSIÓN 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 número de filas en la consulta
♦ MAX MAX ([Distinct | All] col)
Devuelve el valor máximo de la consulta de selección.
♦ MIN MIN ([Distinct | All] col)
Devuelve el valor mínimo de la consulta de selección.
PL/SQL I
VERSIÓN 1 JPV-99 27 / 67
♦ STDDEV STDDEV ([Distinct | All] col)
Devuelve la desviación estándar del elemento de lista de selección.
♦ SUM SUM ([Distinct | All] col)
Devuelve la suma de los valores para el elemento de lista de selección.
♦ VARIANCE VARIANCE ([Distinct | All] col)
Devuelve la varianza estadística del elemento de lista de selección.
OOTTRRAASS FFUUNNCCIIOONNEESS
♦ DECODE DECODE (expr_base, compara1, valor1,
compara2, valor2…
predeterminado)
La función DECODE es similar a una serie de órdenes IF-THEN-ELSE
anidadas. La expresión expr_base se compara sucesivamente con
compara1, compara2, etc. Si expr_base coincide con el elemento de
comparación número i, se devuelve el valor i. Si expr_base no coincide
con ninguno de los valores de comparación, se devuelve el valor
predeterminado.
♦ GREATEST GREATEST (expr1 [expr2] …)
Devuelve la expresión con mayor valor de todos sus argumentos. Cada
expresión es convertida de forma implícita al tipo de expr1 antes de
realizar las comparaciones. Si expr1 es de tipo carácter, se realizan
comparaciones de carácter sin relleno de blancos, y el resultado es de
tipo VARCHAR2.
PL/SQL I
VERSIÓN 1 JPV-99 28 / 67
♦ LEAST LEAST (expr1 [expr2] …)
Devuelve la expresión con menor valor de todos sus argumentos. Cada
expresión es convertida de forma implícita al tipo de expr1 antes de
realizar las comparaciones. Si expr1 es de tipo carácter, se realizan
comparaciones de carácter sin relleno de blancos, y el resultado es de
tipo VARCHAR2.
♦ NVL NVL (expr1 ,expr2)
Si el valor de expr1 es NULL, la función 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 (opción)
Devuelve un valor VARCHAR2 que contiene información acerca de la
sesión actual, según la opción seleccionada.
OPCIONES
LANGUAGE Devuelve el idioma y país utilizados
SESSIONID Devuelve el identificador del elemento de registro
de la sesión
TERMINAL Devuelve un identificador, dependiente del
sistema operativo, para el terminal de la sesión actual.
PL/SQL I
VERSIÓN 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
VERSIÓN 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 día de la semana actual en castellano en letra mediante un DECODE
y sin utilizar la máscara ‘d’.
EJERCICIO Nº 5
- Obtener las nuevas comisiones de los empleados teniendo en cuenta que se
subirán un 5% el próximo año y que aquellos que no tengan les corresponderán
como tales la cuarta parte de su salario.
PRÁCTICA
PL/SQL I
VERSIÓN 1 JPV-99 31 / 67
4. SENTENCIAS DE CONTROL
SSEENNTTEENNCCIIAA IIFF
IF Condición THEN sentencias_ejecutables
[ELSIF condición THEN sentencias_ejecutables; ]
ELSE sentencias_ejecutables; ]
END IF;
SQL> DECLARE
v_NumberSeats rooms.number_seats%TYPE;
v_Comment VARCHAR2(35);
BEGIN
/* Recibe el número 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
VERSIÓN 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
VERSIÓN 1 JPV-99 33 / 67
BBUUCCLLEESS CCOONNDDIICCIIOONNAALLEESS::
WHILE condición
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 <= 50 LOOP
INSERT INTO temp_table
VALUES (v_Counter, 'Loop index');
v_Counter := v_Counter + 1;
END LOOP;
END;
/
PL/SQL I
VERSIÓN 1 JPV-99 34 / 67
BBUUCCLLEESS NNUUMMÉÉRRIICCOOSS::
FOR índice IN [REVERSE] número_inicio..número_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 declaración 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
VERSIÓN 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 numérico.
• Introducir una fila por cada día del mes actual de tal forma que el resultado
final sea algo parecido a esto:
DÍAS
1
2
3
4
5
...
29
30
• Realizar el ejercicio utilizando for...loop , loop...exit y while.
EJERCICIO
PL/SQL I
VERSIÓN 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 número de fila leída 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 implícito por cada sentencia SQL que tenga que
procesar.
♦ Nos referiremos a él como SQL%
IMPORTANTE
PL/SQL I
VERSIÓN 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 número 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 número de departamento que no figura
en la tabla DEPT.
EJERCICIO
PL/SQL I
VERSIÓN 1 JPV-99 38 / 67
EJERCICIO 9
• Crear un bloque PL/SQL que modifique la tabla EMP de tal forma aquellos
empleados cuyo número de empleado sea –1 pasen a tener como job
‘CLERK’.
• Si no existiera ningún empleado con número –1, insertar dicho empleado
con las siguientes características:
ENAME: ‘PEDRO PEREZ’
JOB: ‘CLERK’
MGR: 7934
DPTNO: 20
• Capturar el error utilizando el cursor implícito SQL%.
EJERCICIO
PL/SQL I
VERSIÓN 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 condición 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 parámetros en la SELECT.
CURSOR NOMBRE_CURSOR (nombre_parametro tipo_parametro)
IS SENTENCIA SELECT utilizando los parámetros;
Variable de tipo %ROWTYPE.
♦ Un cursor es un área de trabajo que utiliza ORACLE para consultas que
devuelven más de una fila, permitiendo la lectura y manipulación de cada
una de ellas.
♦ Declaración:
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
VERSIÓN 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 más
filas que devolver
• Nombre_cursor%FOUND Contrario de %notfound
• Nombre_cursor%ROWCOUNT Devuelve el número de fila leída.
• 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 (parámetro).
Para cursores sin parámetros recuperamos una fila utilizando:
FETCH NOMBRE_CURSOR INTO VARIBLE1, VARIABLE2, VARIABLE3...
Cerramos un cursor utilizando la sentencia CLOSE.
BBUUCCLLEESS SSOOBBRREE CCUURRSSOORREESS
Realiza automáticamente las siguientes acciones:
• Abre el cursor.
Se realiza la lectura y se ejecutan las sentencias del bucle hasta que no haya
más filas.
PL/SQL I
VERSIÓN 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 continuación veremos un ejemplo de cursor con las siguientes características:
Objetivo: Consultar las ventas de una fecha dada ordenadas de mayor a
menor.
Nombre:CVENTAS.
Parámetros: cfecha, variable que contiene la fecha a consultar.
PL/SQL I
VERSIÓN 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
VERSIÓN 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 continuación detallaremos las sentencias usadas en este procedimiento:
DECLARE cursor
Define el cursor, su consulta y la lista de parámetros que se pasan a la orden
WHERE, es solo la declaración del cursor y no la realización 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 cómo está
definida esa columna en la tabla y, en caso que la definición de la columna sea
modificada, automáticamente se cambia la variable xarticulo.
OPEN cventas(xfecha);
Realiza la consulta asociada al cursor, pasando el valor del parámetro 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 numérico de repetición para poder consultar las 5 primeras ventas
devueltas por el cursor.
FETCH cventas INTO xarticulo,xvalor;
PL/SQL I
VERSIÓN 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 repetición, en caso que para una
fecha dada se hayan efectuado menos de 5 ventas, ya que en esta situación 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 leídos desde el cursor.
COMMIT;
Actualización 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 añadirles 1000 al
campo salario.
EJERCICIO
PL/SQL I
VERSIÓN 1 JPV-99 45 / 67
EJERCICIO 11
EJERCICIO SOBRE CURSORES
• Crear una tabla de totales por departamentos con dos campos: uno para los
números de departamento y otro numérico para meter los totales por
departamento.
• El proceso consiste en pedir por pantalla el número de departamento y
calcular el total de la suma de los salarios mas las comisiones. Utilizar un
cursor.
• Insertar el resultado en la tabla recién 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 cuántos 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 sólo aquellos trabajos que tengan más de 1 empleado.
EJERCICIO
PL/SQL I
VERSIÓN 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 también %TYPE y %ROWTYPE.
Se puede asignar un registro a otro del mismo tipo o sus campo individualmente, con
la condición 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
VERSIÓN 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
Sería una asignación ilegal que elevaría el error PLS-382. */
v_Rec1 := v_Rec2;
/* Estos campos, son del mismo tipo, por los que la asignación sería
legal. */
v_Rec1.Field1 := v_Rec2.Field1;
v_Rec2.Field2 := v_Rec2.Field2;
END;
/
PL/SQL I
VERSIÓN 1 JPV-99 48 / 67
TTAABBLLAASS EENN PPLL//SSQQLL
Las tablas en PL/SQL se asemejan a los arrays del lenguaje C.
Sintácticamente se las trata de la misma forma que a las matrices, aunque su
implementación es distinta.
DEFINICIÓN 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 definición.
♦ El máximo número de filas viene especificado por el número máximo de
valores que se pueden representar mediante el tipo BINARY_INTEGER.
IMPORTANTE
PL/SQL I
VERSIÓN 1 JPV-99 49 / 67
Dispone de control automático de asignación 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 número 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
VERSIÓN 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 en
v_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
VERSIÓN 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
VERSIÓN 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 posición 1 la cadena ‘Uno’
Insertar en la posición 3 la cadena ‘Tres
Insertar en la posición –2 la cadena ‘Menos dos’
Insertar en la posición 0 la cadena ‘Cero’
Insertar en la posición 100 la cadena ‘Cien’
Mostrar un mensaje con el número total de filas de la tabla
Elimina la fila de la posición 100
Mostrar un mensaje con el número de filas de la tabla
Borrar las filas desde la posición 1 a la 3
Mostrar un mensaje con el número de filas de la tabla
Borrar el elemento que se encuentre en la primera posición
Mostrar el contenido la última posición
Mostrar el contenido de la penúltima posición
Mostrar el contenido de la posición –1
Borrar toda la tabla
EJERCICIO
PL/SQL I
VERSIÓN 1 JPV-99 53 / 67
EJERCICIO 15
EJERCICIO SOBRE TABLAS DE REGISTROS
• Crear una tabla (en el núcleo) 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 comisión no
nula. Una vez realizada la carga del array se extraerán en orden inverso al
que fueron introducidos y se insertarán 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.
Sería 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 implícito.
EJERCICIO
PL/SQL I
VERSIÓN 1 JPV-99 54 / 67
8. SENTENCIAS TRANSACCIONALES
• Savepoint:
Marcas que pone el usuario durante la transacción para deshacer los cambios
por partes en vez de deshacer toda la transacción.
SAVEPOINT <nombre_del_punto_salvaguarda>;
• Commit:
Realiza todas las transacciones pendientes de la actual transacción
haciéndolas visibles para los demás usuarios.
COMMIT [WORK];
• Rollback:
Deshace todos los cambios pendientes de la transacción actual.
ROLLBACK [WORK] [ TO [SAVEPOINT] punto_salvaguarda; ]
♦ Una transacción 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 transacción termina con la orden COMMIT o ROLLBACK.
IMPORTANTE
PL/SQL I
VERSIÓN 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 comisión mayor que 350$ con un
incremento del 15% de su salario. Si la operación afecta a más de
tres empleados, deshacer la transacción, en cualquier otro caso
validar la transacción. Introducir en la tabla TEMP la operación que
se ha realizado.
PRÁCTICA
PL/SQL I
VERSIÓN 1 JPV-99 56 / 67
EJERCICIO 17
EJERCICIO SOBRE UTILIZACIÓN DE SENTENCIAS TRANSACCIONALES
• Crear un bloque PL/SQL que modifique el sal de los empleados que no
tienen comisión a 1000.
• Dentro del mismos bloque PL/SQL actualizar los empleados con una
comisión mayor de 350 $ con un incremento del 15% de su salario. Si la
operación afecta a más de tres empleados, deshacer la transacción, en
cualquier otro caso validar dicha transacción.
• Utilizar sólo un commit en el bloque PL/SQL.
PRÁCTICA
PL/SQL I
VERSIÓN 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 anónimo o del
procedimiento almacenado.
WHEN NOMBRE_EXCEPCION1 [OR NOMBRE_EXCEPCION2....]
THEN SENTENCIAS;
IMPORTANTE
La zona de excepciones no es obligatoria.
NOTA
PL/SQL I
VERSIÓN 1 JPV-99 58 / 67
DEFINIDAS POR EL USUARIO:
Mediante:
a) Exception_init, basadas en errores ORACLE
PRAGMA EXCEPTION_INIT (nombre_excepción, número_error);
b) Declarándola como excepción con el tipo de dato EXCEPTION en el DECLARE.
EEJJEECCUUCCIIÓÓNN DDEE EEXXCCEEPPCCIIOONNEESS
La ejecución de excepciones se produce:
• Automáticamente: Cuando ORACLE detecta un error, para el proceso y
pasa automáticamente 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_excepción>;
Nombre_excepción hay que definirlo antes con EXCEPTION.
El número de error es un sqlcode que no se halla definido para otra excepción
de Oracle , (p. Ej. NO DATA FOUND).
NOTA
PL/SQL I
VERSIÓN 1 JPV-99 59 / 67
FFUUNNCCIIOONNEESS
La función SQLCODE nos devuelve el número de error producido. Sólo tiene valor
cuando ocurre un error ORACLE
Sólo se habilita en la zona de excepciones.
La función 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: Creación de tabla donde almacenarlos:
Se puede emplear la función predefinida RAISE_APPLICATION_ERROR para
la creación de mensajes de error por parte del usuario.
Su sintaxis es:
RAISE_APPLICATION_ERROR (código, ‘Mensaje’).
Donde código es un número entre –20000 y –20999.
NOTA
PL/SQL I
VERSIÓN 1 JPV-99 60 / 67
REM
REM Creación 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
VERSIÓN 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 división–by–zero
INSERT INTO stats (symbol, ratio)
VALUES ('XYZ', pe_ratio);
COMMIT;
EXCEPTION -- COMIENZA EL BLOQUE DE EXCEPCIÓN
WHEN ZERO_DIVIDE THEN -- Maneja el error de división por cero
INSERT INTO stats (symbol, ratio)
VALUES ('XYZ', NULL);
COMMIT;
...
WHEN OTHERS THEN -- maneja todos los demás errores
ROLLBACK;
END; -- fin de las excepciones y del bloque.
/
PL/SQL I
VERSIÓN 1 JPV-99 62 / 67
CREACIÓN 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 sólo
tienes privilegios de consulta
-------------------------------------------------------
BEGIN
...
EXCEPTION
WHEN insufficient_privileges THEN
Maneja el error
...
END;
/
ELEVACIÓN DE MENSAJES DE ERROR PROPIOS DE USUARIO.
DECLARE
...
null_salary EXCEPTION;
/* Número de Error mapeado devuelto por raise_application_error
de una excepción definida por el usuario. */
PRAGMA EXCEPTION_INIT(null_salary, –20101);
PL/SQL I
VERSIÓN 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 excepción que se va
a llamar SOLO_UN_EMPLEADO mostrando un mensaje por pantalla.
• En el caso de recuperar más utilizaremos la excepción TOO_MANY_ROWS
y mostraremos un mensaje indicativo en la pantalla.
• En el caso de no recuperar ninguno utilizaremos las excepción
NO_DATA_FOUND y mostraremos el respectivo mensaje.
PRÁCTICA
PL/SQL I
VERSIÓN 1 JPV-99 64 / 67
10. RESUMEN
PL/SQL, (Procedural Language / SQL), es un lenguaje de programación
procedural estructurado en bloques que amplia la funcionalidad del lenguaje
standard SQL a través 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 métodos, (a partir de versión 8)
El Bloque PL/SQL es la unidad básica 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 implícito 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 más de una fila, permitiendo la lectura y manipulación de cada
una de ellas.
PL/SQL I
VERSIÓN 1 JPV-99 65 / 67
Declaración 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 definición.
El máximo número de filas viene especificado por el número máximo de
valores que se pueden representar mediante el tipo BINARY_INTEGER.
Una transacción 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 transacción 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 anónimo o del
procedimiento almacenado.
PL/SQL I
VERSIÓN 1 JPV-99 66 / 67
11. EVALUACIÓN
1 En PL/SQL, pueden incorporarse órdenes DDL
a) Siempre
b) Sólo a través de SQL Dinámico
c) Nunca
2 En un bloque PL/SQL, la declaracíon 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 daría 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 compilaría porque en la declaración no puede asignarse
una variable a un número
b) Mayor
c) Otro
PL/SQL I
VERSIÓN 1 JPV-99 67 / 67
4 La sentencia ROLLBACK sirve para:
a) Volver al bloque BEGIN / END anterior al que pertenece
b) Reenvía de nuevo la transacción al usuario
c) Deshace todos los cambios pendientes de la transacción actual
5 Defina bloque PL/SQL anónimo:
...............................................................................................................
...............................................................................................................
...............................................................................................................
...............................................................................................................
6 Definición y usos del tipo PLS_Integer:
...............................................................................................................
...............................................................................................................
...............................................................................................................
...............................................................................................................
7 Definición, usos y declaración de un cursor:
...............................................................................................................
...............................................................................................................
...............................................................................................................
...............................................................................................................
PL/SQL II
VERSIÓN 1 JPV-99 1 / 50
PPLL//SSQQLL IIII
Javier Pérez-Vigo (Octubre 1999)
PL/SQL II
VERSIÓN 1 JPV-99 2 / 50
INTRODUCCIÓN
En la unidad didáctica PL/SQL I se estudiaron los bloques PL/SQL
anónimos que se compilaban cada vez que eran ejecutados.
Las estructuras que se verán en esta unidad didáctica, (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 sólo puede contener órdenes DML y no DDL. Sin embargo esta
restricción se supera a partir de la versión 2.1 con el paquete
DBMS_SQL. Este paquete implementa código PL/SQL y SQL dinámico,
al que se llama desde otros bloques PL/SQL.
En el capítulo 4º de esta unidad se verá cómo utilizar el paquete
DBMS_SQL y sus implicaciones.
PL/SQL II
VERSIÓN 1 JPV-99 3 / 50
CONTENIDO:
1. PROCEDIMIENTOS Y FUNCIONES
PROCEDIMIENTOS
FUNCIONES
SUBPROGRAMAS LOCALES.
CONTROL DE PROCEDIMIENTOS Y FUNCIONES.
2. DESARROLLO Y UTILIZACIÓN DE PAQUETES
PAQUETES (PACKAGES)
FUNCIONES DENTRO DE PAQUETES.
3. DISPARADORES (TRIGGERS)
CONCEPTO DE DISPARADORES (TRIGGERS)
CREACIÓN DE DISPARADORES
CONCEPTO DE TABLA MUTANTE
4. PL/SQL DINÁMICO
CONCEPTO
MÉTODOS DE IMPLEMENTACIÓN
5. EJERCICIO DE DESARROLLO
6. RESUMEN
7. EVALUACIÓN
PL/SQL II
VERSIÓN 1 JPV-99 4 / 50
OBJETIVOS
El alumno tras el estudio de esta unidad didáctica podrá:
Conocer y utilizar los procedimientos y funciones almacenados a
través del lenguaje PL/SQL.
Crear y utilizar los paquetes, packages.
Conocer y utilizar los disparadores.
Entender los fundamentos del PL/SQL dinámico.
EXPECTATIVAS
• ··························································································································
························································································································
• ··························································································································
························································································································
• ··························································································································
························································································································
PL/SQL II
VERSIÓN 1 JPV-99 5 / 50
1. PROCEDIMIENTOS Y FUNCIONES
CONCEPTO DE PROCEDIMIENTOS Y FUNCIONES
Los bloques PL/SQL forman una estructura de bloques anónimos, 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 función 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 función pueden llamarse desde
multitud de lados: SQL*, Forms o cualquier otra herramienta ORACLE.
NOTA
PL/SQL II
VERSIÓN 1 JPV-99 6 / 50
PPRROOCCEEDDIIMMIIEENNTTOOSS
CREACIÓN 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
VERSIÓN 1 JPV-99 7 / 50
• Los tipos de los argumentos son: IN, OUT, IN OUT
Indican si el parámetro es de entrada, salida o ambos.
Si no se pone nada se supone que es IN.
• IS o AS llevan implícito el DECLARE, así que las variables se declaran
inmediatamente después de IS o AS.
• Un procedimiento termina con END o con END seguido del nombre del
procedimiento.
No puede haber declaración de argumentos, es decir, en las declaraciones de
tipo NUMBER, VARCHAR2 o DATE no puede figurar ni la escala ni la precisión.
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 sólamente CREATE, ya que de existir el
procedimiento en el núcleo podemos destruirlo.
NOTA
PL/SQL II
VERSIÓN 1 JPV-99 8 / 50
BORRADO
Para borrar un procedimiento se utiliza:
DROP PROCEDURE Nombre_procedimiento;
EJECUCIÓN
Los procedimientos (o funciones) que se declaran como locales a un bloque PL/SQL
se situarán 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
VERSIÓN 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 comisión 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 número de departamento es
el 20 se insertará en la tabla EMP con una comisión = 1000 y no se insertará
en la tabla EMPLEADOS. En cualquier otro caso introducir el empleado en
la tabla EMPLEADOS.
• Modificar el número de argumentos pasados al procedimiento añadiendo
uno que sea insertados el cual va a indicar el número de elementos que se
han insertado en la tabla empleados. Mostrar dicho número desde el bloque
PL/SQL con un mensaje.
PRÁCTICA
PL/SQL II
VERSIÓN 1 JPV-99 10 / 50
FFUUNNCCIIOONNEESS
CREACIÓN DE FUNCIONES
Utilizaremos la siguiente sentencia:
CREATE [OR REPLACE] FUNCTION nombre_función
[(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
VERSIÓN 1 JPV-99 11 / 50
• Como TIPO: IN, OUT, IN OUT
• Return de una función no lleva ni escala ni precisión.
• Return puede llevar expresiones.
• El tipo de dato no puede incluir escala o precisión.
• Una función puede tener más de un return.
• Si declaramos una sin return da un error.
BORRADO
Para borrar una función se utiliza:
DROP FUNCTION Nombre_procedimiento;
EJECUCIÓN
Los argumentos OUT o IN OUT son válidos dentro de las funciones pero se
usan raramente.
NOTA
♦ Una función 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
VERSIÓN 1 JPV-99 12 / 50
• Una función se puede invocar desde una sentencia SELECT, WHERE, HAVING,
cláusula 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 función dentro de una sentencia SQL:
• Debe de ser una función 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 están 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
VERSIÓN 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 función que nos permita realizar una consulta del salario del
empleado de la tabla EMP que se le pasa como parámetro desde SQL* (se
le pasa el número del empleado). Si la consulta ha sido satisfactoria la
función devuelve un SI, en caso contrario devuelve un NO.
• Utilizar desde el SQL para llamar a la función: dbms_output.put_line(‘¿Existe
el empleado?’||di_si_existe(&empleado));
PRÁCTICA
PL/SQL II
VERSIÓN 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 múltiplo 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 máximo jefe.
• Obtener su máximo jefe utilizando una función.
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 través de un procedimiento a partir del
cual se va a obtener el puesto que ocupa cada empleado en la empresa en
cuestión de salario + comisión.
• Utilizar un cursor para cargar la tabla.
PL/SQL II
VERSIÓN 1 JPV-99 15 / 50
CCOONNTTRROOLL DDEE PPRROOCCEEDDIIMMIIEENNTTOOSS YY FFUUNNCCIIOONNEESS..
DOCUMENTACIÓN DE PROCEDIMIENTOS Y FUNCIONES.
A través 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 través de la vista del diccionario de datos USER_SOURCE se puede obtener el
código de los siguientes elementos dentro de un esquema:
• FUNCTION
• PACKAGE
• PACKAGE BODY
• PROCEDURE
PL/SQL II
VERSIÓN 1 JPV-99 16 / 50
• Para visualizar el nombre de un procedimiento o función y su lista de argumentos
utilizaremos el comando DESCRIBE.
DESC[RIBE] Nombre_procedimiento o Nombre_función;
• Para mostrar el texto de los errores de compilación utilizaremos la vista
USER_ERRORS.
• Para visualizar los errores de compilación utilizaremos la siguiente sentencia:
SHOW ERRORS PROCEDURE o FUNCTION o PACKAGE o
PACKAGE BODY o TRIGGER nombre_objeto;
DEPURACIÓN DE PROCEDIMIENTOS Y FUNCIONES.
• Para activar este procedimiento utilizaremos la opción
SET SERVEROUTPUT ON
• Para preparar el texto del mensaje de salida se utiliza PUT.
DBMS_OUTPUT.PUT (Texto);
♦ Para la depuración de procedimientos y funciones se utiliza el
procedimiento suministrado por Oracle: DBMS_OUTPUT
IMPORTANTE
PL/SQL II
VERSIÓN 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 (opción más utilizada)
• Estos procedimientos están 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
VERSIÓN 1 JPV-99 18 / 50
Este sería el diagrama en el que se explica el funcionamiento del DBMS_OUTPUT:
La salida DBMS_OUTPUT es independiente para cada sesión.
NOTA
Para que no nos dé un error debido a que el buffer es muy pequeño, conviene
inicializarlo mediante el comando:
SET SERVEROUTPUT ON size 1000000
NOTA
PL/SQL II
VERSIÓN 1 JPV-99 19 / 50
2. DESARROLLO Y UTILIZACIÓN DE PAQUETES
PPAAQQUUEETTEESS ((PPAACCKKAAGGEESS))
Estructura de un paquete:
PÚBLICA
Variable Pública
Declaración del Procedimiento A
Procedimiento Público
Variable Privada
Definición del Procedimiento B
Definición del Procedimiento A
Variable local
Procedimiento Privado
Procedimiento Público
PRIVADA
PACKAGE
PACKAGE
BODY
Zona de Especificación
Cuerpo del paquete
♦ Un paquete es un grupo de identificadores y rutinas agrupadas dentro de la
misma construcción.
IMPORTANTE
PL/SQL II
VERSIÓN 1 JPV-99 20 / 50
CREACIÓN DE PAQUETES
Para crear un paquete:
CREATE [OR REPLACE] PACKAGE Nombre_paquete IS O AS
Declaración variable
Declaración cursor
Declaración excepción
Declaración procedimiento
Declaración función
END Nombre_paquete
Para la creación del cuerpo del paquete:
CREATE [OR REPLACE] PACKAGE BODY Nombre_paquete IS O AS
Declaración variable
Declaración cursor
Declaración excepción
Código del procedimiento
Código de la función
[BEGIN Código de inicialización del paquete]
END Nombre_paquete
• Para borrar un paquete y el cuerpo del paquete se utiliza.
DROP PACKAGE Nombre_paquete
PL/SQL II
VERSIÓN 1 JPV-99 21 / 50
• Para borrar el cuerpo del paquete se utiliza.
DROP PACKAGE BODY Nombre_paquete
• Para invocar un procedimiento o función 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_función ó
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
VERSIÓN 1 JPV-99 22 / 50
• Los packages disponen de la opción de sobrecarga de procedimientos y funciones,
es decir, con el mismo nombre y distintos argumentos.
No se pueden sobrecargar si difieren sólo en el modo (IN OUT).
No se pueden sobrecargar si difieren sólo en el tipo de dato devuelto.
No se pueden sobrecargar si difieren sólo en la familia del tipo de dato.
NOTA
DECLARE
FUNCTION value_ok (date_in IN DATE)
RETURN BOOLEAN IS
BEGIN
RETURN date_in <= SYSDATE; Date Version
END;
FUNCTION value_ok (num_in IN NUMBER)
RETURN BOOLEAN IS
BEGIN
RETURN number_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
VERSIÓN 1 JPV-99 23 / 50
• Podemos cambiar el cuerpo sin cambiar la cabecera.
Si cambiamos la cabecera y no el cuerpo éste queda inválido, siendo necesario
volver a compilarlo.
• Para compilar los objetos inválidos 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 depuración de una función dentro de un paquete
cuando se crea un paquete (en la especificación).
• El nivel de depuración determina qué operaciones no van a ser realizadas por la
función del paquete.
• No se puede utilizar una función que está dentro de un paquete en una sentencia
SQL. Es necesario indicar el nivel de depuración.
PL/SQL II
VERSIÓN 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 especificación del paquete detrás de todas las
funciones.
El argumento WNDS debe indicarse SIEMPRE que se utilice
RESTRICT_REFERENCES.
WNDS -> (Writes No Database State) Indica que la función no va
modificar tablas de la base de datos
WNPS -> (Writes No Package Status) Indica que la función no va a
cambiar los valores de variables de un paquete público.
RNDS -> (Reads No Database State) Indica que la función no va
aconsultar ninguna tabla de la base de datos.
RNPS-> (Reads No Package Status) Indica que la función no va a
referenciar los valores de las variables de un paquete público.
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
VERSIÓN 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
VERSIÓN 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 trataría de recuperar desde un bloque PL/SQL los elementos de la tabla
EMP cuya suma de su salario + comisión > 2000 e ir introduciéndolos en la
tabla del paquete recién creado a partir de la función pr_insertar.
• Consultar desde el bloque PL/SQL el índice del paquete y obtener el número
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 función, 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 función desde SQL*.
• La función fu_inicializa borra la tabla y pone el índice a 0.
PRÁCTICA
PL/SQL II
VERSIÓN 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 número me va a devolver el salario de la persona
que se encuentra en la posición 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 número 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
pública) las personas con una antigüedad mayor que la pasada
como parámetro de forma ordenada por fecha . Se trata de una
tabla de registros con los campos Nombre, antigüedad. Extraer
cada uno de esos empleados de la tabla, visualizando el nombre
del empleado y el número de días que lleva en la empresa.
EJERCICIO 10
• Ampliar el primer paquete creado con la función 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 comisión sea mayor que el valor devuelto por la función
fu_media_comision.
PL/SQL II
VERSIÓN 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 implícitamente cuando se ejecuta una sentencia de
manipulación 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. (Común en desnormalizaciones).
En la auditoría de la información contenida en la tabla, registrando los cambios
realizados y la identidad de quien lo llevó a cabo.
El aviso automático a otros programas de que hay que llevar a cabo una
determinada acción, 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 instrucción SQL se va a ejecutar sobre dicha
tabla.
IMPORTANTE
PL/SQL II
VERSIÓN 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 través de la vista del diccionario
de datos USER_TRIGGERS.
Clasificación:
Según el momento en el que salta el disparador
*BEFORE
* AFTER
Según el tipo de operación que provoca su actuación
* INSERT
* UPDATE
* DELETE
Según las veces que se ejecuta el cuerpo del disparador
* Sentencia
* Fila
En la figura de abajo se disparan los triggers para la operación que contiene la
cláusula WHERE: WHERE ENAME LIKE 'J%':
• Dentro de un disparador están prohibidas sentencias transaccionales:
COMMIT, ROLLBACK y SAVEPOINT.
NOTA
PL/SQL II
VERSIÓN 1 JPV-99 30 / 50
• Para borrar un trigger utilizaremos:
DROP TRIGGER Nombre_trigger
CCRREEAACCIIÓÓNN 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 Condición_restricción]
[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 inserción el valor antiguo es NULL, durante el borrado el valor nuevo es
NULL.
• El cualificador :NEW puede aparecer a la izquierda de una asignación en el cuerpo
PL/SQL solamente en disparadores de fila BEFORE. No puede aparecer en la
PL/SQL II
VERSIÓN 1 JPV-99 31 / 50
parte izquierda de una asignación 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 asignación.
ACTIVACIÓN 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 compilación, 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 sintácticamente 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
VERSIÓN 1 JPV-99 32 / 50
ORDEN DE EJECUCIÓN DE LOS DISPARADORES
Los disparadores se ejecutan según 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 modificación sobre la misma tabla. Esto
provoca que la tabla quede mutante por la incosistencia de la información en ese
instante y da un error por pantalla.
♦ Una tabla mutante es una tabla que está modificándose actualmente por
una orden DML (INSERT, UPDATE, DELETE).
Para un disparador, ésta es la tabla sobre la que está definido.
IMPORTANTE
PL/SQL II
VERSIÓN 1 JPV-99 33 / 50
La solución del error de la tabla mutante consistiría 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 utilizarán los valores almacenados
por el disparador de sentencia:
BEFORE -> Inicializa
BEFORE EACH ROW -> Almacena
AFTER -> Procesa
Si una operación INSERT afecta a una única fila, entonces los disparadores de
fila previo y posterior por dicha fila no tratarán 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
VERSIÓN 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 más 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 número de departamento, compruebe
que este número sea múltiplo de diez.
PRÁCTICA
PL/SQL II
VERSIÓN 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 operación sobre la tabla EMP (inserción, modificación,borrado),
realice una inserción 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 máximo y el mínimo 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 más 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
VERSIÓN 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 comisión no sea mayor que la
del jefe con menor comisión.
• 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
VERSIÓN 1 JPV-99 37 / 50
4. PL/SQL DINÁMICO
CCOONNCCEEPPTTOO
Mediante el DBMS_SQL podemos manejar también órdenes DML.
Las órdenes SQL Dinámicas tienen muy pocas restricciones, porque si se desea, la
orden completa SQl se puede determinar en el momento de la ejecución, en lugar de
en la compilación.
Desventajas:
• El SQL Dinámico no se ejecuta con la misma eficiencia que el estático.
• Aquellas tablas a las que se hace referencia no aparecerán en
USER_DEPENDENCES.
♦ El PL/SQL dinámico 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 dinámicamente surge al
hacer referencia a una tabla, que se creará en ejecución; por lo que si la orden
que la refiere estuviera en SQL estático, no compilaría.
NOTA
PL/SQL II
VERSIÓN 1 JPV-99 38 / 50
• Cuando se borra una tabla dinámicamente, es labor del usuario el cambiar el
estado de los paquetes que hagan referencia a dicha tabla.
PROCEDIMIENTOS DE SQL DINÁMICO:
• Función 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
• Función DBMS_SQL.IS_OPEN (c IN INTEGER) RETURN BOOLEAN;
Comprueba si el cursor ya está abierto.
• Procedure DBMS_SQL.BIND_VARIABLE
(cursor IN INTEGER, ‘:variable_usada’ IN VARCHAR2,
dato a incluir IN <datatype>);
Asigna las variables a la sentencia.
• Procedure DBMS_SQL.DEFINE_COLUMN
(cursor IN INTEGER, position_en_la_select_de_la_columna IN INTEGER,
columna_variable IN <column_datatype>);
Tipos de datos de las columnas para crear variables locales.
• Función DBMS_SQL.EXECUTE (cursor IN INTEGER) RETURN INTEGER;
Ejecuta la sentencia asociada al cursor.
• FUNCTION DBMS_SQL.FETCH_ROWS
PL/SQL II
VERSIÓN 1 JPV-99 39 / 50
(cursor IN INTEGER) RETURN INTEGER;
Recoge la siguiente fila del cursor
• PROCEDURE DBMS_SQL.COLUMN_VALUE
(cursor IN INTEGER, posicion IN INTEGER, valor OUT <datatype>,
[, column_error OUT NUMBER]
[, actual_length OUT INTEGER ]);
Introduce el valor del cursor en variables locales
• PROCEDURE DBMS_SQL.CLOSE_CURSOR
(cursor IN OUT INTEGER);
Cierra el cursor.
MMÉÉTTOODDOOSS DDEE IIMMPPLLEEMMEENNTTAACCIIÓÓNN
♦ Existen varios métodos distintos de implementar SQL Dinámico:
• Ejecución de órdenes DML
• Ejecución de órdenes DDL que no sean consultas
• Ejecución de consultas
IMPORTANTE
PL/SQL II
VERSIÓN 1 JPV-99 40 / 50
EJECUCIÓN DE ÓRDENES DML
Estructura de la orden:
• Abir el cursor (OPEN_CURSOR)
• Analizar la orden (PARSE)
• Cerrar el cursor (CLOSE_CURSOR)
DECLAREt_owner varchar2(30) := 'ACADEMIA';
CURSOR all_obj_cur IS
SELECT table_name ,trigger_name
FROM user_triggers
WHERE STATUS='DISABLED'
order by table_name,trigger_name;
disable_cursor INTEGER;
out_str VARCHAR2(1000);
BEGIN
FOR obj_rec IN all_obj_cur
LOOP
disable_cursor := DBMS_SQL.OPEN_CURSOR;
out_str := 'ALTER TRIGGER ' || obj_rec.trigger_name
|| ' ENABLE';
DBMS_SQL.PARSE (disable_cursor, out_str,
DBMS_SQL.NATIVE);
DBMS_SQL.CLOSE_CURSOR (disable_cursor);
END LOOP;
END;
/
PL/SQL II
VERSIÓN 1 JPV-99 41 / 50
CREATE OR REPLACE PROCEDURE UpdateSal(
p_Department IN emp.deptno%TYPE,
p_NewSal IN emp.sal%TYPE,
p_RowsUpdated OUT INTEGER) AS
v_CursorID INTEGER;
v_UpdateStmt VARCHAR2(100);
BEGIN
-- Open the cursor for processing.
v_CursorID := DBMS_SQL.OPEN_CURSOR;
--Determine the SQL string.
v_UpdateStmt :=
'UPDATE emp
SET sal = :nc
WHERE deptno = :dept';
--Parse the statement.
DBMS_SQL.PARSE(v_CursorID, v_UpdateStmt,
DBMS_SQL.V7);
--Bind p_NewSal to the placeholder :nc.
EJECUCIÓN DE ÓRDENES DDL QUE NO SEAN CONSULTAS
Estructura de la orden:
• Abir el cursor (OPEN_CURSOR)
• Analizar la orden (PARSE)
• Acoplar todas las variables de entrada (BIND_VARIABLE)
• Ejecutar la orden (EXECUTE)
• Cerrar el cursor (CLOSE_CURSOR)
PL/SQL II
VERSIÓN 1 JPV-99 42 / 50
EJECUCIÓN DE CONSULTAS
Estructura de la orden:
• Abir el cursor (OPEN_CURSOR)
• Analizar la orden (PARSE)
• Acoplar todas las variables de entrada (BIND_VARIABLE)
• Definir las variables de salida (DEFINE_COLUMN)
• Ejecutar la consulta (EXECUTE)
• Extraer las filas (FETCH_ROWS)
• Devolver los resultados a variables (COLUMN_VALUE)
• Cerrar el cursor (CLOSE_CURSOR)
DBMS_SQL.BIND_VARIABLE(v_CursorID, ':nc', p_NewSal);
--Bind p_Department to the placeholder :dept.
DBMS_SQL.BIND_VARIABLE(v_CursorID, ':dept',
p_Department);
-- Execute the statement.
p_RowsUpdated := DBMS_SQL.EXECUTE(v_CursorID);
-- Close the cursor.
DBMS_SQL.CLOSE_CURSOR(v_CursorID);
EXCEPTION
WHEN OTHERS THEN
-- Close the cursor, then raise the error again.
DBMS_SQL.CLOSE_CURSOR(v_CursorID);
RAISE;
END UpdateSal;
/
PL/SQL II
VERSIÓN 1 JPV-99 43 / 50
CREATE OR REPLACE FUNCTION obtener_nombre
(empno_in IN emp.empno%TYPE)
RETURN VARCHAR2
IS
cur INTEGER;
out_str varchar2(1000);
fdbk INTEGER;
return_value emp.ename%TYPE := NULL;
BEGIN
cur := DBMS_SQL.OPEN_CURSOR;
out_str := ('SELECT ename FROM emp WHERE empno = :id');
DBMS_SQL.PARSE (cur, out_str, DBMS_SQL.NATIVE);
/* Define the first/only column as a string. */
DBMS_SQL.DEFINE_COLUMN (cur, 1, return_value, 100);
/* Bind the specified contact ID into the SELECT. */
DBMS_SQL.BIND_VARIABLE (cur, 'id', empno_in);
/* Execute and fetch from the cursor. */
fdbk := DBMS_SQL.EXECUTE (cur);
fdbk := DBMS_SQL.FETCH_ROWS (cur);
/* Fetch the row. If feedback is 0, no match found */
IF fdbk = 1
THEN
/* A record was fetched. Retrieve the name. */
DBMS_SQL.COLUMN_VALUE (cur, 1, return_value);
END IF;
DBMS_SQL.CLOSE_CURSOR (cur);
RETURN return_value;
END obtener_nombre;
/
PL/SQL II
VERSIÓN 1 JPV-99 44 / 50
Procurar siempre cerrar todos los cursores una vez ejecutada la sentencia,
incluso a través de las excepciones.
NOTA
No utilice comentario especificados con – dentro de un bloque PL/SQL
ejecutado con DBMS_SQL.
El símbolo de doble guión hace que se considere como comentario todo lo que
sigue, hasta encontrar un carácter de avance de linea. Sin embargo, dado que
el bloque completo se encuentra en una cadena, todo el resto del bloque sería
considerado un comentario.
Utilice los comentarios de estilo C delimitados por /* y */ en su lugar.
NOTA
PL/SQL II
VERSIÓN 1 JPV-99 45 / 50
EJERCICIO SOBRE CURSORES DINÁMICOS
EJERCICIO 17
• Desactivar todas las constraints de la base de datos teniendo en cuenta que
en primer lugar hay que desactivar las Primary y Unique y en segundo lugar
las Foreign y Check constraints.
NOTA: La notación del campo CONSTRAINT_TYPE es la siguiente:
P Primary Key
U Unique Key
R Foreign Key
C Check constraint
• Crear el procedimiento contrario siguiendo el orden inverso.
EJERCICIO 18
• Crear un procedimiento que nos obtenga dinámicamente el nombre del
departamento y la localización del número del departamento que le
pasemos.
EJERCICIO 19
• Codificar un procedimiento que cree una tabla copia de la de empleado y a
través de un parámetro en que le pasamos el nombre del empleado, copiar
los datos del empleado requerido en la nueva tabla.
PRÁCTICA
PL/SQL II
VERSIÓN 1 JPV-99 46 / 50
5. EJERCICIO DE DESARROLLO
1.-Crear una tabla TMP+Nombre_usuario que sea una copia de la de Empleado
1.1- Añadirle los campos Usuario y Fecha modificación.
1.2- Crear un disparador que audite el usuario y la fecha en que se
inserta o se modifica dicha tabla.
2.- Mediante un cursor Modificar dicha tabla y subir el sueldo a los empleados
que pertenezcan al departamento SALES
3.- Crear una función que devuelva la media de sueldo de los empleados que
tengan el mismo puesto (JOB) pasándole como parámetro en formato texto
dicho cargo.
4.- Crear un disparador tal que cuando modifiquemos el sueldo del presidente,
se encargue de recalcular el resto de los sueldos de todos los empleados en el
mismo porcentaje.
5.- Crear un procedimiento que actualice la fecha HIREDATE al primer día del
siguiente mes del día de la semana que coincida con la fecha anterior.
6.- Crear un procedimiento dinámico que borre todos los objetos de la base de
datos del tipo que nosotros le pasemos como parámetro del usuario que está
conectado.
Si no se le pasa ningún parámetro, debe borrar todos. (Excepto el propio
procedimiento creado).
PL/SQL II
VERSIÓN 1 JPV-99 47 / 50
6. RESUMEN
Un procedimiento es un conjunto de instrucciones PL/SQL que puede ser
llamado usando el nombre que se le haya asignado.
Una función 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.
Un procedimiento se invoca con la sentencia EXEC[UTE] desde SQL*.
Desde un bloque PL/SQL simplemente es necesario nombrarlo para
ejecutarlo.
Una función 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.
Los subprogramas se incluyen en el DECLARE del bloque y es necesario
incluir el subprograma entero.
Para la depuración de procedimientos y funciones se utiliza el
procedimiento suministrado por Oracle: DBMS_OUTPUT
Un paquete es un grupo de identificadores y rutinas agrupadas dentro de la
misma construcción.
PL/SQL II
VERSIÓN 1 JPV-99 48 / 50
Un disparador es un bloque PL/SQL asociado a una tabla que se ejecuta
cuando una determinada instrucción SQL se va a ejecutar sobre dicha
tabla.
Una tabla mutante es una tabla que está modificándose actualmente por
una orden DML (INSERT, UPDATE, DELETE).
Para un disparador, ésta es la tabla sobre la que está definido.
El PL/SQL dinámico nace de la necesidad de implementar órdenes DDL
dentro de un bloque de PL/SQL.
Se implementa en el paquete DBMS_SQL
Existen varios métodos distintos de implementar SQL Dinámico:
Ejecución de órdenes DML
Ejecución de órdenes DDL que no sean consultas
Ejecución de consultas
PL/SQL II
VERSIÓN 1 JPV-99 49 / 50
7. EVALUACIÓN
1. Para ejecutar un procedimiento desde SQLPLUS utilizaremos la sentencia:
a) START procedimiento
b) EXEC procedimiento
c) RUN procedimiento
2. ¿Cual de estas sentencias es incorrecta?
a) Las funciones no pueden llevar argumentos, sólo devuelven valores
b) Los procedimientos pueden llevar parámetros IN y OUT
c) Las funciones PL/SQl que están dentro de sentencias SQL no
pueden modificar datos en las tablas.
3. ¿Cual de estas sentencias es incorrecta?
a) La sobrecarga de los packages surge a partir del décimo
procedimiento
b) Los packages disponen de la opción de sobrecarga de
procedimientos y funciones
c) Para que no haya sobrcarga en un package debemos indicar en la
cabecera el nivel de depuración
PL/SQL II
VERSIÓN 1 JPV-99 50 / 50
4. Un disparador ..
a) Permite argumentos
b) No permite sentencias transaccionales (Commit, rollback…)
c) Permite ejecutarse desde un procedimiento mediante la orden EXEC
TRIGGER nombre_de_trigger
5. Una tabla mutante es:
a) Una tabla que se altera cuando dos usuarios modifican los datos de
una tabla a la vez.
b) Una tabla que se está modificándose actualmente por una orden
DML debido a un trigger FOR_EACH_ROW
c) Un tabla que se modifica porque un usuario ejecuta un procedimiento
a la vez que otro ejecuta una sentencia DML
6. ¿Qué tipo de error puede dar lugar en un cursor?
a) NO_DATA_FOUND
b) TOO_MANY_ROWS
c) VALUE_ERROR
ANEXOS A CURSO PL/SQL
VERSIÓN 1 JPV- 99 1 / 49
AANNEEXXOOSS AA CCUURRSSOO PPLL//SSQQLL
Javier Pérez-Vigo (Octubre 1999)
ANEXOS A CURSO PL/SQL
VERSIÓN 1 JPV- 99 2 / 49
AANNEEXXOO 11:: SSQQLL**PPLLUUSS
La herramienta que nos proporciona ORACLE para interactuar con la base de datos se llama
SQL*Plus. Básicamente, es un intérprete SQL con algunas opciones de edición y formateo de
resultados.
Conceptos previos antes de conectarse a SQL*Plus:
• Usuario/Clave
Para poder acceder a una base de datos gestionada por ORACLE debemos ser
un usuario autorizado de la misma y conocer la palabra clave, password, asociada
al usuario.
• Variable de ambiente ORACLE_SID
Indica la base de datos con la que vamos a trabajar.
11 CCOONNEEXXIIÓÓNN
Para entar en SQL*Plus se debe ejecutar el comando
$ sqlplus usuario/passwd
donde le indicamos al SGBD Oracle quién somos y nuestra palabra clave.
Si la configuración del SGBD Oracle se corresponde a una configuración cliente-servidor
asentada sobre una red (SQL*Net v2) deberemos indicar, además, el sevicio (o base de
datos) con el que queremos contactar. Esto se hace colocando el símbolo @ antes del
nombre del servicio como se indica a continuación:
$ sqlplus usuario/passwd@servicio
Otra circunstancia que hay que tener en cuenta a la hora de conectarnos a SQL*Plus es el
modo establecido por el DBA para la autentificación del usuario de la base de datos. La
primera posibilidad es que recaiga sobre el SGBD Oracle la autentificación de los usuarios,
por lo que tendremos que darle nuestro nombre de usuario y la palabra de paso. Pero existe
la posibilidad de que el SGBD Oracle deje en manos del Sistema Operativo esta
responsabilidad. Así, no será necesario demostrarle al SGBD Oracle quién somos ya que el
SO se ha encargado previamente de comprobar que todo es correcto. En este segundo caso,
el comando de conexión con SQL*Plus debe omitir el nombre de usuario y la palabra clave,
pero manteniendo el resto de esta manera:
$ sqlplus /@servicio
ANEXOS A CURSO PL/SQL
VERSIÓN 1 JPV- 99 3 / 49
Una vez que hemos conseguido entrar en SQL*Plus nos presenta el prompt y espera la
insercción de sentencias SQL. Todas las sentencias deben acabar con un ';'. Una sentencia
puede continuar en varias líneas, que SQL*Plus va numerando. Si queremos anular la
sentencia actual podemos hacerlo colocando un '.' como único carácter en una línea. Si
queremos volver a ejecutar la última sentencia se puede hacer con el comando '/'. Si
queremos ejecutar las sentencias que almacena un fichero .sql podemos hacerlo
anteponiendo el símbolo '@' al nombre del fichero.
Para cerrar la sesión vale con teclear 'exit'.
22 PPOOSSIIBBIILLIIDDAADDEESS DDEE EEDDIICCIIÓÓNN
SQL*Plus almacena en un buffer la última sentencia SQL introducida. El buffer mantiene sólo
una sentencia cada vez, y si se introduce una nueva sentencia se sobreescribe sobre la
anterior.
La sentencia en el buffer puede ser recuperada para ejecutarla de nuevo con los comandos:
• RUN que visualiza la sentencia en el buffer antes de ejecutarla;
• / que ejecuta la sentencia sin visualizarla.
SQL*Plus también nos permite editar la sentencia SQL alamacenada en el buffer mediante un
sencillo (y limitado) editor en línea, cuyos comandos se enumeran a continuación:
Comando Abreviatura Descripción
APPEND texto A texto Añade texto al final de la línea.
CHANGE/fuente/destino C/fuente/destino Cambia el contenido 'fuente' por el 'destino'
CHANGE/texto C/texto Quita 'texto' de una línea.
CLEAR BUFFER CL BUFF Borra el buffer
DEL DEL Borra una línea.
INPUT I Inserta una o más líneas.
INPUT texto I texto Inserta una línea con 'texto'.
LIST L Lista las líneas del buffer
LIST n L n ó n Lista la línea n-ésima.
LIST * L * Lista la línea actual.
LIST LAST L LAST Lista la última línea.
LIST m n L m n Lista las líneas desde la m-ésima a la n-ésima.
Al contenido del buffer también se puede acceder desde el editor del Sistema Operativo. Así,
el buffer podrá ser manipulado con las posibilidades del editor con el que estemos
ANEXOS A CURSO PL/SQL
VERSIÓN 1 JPV- 99 4 / 49
acostumbrados a trabajar. Al salir del editor se devuelve el control al SQL*Plus. Para
conseguir trabajar con el editor del Sistema Operativo basta con colocar la variable
DEFINE_EDITOR y luego llamar al editor.
SQL> define_editor=vi
SQL> edit
33 UUTTIILLIIZZAACCIIÓÓNN DDEE FFIICCHHEERROOSS
SQL*Plus considera dos tipos de ficheros: de spool y de comandos.
Un fichero de spool almacena los resultados de una consulta (o varias) en un fichero con la
extensión .lst (o lo manda a la impresora).
Los comandos asociados con los ficheros spool son
SPOOL fichero
Manda el resultado de las consultas al fichero.
SPOOL OUT
Manda el resultado de las consultas a la impresora.
SPOOL OFF
Cierra el fichero de spool.
EXIT
Al salir de SQL*Plus se cierran los ficheros de spool.
Los archivos de comandos almacenan comandos SQL y SQL*Plus para ser editado,
almacenado y/o ejecutado; y tienen por defecto la extensión .sql :
• Para editarlo se puede utilizar el comando edit fichero.
• Para ejecutarlo se utilizará el comando START fichero o @fichero
44 AALLMMAACCEENNAAMMIIEENNTTOO YY RREECCUUPPEERRAACCIIÓÓNN DDEE FFIICCHHEERROOSS DDEE
CCOOMMAANNDDOOSS
Un fichero de comandos es una secuencia de órdenes SQL y SQL*Plus almacenados en un
fichero del sistema operativo.
• Comando SAVE: Almacena en un fichero en disco el contenido del búffer activo.
SAVE nombre_fichero [APPEND|CREATE|REPLACE]
• Comando GET: Para recuperar un fichero de comandos.
GET nombre_fichero [LIST|NOLIST]
Introducción a PL/SQL
Introducción a PL/SQL
Introducción a PL/SQL
Introducción a PL/SQL
Introducción a PL/SQL
Introducción a PL/SQL
Introducción a PL/SQL
Introducción a PL/SQL
Introducción a PL/SQL
Introducción a PL/SQL
Introducción a PL/SQL
Introducción a PL/SQL
Introducción a PL/SQL
Introducción a PL/SQL
Introducción a PL/SQL
Introducción a PL/SQL
Introducción a PL/SQL
Introducción a PL/SQL
Introducción a PL/SQL
Introducción a PL/SQL
Introducción a PL/SQL
Introducción a PL/SQL
Introducción a PL/SQL
Introducción a PL/SQL
Introducción a PL/SQL
Introducción a PL/SQL
Introducción a PL/SQL
Introducción a PL/SQL
Introducción a PL/SQL
Introducción a PL/SQL
Introducción a PL/SQL
Introducción a PL/SQL
Introducción a PL/SQL
Introducción a PL/SQL
Introducción a PL/SQL
Introducción a PL/SQL
Introducción a PL/SQL
Introducción a PL/SQL
Introducción a PL/SQL
Introducción a PL/SQL
Introducción a PL/SQL
Introducción a PL/SQL
Introducción a PL/SQL
Introducción a PL/SQL
Introducción a PL/SQL

Más contenido relacionado

La actualidad más candente

Concepto de semáforo, exclusión mutua y sección critica.
Concepto de semáforo, exclusión mutua y sección critica.Concepto de semáforo, exclusión mutua y sección critica.
Concepto de semáforo, exclusión mutua y sección critica.Uriel Martinez Cervantes
 
Sesion06b - Introducción al PL-SQL (Oracle)
Sesion06b - Introducción al PL-SQL (Oracle)Sesion06b - Introducción al PL-SQL (Oracle)
Sesion06b - Introducción al PL-SQL (Oracle)José Toro
 
Curso Básico de Pl Sql Oracle
Curso Básico de Pl Sql OracleCurso Básico de Pl Sql Oracle
Curso Básico de Pl Sql Oracleluisguil
 
Sesion05 - Manipulacion de datos (Oracle)
Sesion05 - Manipulacion de datos (Oracle)Sesion05 - Manipulacion de datos (Oracle)
Sesion05 - Manipulacion de datos (Oracle)José Toro
 
Sesion10 - Funciones y procedimientos (Oracle)
Sesion10 - Funciones y procedimientos (Oracle)Sesion10 - Funciones y procedimientos (Oracle)
Sesion10 - Funciones y procedimientos (Oracle)José Toro
 
Tc4 diagramas bloque
Tc4 diagramas bloqueTc4 diagramas bloque
Tc4 diagramas bloqueMario Blass
 
Iv unidad estructuras de control
Iv unidad estructuras de controlIv unidad estructuras de control
Iv unidad estructuras de controlmariaisabelg
 
Introduccion matlab
Introduccion matlabIntroduccion matlab
Introduccion matlabgrupo6eda
 
Sesion07- Estructuras de control (Oracle)
Sesion07- Estructuras de control (Oracle)Sesion07- Estructuras de control (Oracle)
Sesion07- Estructuras de control (Oracle)José Toro
 
01-declaracion-de-variables
01-declaracion-de-variables01-declaracion-de-variables
01-declaracion-de-variablesUAL
 
Sesion08 - Cursores (Oracle)
Sesion08 - Cursores (Oracle)Sesion08 - Cursores (Oracle)
Sesion08 - Cursores (Oracle)José Toro
 
Sistemas Operativos - Semáforos
Sistemas Operativos - SemáforosSistemas Operativos - Semáforos
Sistemas Operativos - SemáforosJuan Rojas
 
Instrucciones basicas de_c_
Instrucciones basicas de_c_Instrucciones basicas de_c_
Instrucciones basicas de_c_EspitiaGiancarlo
 
Asignación de Polos y Predictor de Smith
Asignación de Polos y Predictor de SmithAsignación de Polos y Predictor de Smith
Asignación de Polos y Predictor de SmithPaolo Castillo
 

La actualidad más candente (19)

Concepto de semáforo, exclusión mutua y sección critica.
Concepto de semáforo, exclusión mutua y sección critica.Concepto de semáforo, exclusión mutua y sección critica.
Concepto de semáforo, exclusión mutua y sección critica.
 
Sesion06b - Introducción al PL-SQL (Oracle)
Sesion06b - Introducción al PL-SQL (Oracle)Sesion06b - Introducción al PL-SQL (Oracle)
Sesion06b - Introducción al PL-SQL (Oracle)
 
Curso Básico de Pl Sql Oracle
Curso Básico de Pl Sql OracleCurso Básico de Pl Sql Oracle
Curso Básico de Pl Sql Oracle
 
Sesion05 - Manipulacion de datos (Oracle)
Sesion05 - Manipulacion de datos (Oracle)Sesion05 - Manipulacion de datos (Oracle)
Sesion05 - Manipulacion de datos (Oracle)
 
Sesion10 - Funciones y procedimientos (Oracle)
Sesion10 - Funciones y procedimientos (Oracle)Sesion10 - Funciones y procedimientos (Oracle)
Sesion10 - Funciones y procedimientos (Oracle)
 
Lumisaca hector bdii_t7
Lumisaca hector bdii_t7Lumisaca hector bdii_t7
Lumisaca hector bdii_t7
 
Tc4 diagramas bloque
Tc4 diagramas bloqueTc4 diagramas bloque
Tc4 diagramas bloque
 
Iv unidad estructuras de control
Iv unidad estructuras de controlIv unidad estructuras de control
Iv unidad estructuras de control
 
Introduccion matlab
Introduccion matlabIntroduccion matlab
Introduccion matlab
 
Sesion07- Estructuras de control (Oracle)
Sesion07- Estructuras de control (Oracle)Sesion07- Estructuras de control (Oracle)
Sesion07- Estructuras de control (Oracle)
 
Curso de pl sql básico
Curso de pl sql básicoCurso de pl sql básico
Curso de pl sql básico
 
Guía Práctica de Diagramas de Flujo
Guía Práctica de Diagramas de FlujoGuía Práctica de Diagramas de Flujo
Guía Práctica de Diagramas de Flujo
 
01-declaracion-de-variables
01-declaracion-de-variables01-declaracion-de-variables
01-declaracion-de-variables
 
Estructuras
EstructurasEstructuras
Estructuras
 
Dig2 i
Dig2 iDig2 i
Dig2 i
 
Sesion08 - Cursores (Oracle)
Sesion08 - Cursores (Oracle)Sesion08 - Cursores (Oracle)
Sesion08 - Cursores (Oracle)
 
Sistemas Operativos - Semáforos
Sistemas Operativos - SemáforosSistemas Operativos - Semáforos
Sistemas Operativos - Semáforos
 
Instrucciones basicas de_c_
Instrucciones basicas de_c_Instrucciones basicas de_c_
Instrucciones basicas de_c_
 
Asignación de Polos y Predictor de Smith
Asignación de Polos y Predictor de SmithAsignación de Polos y Predictor de Smith
Asignación de Polos y Predictor de Smith
 

Destacado

LEÇON 74 – Il n’est de volonté que Celle de Dieu.
LEÇON 74 – Il n’est de volonté que Celle de Dieu.LEÇON 74 – Il n’est de volonté que Celle de Dieu.
LEÇON 74 – Il n’est de volonté que Celle de Dieu.Pierrot Caron
 
How to Use Search Data to Build Content That Drives Value at Scale
How to Use Search Data to Build Content That Drives Value at ScaleHow to Use Search Data to Build Content That Drives Value at Scale
How to Use Search Data to Build Content That Drives Value at ScaleGrant Simmons
 
Convidar os pobres e estropiados - Cap. XIII - ESE
Convidar os pobres e estropiados - Cap. XIII - ESEConvidar os pobres e estropiados - Cap. XIII - ESE
Convidar os pobres e estropiados - Cap. XIII - ESEFernanda Florian
 
Economía Petrolera venezolana
Economía Petrolera venezolanaEconomía Petrolera venezolana
Economía Petrolera venezolanaDouglimar Alvarez
 
A Quiet Place - Un lugar de serenidad
A Quiet Place  - Un lugar de serenidadA Quiet Place  - Un lugar de serenidad
A Quiet Place - Un lugar de serenidadFreekidstories
 
Lista 2 ano final nox
Lista 2 ano final noxLista 2 ano final nox
Lista 2 ano final noxRenato Souza
 
Gestión del talento essentials
Gestión del talento   essentialsGestión del talento   essentials
Gestión del talento essentialsCamilo Gallyas
 
The hitchhikers journey trough the leadership and communication galaxy
The hitchhikers journey trough the leadership and communication galaxyThe hitchhikers journey trough the leadership and communication galaxy
The hitchhikers journey trough the leadership and communication galaxySteliana Moraru
 
A Quiet Place - Un luogo tranquillo
A Quiet Place - Un luogo tranquilloA Quiet Place - Un luogo tranquillo
A Quiet Place - Un luogo tranquilloFreekidstories
 
A Quiet Place - Um lugar de quietude
A Quiet Place - Um lugar de quietudeA Quiet Place - Um lugar de quietude
A Quiet Place - Um lugar de quietudeFreekidstories
 
Aula 4 estrutura literária - lucas 18. 18-30
Aula 4   estrutura literária - lucas 18. 18-30Aula 4   estrutura literária - lucas 18. 18-30
Aula 4 estrutura literária - lucas 18. 18-30Ipabr Limesp
 
2017 circular 1ª ronda liga nacional cadete v.1
2017 circular 1ª ronda liga nacional cadete v.12017 circular 1ª ronda liga nacional cadete v.1
2017 circular 1ª ronda liga nacional cadete v.1Luis Gomez
 
Kablosuz ağlar
Kablosuz ağlarKablosuz ağlar
Kablosuz ağlarcankugu
 

Destacado (20)

A civilização grega pdf
A civilização grega pdfA civilização grega pdf
A civilização grega pdf
 
LEÇON 74 – Il n’est de volonté que Celle de Dieu.
LEÇON 74 – Il n’est de volonté que Celle de Dieu.LEÇON 74 – Il n’est de volonté que Celle de Dieu.
LEÇON 74 – Il n’est de volonté que Celle de Dieu.
 
How to Use Search Data to Build Content That Drives Value at Scale
How to Use Search Data to Build Content That Drives Value at ScaleHow to Use Search Data to Build Content That Drives Value at Scale
How to Use Search Data to Build Content That Drives Value at Scale
 
Convidar os pobres e estropiados - Cap. XIII - ESE
Convidar os pobres e estropiados - Cap. XIII - ESEConvidar os pobres e estropiados - Cap. XIII - ESE
Convidar os pobres e estropiados - Cap. XIII - ESE
 
Economía Petrolera venezolana
Economía Petrolera venezolanaEconomía Petrolera venezolana
Economía Petrolera venezolana
 
A Quiet Place - Un lugar de serenidad
A Quiet Place  - Un lugar de serenidadA Quiet Place  - Un lugar de serenidad
A Quiet Place - Un lugar de serenidad
 
Lista 2 ano final nox
Lista 2 ano final noxLista 2 ano final nox
Lista 2 ano final nox
 
Hiding behind masks AQ-130317-eng fnl
Hiding behind masks AQ-130317-eng fnlHiding behind masks AQ-130317-eng fnl
Hiding behind masks AQ-130317-eng fnl
 
Herramientas Web 2.0
Herramientas Web 2.0Herramientas Web 2.0
Herramientas Web 2.0
 
Gestión del talento essentials
Gestión del talento   essentialsGestión del talento   essentials
Gestión del talento essentials
 
The hitchhikers journey trough the leadership and communication galaxy
The hitchhikers journey trough the leadership and communication galaxyThe hitchhikers journey trough the leadership and communication galaxy
The hitchhikers journey trough the leadership and communication galaxy
 
A Quiet Place - Un luogo tranquillo
A Quiet Place - Un luogo tranquilloA Quiet Place - Un luogo tranquillo
A Quiet Place - Un luogo tranquillo
 
A Quiet Place - Um lugar de quietude
A Quiet Place - Um lugar de quietudeA Quiet Place - Um lugar de quietude
A Quiet Place - Um lugar de quietude
 
Conference Award Winners
Conference Award WinnersConference Award Winners
Conference Award Winners
 
Aula 4 estrutura literária - lucas 18. 18-30
Aula 4   estrutura literária - lucas 18. 18-30Aula 4   estrutura literária - lucas 18. 18-30
Aula 4 estrutura literária - lucas 18. 18-30
 
Ebt centec
Ebt   centecEbt   centec
Ebt centec
 
Ley de titulos_valores
Ley de titulos_valoresLey de titulos_valores
Ley de titulos_valores
 
2017 circular 1ª ronda liga nacional cadete v.1
2017 circular 1ª ronda liga nacional cadete v.12017 circular 1ª ronda liga nacional cadete v.1
2017 circular 1ª ronda liga nacional cadete v.1
 
Kablosuz ağlar
Kablosuz ağlarKablosuz ağlar
Kablosuz ağlar
 
Base de datos 2 trabajo 3
Base de datos 2 trabajo 3Base de datos 2 trabajo 3
Base de datos 2 trabajo 3
 

Similar a Introducción a PL/SQL (20)

Conceptos basicos de programacion con pl sql
Conceptos basicos de programacion con pl sqlConceptos basicos de programacion con pl sql
Conceptos basicos de programacion con pl sql
 
PLSQL y paquetes
PLSQL y paquetesPLSQL y paquetes
PLSQL y paquetes
 
Bloques
BloquesBloques
Bloques
 
Procedimientos almacenados
Procedimientos almacenadosProcedimientos almacenados
Procedimientos almacenados
 
Transac sq ll
Transac sq llTransac sq ll
Transac sq ll
 
103305862 t-sql
103305862 t-sql103305862 t-sql
103305862 t-sql
 
t-sql
t-sqlt-sql
t-sql
 
Pl
PlPl
Pl
 
PL/SQL
PL/SQLPL/SQL
PL/SQL
 
U8- BBDD - El lenguaje PLSQL operadores y estructuras de control.pdf
U8- BBDD - El lenguaje PLSQL operadores y estructuras de control.pdfU8- BBDD - El lenguaje PLSQL operadores y estructuras de control.pdf
U8- BBDD - El lenguaje PLSQL operadores y estructuras de control.pdf
 
Lenguaje transact sql
Lenguaje transact sqlLenguaje transact sql
Lenguaje transact sql
 
Bloques
BloquesBloques
Bloques
 
Yungan geovanny 6_s_ti_2
Yungan geovanny 6_s_ti_2Yungan geovanny 6_s_ti_2
Yungan geovanny 6_s_ti_2
 
Expo
ExpoExpo
Expo
 
Diapositivas transact sql
Diapositivas transact sqlDiapositivas transact sql
Diapositivas transact sql
 
Curso-de-PLC.pdf
Curso-de-PLC.pdfCurso-de-PLC.pdf
Curso-de-PLC.pdf
 
Transact sql
Transact sqlTransact sql
Transact sql
 
Saula ana bdii_t7
Saula ana bdii_t7Saula ana bdii_t7
Saula ana bdii_t7
 
Yungán geovanny bdii_t7
Yungán geovanny bdii_t7Yungán geovanny bdii_t7
Yungán geovanny bdii_t7
 
Lenguaje transact sql
Lenguaje transact sqlLenguaje transact sql
Lenguaje transact sql
 

Último

Flujo potencial, conceptos básicos y ejemplos resueltos.
Flujo potencial, conceptos básicos y ejemplos resueltos.Flujo potencial, conceptos básicos y ejemplos resueltos.
Flujo potencial, conceptos básicos y ejemplos resueltos.ALEJANDROLEONGALICIA
 
SOLICITUD-PARA-LOS-EGRESADOS-UNEFA-2022.
SOLICITUD-PARA-LOS-EGRESADOS-UNEFA-2022.SOLICITUD-PARA-LOS-EGRESADOS-UNEFA-2022.
SOLICITUD-PARA-LOS-EGRESADOS-UNEFA-2022.ariannytrading
 
¿QUE SON LOS AGENTES FISICOS Y QUE CUIDADOS TENER.pptx
¿QUE SON LOS AGENTES FISICOS Y QUE CUIDADOS TENER.pptx¿QUE SON LOS AGENTES FISICOS Y QUE CUIDADOS TENER.pptx
¿QUE SON LOS AGENTES FISICOS Y QUE CUIDADOS TENER.pptxguillermosantana15
 
Voladura Controlada Sobrexcavación (como se lleva a cabo una voladura)
Voladura Controlada  Sobrexcavación (como se lleva a cabo una voladura)Voladura Controlada  Sobrexcavación (como se lleva a cabo una voladura)
Voladura Controlada Sobrexcavación (como se lleva a cabo una voladura)ssuser563c56
 
Presentación N° 1 INTRODUCCIÓN Y CONCEPTOS DE GESTIÓN AMBIENTAL.pdf
Presentación N° 1 INTRODUCCIÓN Y CONCEPTOS DE GESTIÓN AMBIENTAL.pdfPresentación N° 1 INTRODUCCIÓN Y CONCEPTOS DE GESTIÓN AMBIENTAL.pdf
Presentación N° 1 INTRODUCCIÓN Y CONCEPTOS DE GESTIÓN AMBIENTAL.pdfMIGUELANGELCONDORIMA4
 
TALLER PAEC preparatoria directamente de la secretaria de educación pública
TALLER PAEC preparatoria directamente de la secretaria de educación públicaTALLER PAEC preparatoria directamente de la secretaria de educación pública
TALLER PAEC preparatoria directamente de la secretaria de educación públicaSantiagoSanchez353883
 
Polimeros.LAS REACCIONES DE POLIMERIZACION QUE ES COMO EN QUIMICA LLAMAMOS A ...
Polimeros.LAS REACCIONES DE POLIMERIZACION QUE ES COMO EN QUIMICA LLAMAMOS A ...Polimeros.LAS REACCIONES DE POLIMERIZACION QUE ES COMO EN QUIMICA LLAMAMOS A ...
Polimeros.LAS REACCIONES DE POLIMERIZACION QUE ES COMO EN QUIMICA LLAMAMOS A ...SuannNeyraChongShing
 
Flujo multifásico en tuberias de ex.pptx
Flujo multifásico en tuberias de ex.pptxFlujo multifásico en tuberias de ex.pptx
Flujo multifásico en tuberias de ex.pptxEduardoSnchezHernnde5
 
TEXTURA Y DETERMINACION DE ROCAS SEDIMENTARIAS
TEXTURA Y DETERMINACION DE ROCAS SEDIMENTARIASTEXTURA Y DETERMINACION DE ROCAS SEDIMENTARIAS
TEXTURA Y DETERMINACION DE ROCAS SEDIMENTARIASfranzEmersonMAMANIOC
 
Sesion 02 Patentes REGISTRO EN INDECOPI PERU
Sesion 02 Patentes REGISTRO EN INDECOPI PERUSesion 02 Patentes REGISTRO EN INDECOPI PERU
Sesion 02 Patentes REGISTRO EN INDECOPI PERUMarcosAlvarezSalinas
 
Comite Operativo Ciberseguridad 012020.pptx
Comite Operativo Ciberseguridad 012020.pptxComite Operativo Ciberseguridad 012020.pptx
Comite Operativo Ciberseguridad 012020.pptxClaudiaPerez86192
 
Reporte de Exportaciones de Fibra de alpaca
Reporte de Exportaciones de Fibra de alpacaReporte de Exportaciones de Fibra de alpaca
Reporte de Exportaciones de Fibra de alpacajeremiasnifla
 
Hanns Recabarren Diaz (2024), Implementación de una herramienta de realidad v...
Hanns Recabarren Diaz (2024), Implementación de una herramienta de realidad v...Hanns Recabarren Diaz (2024), Implementación de una herramienta de realidad v...
Hanns Recabarren Diaz (2024), Implementación de una herramienta de realidad v...Francisco Javier Mora Serrano
 
El proyecto “ITC SE Lambayeque Norte 220 kV con seccionamiento de la LT 220 kV
El proyecto “ITC SE Lambayeque Norte 220 kV con seccionamiento de la LT 220 kVEl proyecto “ITC SE Lambayeque Norte 220 kV con seccionamiento de la LT 220 kV
El proyecto “ITC SE Lambayeque Norte 220 kV con seccionamiento de la LT 220 kVSebastianPaez47
 
Elaboración de la estructura del ADN y ARN en papel.pdf
Elaboración de la estructura del ADN y ARN en papel.pdfElaboración de la estructura del ADN y ARN en papel.pdf
Elaboración de la estructura del ADN y ARN en papel.pdfKEVINYOICIAQUINOSORI
 
Presentación Proyecto Trabajo Creativa Profesional Azul.pdf
Presentación Proyecto Trabajo Creativa Profesional Azul.pdfPresentación Proyecto Trabajo Creativa Profesional Azul.pdf
Presentación Proyecto Trabajo Creativa Profesional Azul.pdfMirthaFernandez12
 
IPERC Y ATS - SEGURIDAD INDUSTRIAL PARA TODA EMPRESA
IPERC Y ATS - SEGURIDAD INDUSTRIAL PARA TODA EMPRESAIPERC Y ATS - SEGURIDAD INDUSTRIAL PARA TODA EMPRESA
IPERC Y ATS - SEGURIDAD INDUSTRIAL PARA TODA EMPRESAJAMESDIAZ55
 
Tiempos Predeterminados MOST para Estudio del Trabajo II
Tiempos Predeterminados MOST para Estudio del Trabajo IITiempos Predeterminados MOST para Estudio del Trabajo II
Tiempos Predeterminados MOST para Estudio del Trabajo IILauraFernandaValdovi
 
Seleccion de Fusibles en media tension fusibles
Seleccion de Fusibles en media tension fusiblesSeleccion de Fusibles en media tension fusibles
Seleccion de Fusibles en media tension fusiblesSaulSantiago25
 

Último (20)

Flujo potencial, conceptos básicos y ejemplos resueltos.
Flujo potencial, conceptos básicos y ejemplos resueltos.Flujo potencial, conceptos básicos y ejemplos resueltos.
Flujo potencial, conceptos básicos y ejemplos resueltos.
 
SOLICITUD-PARA-LOS-EGRESADOS-UNEFA-2022.
SOLICITUD-PARA-LOS-EGRESADOS-UNEFA-2022.SOLICITUD-PARA-LOS-EGRESADOS-UNEFA-2022.
SOLICITUD-PARA-LOS-EGRESADOS-UNEFA-2022.
 
¿QUE SON LOS AGENTES FISICOS Y QUE CUIDADOS TENER.pptx
¿QUE SON LOS AGENTES FISICOS Y QUE CUIDADOS TENER.pptx¿QUE SON LOS AGENTES FISICOS Y QUE CUIDADOS TENER.pptx
¿QUE SON LOS AGENTES FISICOS Y QUE CUIDADOS TENER.pptx
 
Voladura Controlada Sobrexcavación (como se lleva a cabo una voladura)
Voladura Controlada  Sobrexcavación (como se lleva a cabo una voladura)Voladura Controlada  Sobrexcavación (como se lleva a cabo una voladura)
Voladura Controlada Sobrexcavación (como se lleva a cabo una voladura)
 
Presentación N° 1 INTRODUCCIÓN Y CONCEPTOS DE GESTIÓN AMBIENTAL.pdf
Presentación N° 1 INTRODUCCIÓN Y CONCEPTOS DE GESTIÓN AMBIENTAL.pdfPresentación N° 1 INTRODUCCIÓN Y CONCEPTOS DE GESTIÓN AMBIENTAL.pdf
Presentación N° 1 INTRODUCCIÓN Y CONCEPTOS DE GESTIÓN AMBIENTAL.pdf
 
TALLER PAEC preparatoria directamente de la secretaria de educación pública
TALLER PAEC preparatoria directamente de la secretaria de educación públicaTALLER PAEC preparatoria directamente de la secretaria de educación pública
TALLER PAEC preparatoria directamente de la secretaria de educación pública
 
Polimeros.LAS REACCIONES DE POLIMERIZACION QUE ES COMO EN QUIMICA LLAMAMOS A ...
Polimeros.LAS REACCIONES DE POLIMERIZACION QUE ES COMO EN QUIMICA LLAMAMOS A ...Polimeros.LAS REACCIONES DE POLIMERIZACION QUE ES COMO EN QUIMICA LLAMAMOS A ...
Polimeros.LAS REACCIONES DE POLIMERIZACION QUE ES COMO EN QUIMICA LLAMAMOS A ...
 
Flujo multifásico en tuberias de ex.pptx
Flujo multifásico en tuberias de ex.pptxFlujo multifásico en tuberias de ex.pptx
Flujo multifásico en tuberias de ex.pptx
 
TEXTURA Y DETERMINACION DE ROCAS SEDIMENTARIAS
TEXTURA Y DETERMINACION DE ROCAS SEDIMENTARIASTEXTURA Y DETERMINACION DE ROCAS SEDIMENTARIAS
TEXTURA Y DETERMINACION DE ROCAS SEDIMENTARIAS
 
Sesion 02 Patentes REGISTRO EN INDECOPI PERU
Sesion 02 Patentes REGISTRO EN INDECOPI PERUSesion 02 Patentes REGISTRO EN INDECOPI PERU
Sesion 02 Patentes REGISTRO EN INDECOPI PERU
 
Comite Operativo Ciberseguridad 012020.pptx
Comite Operativo Ciberseguridad 012020.pptxComite Operativo Ciberseguridad 012020.pptx
Comite Operativo Ciberseguridad 012020.pptx
 
Reporte de Exportaciones de Fibra de alpaca
Reporte de Exportaciones de Fibra de alpacaReporte de Exportaciones de Fibra de alpaca
Reporte de Exportaciones de Fibra de alpaca
 
VALORIZACION Y LIQUIDACION MIGUEL SALINAS.pdf
VALORIZACION Y LIQUIDACION MIGUEL SALINAS.pdfVALORIZACION Y LIQUIDACION MIGUEL SALINAS.pdf
VALORIZACION Y LIQUIDACION MIGUEL SALINAS.pdf
 
Hanns Recabarren Diaz (2024), Implementación de una herramienta de realidad v...
Hanns Recabarren Diaz (2024), Implementación de una herramienta de realidad v...Hanns Recabarren Diaz (2024), Implementación de una herramienta de realidad v...
Hanns Recabarren Diaz (2024), Implementación de una herramienta de realidad v...
 
El proyecto “ITC SE Lambayeque Norte 220 kV con seccionamiento de la LT 220 kV
El proyecto “ITC SE Lambayeque Norte 220 kV con seccionamiento de la LT 220 kVEl proyecto “ITC SE Lambayeque Norte 220 kV con seccionamiento de la LT 220 kV
El proyecto “ITC SE Lambayeque Norte 220 kV con seccionamiento de la LT 220 kV
 
Elaboración de la estructura del ADN y ARN en papel.pdf
Elaboración de la estructura del ADN y ARN en papel.pdfElaboración de la estructura del ADN y ARN en papel.pdf
Elaboración de la estructura del ADN y ARN en papel.pdf
 
Presentación Proyecto Trabajo Creativa Profesional Azul.pdf
Presentación Proyecto Trabajo Creativa Profesional Azul.pdfPresentación Proyecto Trabajo Creativa Profesional Azul.pdf
Presentación Proyecto Trabajo Creativa Profesional Azul.pdf
 
IPERC Y ATS - SEGURIDAD INDUSTRIAL PARA TODA EMPRESA
IPERC Y ATS - SEGURIDAD INDUSTRIAL PARA TODA EMPRESAIPERC Y ATS - SEGURIDAD INDUSTRIAL PARA TODA EMPRESA
IPERC Y ATS - SEGURIDAD INDUSTRIAL PARA TODA EMPRESA
 
Tiempos Predeterminados MOST para Estudio del Trabajo II
Tiempos Predeterminados MOST para Estudio del Trabajo IITiempos Predeterminados MOST para Estudio del Trabajo II
Tiempos Predeterminados MOST para Estudio del Trabajo II
 
Seleccion de Fusibles en media tension fusibles
Seleccion de Fusibles en media tension fusiblesSeleccion de Fusibles en media tension fusibles
Seleccion de Fusibles en media tension fusibles
 

Introducción a PL/SQL

  • 1. PL/SQL I VERSIÓN 1 JPV-99 1 / 67 PPLL//SSQQLL II Javier Pérez-Vigo (Octubre 1999)
  • 2. PL/SQL I VERSIÓN 1 JPV-99 2 / 67 INTRODUCCIÓN ORACLE es un sistema de base de datos relacional potente y flexible. El lenguaje de programación PL/SQL está diseñado 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 manipulación de información almacenada en bases de datos ORACLE y para el desarrollo de cualquier aplicación en ese entorno. En esta unidad didáctica se definen las principales características de este lenguaje y su sintaxis, se enumeran las principales funciones predefinidas. Así mismo se estudian las órdenes SQL disponibles: de control, de manipulación de datos y transaccionales. Posteriormente se introduce el concepto de cursor y por último se explica cómo se diseña el tratamiento de errores.
  • 3. PL/SQL I VERSIÓN 1 JPV-99 3 / 67 CONTENIDO 1. DEFINICIÓN Y CARACTERÍSTICAS DE PL/SQL 2. EL BLOQUE PL/SQL ZONA DE DECLARACIÓN: DECLARACIÓN DE VARIABLES Y CONSTANTES ZONA DE PROCESO ZONA DE EXCEPCIONES 3. FUNCIONES SQL PREDEFINIDAS FUNCIONES DE CARÁCTER QUE DEVUELVEN VALORES DE CARÁCTER FUNCIONES DE CARÁCTER QUE DEVUELVEN VALORES NUMÉRICOS FUNCIONES NUMÉRICAS FUNCIONES DE FECHA FUNCIONES DE CONVERSIÓN 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 EVALUACIÓN
  • 4. PL/SQL I VERSIÓN 1 JPV-99 4 / 67 OBJETIVOS El alumno tras el estudio de esta unidad didáctica podrá: Conocer la sintaxis y los elementos que componen el lenguaje PL/SQL. Consultar y manipular la información almacenada en servidores de Bases de Datos Oracle. Desarrollar estructuras básicas de programación en PL/SQL. EXPECTATIVAS • ·························································································································· ························································································································ • ·························································································································· ························································································································ • ·························································································································· ························································································································
  • 5. PL/SQL I VERSIÓN 1 JPV-99 5 / 67 1. DEFINICIÓN Y CARACTERÍSTICAS 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 técnicas 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 código ejecutable almacenado en el servidor de base de datos. ♦ PL/SQL, (Procedural Language / SQL), es un lenguaje de programación procedural estructurado en bloques que amplia la funcionalidad del lenguaje standard SQL a través 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 métodos, (a partir de versión 8) IMPORTANTE DQL. Data Query Language (select) DML Data manipulation language (insert) DDL Data definition language (create table) NOTA
  • 6. PL/SQL I VERSIÓN 1 JPV-99 6 / 67 Es un lenguaje estructurado en bloques: Bloque es la unidad básica 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 construcción, cuya finalidad es el encapsulamiento, la abstracción y el control de acceso). • Disparadores (Eventos que se ejecutan cuando ocurre una operación de manipulación de datos sobre una tabla) La versión objeto de estudio será la 2.3. NOTA También se pueden incorporar órdenes DDL mediante SQL Dinámico. NOTA
  • 7. PL/SQL I VERSIÓN 1 JPV-99 7 / 67 2. EL BLOQUE PL/SQL Todos los bloques tienen tres secciones diferenciadas: • Sección declarativa. • Sección ejecutable, (la única obligatoria). • Sección de excepciones. EESSTTRRUUCCTTUURRAA:: [DECLARE] Declaración 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. ExcepciónVariables para control de errores. ♦ El Bloque PL/SQL es la unidad básica en todo programa PL/SQL. ♦ Un programa PL/SQL será un conjunto de bloques PL/SQL, situados de manera secuencial o anidados IMPORTANTE
  • 8. PL/SQL I VERSIÓN 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 excepción pueden ser definidos por el usuario o por el sistema, como es por ejemplo la excepción ZERO_DIVIDE. Las excepciones se activan automáticamente al ocurrir un error, existiendo la definición de la excepción 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 DDEECCLLAARRAACCIIÓÓNN:: DDEE VVAARRIIAABBLLEESS YY CCOONNSSTTAANNTTEESS Las variables son utilizadas para guardar valores devueltos por una consulta o almacenar cálculos intermedios. Las constantes son campos que se definen y no alteran su valor en el proceso. Nombre_campo [CONSTANT] Tipo de dato := valor_constante / expresión_pl_sql Este tipo de bloque se le suele llamar anónimo, y es el más utilizado en Scripts. NOTA
  • 9. PL/SQL I VERSIÓN 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 también 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 sólo en bloques PL/SQL anónimos. Var1 number(59); Var2 Var1%TYPE; Var3 tabla.identificador%TYPE; registro tabla%ROWTYPE
  • 10. PL/SQL I VERSIÓN 1 JPV-99 10 / 67 TIPOS DE DATOS. Number (n [, d]) – numérico n <= 38 Binary_Integer – entero, desde –2147483647 a +2147483647 PLS_Integer – entero, desde –2147483647 a +2147483647 Char – de longitud fija, hasta 255 caracteres Varchar – de tipo carácter (obsoleto) Varchar2 – Tamaño variable hasta 2000 caracteres. Date - Fechas Boolean – TRUE o FALSE (no puede utilizarse en campos SQL) Long- Cadena de caracteres de longitud variable hasta 2 Gigabytes Raw- Datos binarios de longitud variable, hasta 255 caracteres (gráficos) Longraw- Cadena binaria de longitud variable de hasta 2 Gigabytes (gráficos) El tipo PLS_Integer se suele utilizar para contadores. Es idéntico al Binary_integer pero añade la característica de dar un mensaje de error en caso de error. El tipo Binary_Integer se suele utilizar para tablas de PL/SQL NOTA
  • 11. PL/SQL I VERSIÓN 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 más de uno provoca un ERROR, saltando la ejecución directamente al EXCEPTION. ASIGNACIÓN DE VALORES Las dos formas que existen para asignar valores a variables de memoria, son: - Con el operador de asignación :=, como cuando calculamos el promedio de las ventas asignándole 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 asignación de valores a las variables xtotal y xcant con el siguiente código: 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.
  • 12. PL/SQL I VERSIÓN 1 JPV-99 12 / 67 COMENTARIOS Hay dos tipos de comentarios: Con el signo -- se indica comentario de una sola línea. Mediante /* al principio del comentario y */ al final de éste. ZZOONNAA DDEE EEXXCCEEPPCCIIOONNEESS Las excepciones saltan cuando se ha producido un error en la ejecución. Es sección no obligatoria. Esta sección 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 después del WHEN: Excepción Número de error CURSOR_ALREADY_OPEN ORA–06511 –6511 DUP_VAL_ON_INDEX ORA–00001 –1 INVALID_CURSOR ORA–01001 –1001 INVALID_NUMBER ORA–01722 –1722 LOGIN_DENIED ORA–01017 –1017 NO_DATA–FOUND ORA–01403 +100 NOT_LOGGED_ON ORA–01012 –1012 PROGRAM_ERROR ORA–06501 –6501
  • 13. PL/SQL I VERSIÓN 1 JPV-99 13 / 67 ROWTYPE_MISMATCH ORA–06504 –6504 STORAGE_ERROR ORA–06500 –6500 TIMEOUT_ON_RESOURCE ORA–00051 –51 TOO_MANY_ROWS ORA–01422 –1422 VALUE_ERROR ORA–06502 –6502 ZERO_DIVIDE ORA–01476 –1476 EJERCICIO Nº 1 Crear un bloque PL/SQL con las siguientes características: • Definir una constante de tipo numérico, de nombre x, a la que le vamos a asignar el valor de 12. • Definir una variable, y, del mismo tipo que el campo hiredate, de la tabla EMP, de la base de datos DEMO. • Definir una variable de tipo numérico que se llame z. • Asignar a la variable y la fecha actual. Asignar a la variable z el resultado de multiplicar x por 10. • Mostrar por pantalla el contenido de las variables y e z. EJERCICIO
  • 14. PL/SQL I VERSIÓN 1 JPV-99 14 / 67 EJERCICIO Nº 2 Se trata de hacer una consulta a la tabla EMP, concretamente del campo ename de tal forma que el usuario introduzca un nombre por teclado y el bloque PL/SQL sea capaz de recuperar el campo job de dicho empleado a través de dicha consulta. • Pedir que se introduzca por teclado un nombre, el cual lo almacenaremos en la variable nombre. • Una vez introducido el nombre, lanzar un bloque PL/SQL (previamente creado) de tal forma que sea capaz de seleccionar la fila de la tabla EMP cuyo ename sea igual al introducido por teclado y mostrar el campo job correspondiente a ese empleado por pantalla. EJERCICIO
  • 15. PL/SQL I VERSIÓN 1 JPV-99 15 / 67 3. FUNCIONES SQL PREDEFINIDAS FFUUNNCCIIOONNEESS DDEE CCAARRÁÁCCTTEERR QQUUEE DDEEVVUUEELLVVEENN VVAALLOORREESS DDEE CCAARRÁÁCCTTEERR ♦ CHR Chr(x) Devuelve el carácter dado su número ASCII . ♦ CONCAT Concat (cadena1, cadena2) Devuelve las dos cadenas encadenadas (Es idéntico a usar ||). ♦ INITCAP Initcap (cadena) Devuelve la misma cadena, con el primer carácter de cada palabra en mayúscula y el resto en minúscula. ♦ LOWER Lower (cadena) Devuelve la misma cadena con todos los caracteres en minúscula. ♦ 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
  • 16. PL/SQL I VERSIÓN 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 porción, de b caracteres de longitud, de la cadena proporcionada como argumento, empezando a partir de la posición 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 contaría desde el final de la cadena. ♦ UPPER Upper (cadena) Devuelve la cadena proporcionada con todas las letras en mayúsculas.
  • 17. PL/SQL I VERSIÓN 1 JPV-99 17 / 67 FFUUNNCCIIOONNEESS DDEE CCAARRÁÁCCTTEERR QQUUEE DDEEVVUUEELLVVEENN VVAALLOORREESS NNUUMMÉÉRRIICCOOSS ♦ ASCII ASCII (cadena) Devuelve la representación decimal del primer byte de la cadena. ♦ INSTR INSTR (cadena1, cadena2 [,a[,b]]) Devuelve la posición de la cadena1 donde está contenida la cadena2. (La cadena se explora desde la izquierda, empezando a partir de la posición a. Sí a es negativo, entonces la cadena1 se explora desde la derecha. El valor devuelto es el de la aparición número b de la cadena de la búsqueda). 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
  • 18. PL/SQL I VERSIÓN 1 JPV-99 18 / 67 ♦ LENGTH Length (cadena) Devuelve la longitud de la cadena. FFUUNNCCIIOONNEESS NNUUMMÉÉRRIICCAASS ♦ 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(‘Scott’’s spot’, ‘ot’, 1, 2) Cadena FROM dual; > 11
  • 19. PL/SQL I VERSIÓN 1 JPV-99 19 / 67 ♦ COSH COSH (x) Devuelve el coseno hiperbólico 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 número 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 hiperbólico de x ♦ SQRT SQRT (x) Devuelve la raiz cuadrada de X
  • 20. PL/SQL I VERSIÓN 1 JPV-99 20 / 67 ♦ TAN TAN (x) Devuelve la tangente de x (en radianes) ♦ TANH TANH (x) Devuelve la tangente hiperbólica 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 más x meses ♦ LAST_DAY LAST_DAY (d) Devuelve la fecha del último día del mes al que d pertenece ♦ MONTHS_BETWEEN MONTHS_BETWEEN (fecha1, fecha2) Devuelve el número 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
  • 21. PL/SQL I VERSIÓN 1 JPV-99 21 / 67 ♦ NEXT_DAY NEXT_DAY(d, cadena) Devuelve la fecha del día 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
  • 22. PL/SQL I VERSIÓN 1 JPV-99 22 / 67 FFUUNNCCIIOONNEESS DDEE CCOONNVVEERRSSIIÓÓNN CONVERSIONES IMPLÍCITAS PL/SQL Convierte automáticamente entre los siguientes tipos de datos: CONVERSIONES EXPLÍCITAS 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
  • 23. PL/SQL I VERSIÓN 1 JPV-99 23 / 67 ♦ TO_NUMBER TO_NUMBER (d [,formato [, paramls]]) Convierte la cadena a un valor numérico. 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
  • 24. PL/SQL I VERSIÓN 1 JPV-99 24 / 67 FORMATOS NUMÉRICOS 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
  • 25. PL/SQL I VERSIÓN 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)
  • 26. PL/SQL I VERSIÓN 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 número de filas en la consulta ♦ MAX MAX ([Distinct | All] col) Devuelve el valor máximo de la consulta de selección. ♦ MIN MIN ([Distinct | All] col) Devuelve el valor mínimo de la consulta de selección.
  • 27. PL/SQL I VERSIÓN 1 JPV-99 27 / 67 ♦ STDDEV STDDEV ([Distinct | All] col) Devuelve la desviación estándar del elemento de lista de selección. ♦ SUM SUM ([Distinct | All] col) Devuelve la suma de los valores para el elemento de lista de selección. ♦ VARIANCE VARIANCE ([Distinct | All] col) Devuelve la varianza estadística del elemento de lista de selección. OOTTRRAASS FFUUNNCCIIOONNEESS ♦ DECODE DECODE (expr_base, compara1, valor1, compara2, valor2… predeterminado) La función DECODE es similar a una serie de órdenes IF-THEN-ELSE anidadas. La expresión expr_base se compara sucesivamente con compara1, compara2, etc. Si expr_base coincide con el elemento de comparación número i, se devuelve el valor i. Si expr_base no coincide con ninguno de los valores de comparación, se devuelve el valor predeterminado. ♦ GREATEST GREATEST (expr1 [expr2] …) Devuelve la expresión con mayor valor de todos sus argumentos. Cada expresión es convertida de forma implícita al tipo de expr1 antes de realizar las comparaciones. Si expr1 es de tipo carácter, se realizan comparaciones de carácter sin relleno de blancos, y el resultado es de tipo VARCHAR2.
  • 28. PL/SQL I VERSIÓN 1 JPV-99 28 / 67 ♦ LEAST LEAST (expr1 [expr2] …) Devuelve la expresión con menor valor de todos sus argumentos. Cada expresión es convertida de forma implícita al tipo de expr1 antes de realizar las comparaciones. Si expr1 es de tipo carácter, se realizan comparaciones de carácter sin relleno de blancos, y el resultado es de tipo VARCHAR2. ♦ NVL NVL (expr1 ,expr2) Si el valor de expr1 es NULL, la función 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 (opción) Devuelve un valor VARCHAR2 que contiene información acerca de la sesión actual, según la opción seleccionada. OPCIONES LANGUAGE Devuelve el idioma y país utilizados SESSIONID Devuelve el identificador del elemento de registro de la sesión TERMINAL Devuelve un identificador, dependiente del sistema operativo, para el terminal de la sesión actual.
  • 29. PL/SQL I VERSIÓN 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
  • 30. PL/SQL I VERSIÓN 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 día de la semana actual en castellano en letra mediante un DECODE y sin utilizar la máscara ‘d’. EJERCICIO Nº 5 - Obtener las nuevas comisiones de los empleados teniendo en cuenta que se subirán un 5% el próximo año y que aquellos que no tengan les corresponderán como tales la cuarta parte de su salario. PRÁCTICA
  • 31. PL/SQL I VERSIÓN 1 JPV-99 31 / 67 4. SENTENCIAS DE CONTROL SSEENNTTEENNCCIIAA IIFF IF Condición THEN sentencias_ejecutables [ELSIF condición THEN sentencias_ejecutables; ] ELSE sentencias_ejecutables; ] END IF; SQL> DECLARE v_NumberSeats rooms.number_seats%TYPE; v_Comment VARCHAR2(35); BEGIN /* Recibe el número 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';
  • 32. PL/SQL I VERSIÓN 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; /
  • 33. PL/SQL I VERSIÓN 1 JPV-99 33 / 67 BBUUCCLLEESS CCOONNDDIICCIIOONNAALLEESS:: WHILE condición 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 <= 50 LOOP INSERT INTO temp_table VALUES (v_Counter, 'Loop index'); v_Counter := v_Counter + 1; END LOOP; END; /
  • 34. PL/SQL I VERSIÓN 1 JPV-99 34 / 67 BBUUCCLLEESS NNUUMMÉÉRRIICCOOSS:: FOR índice IN [REVERSE] número_inicio..número_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 declaración 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;
  • 35. PL/SQL I VERSIÓN 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 numérico. • Introducir una fila por cada día del mes actual de tal forma que el resultado final sea algo parecido a esto: DÍAS 1 2 3 4 5 ... 29 30 • Realizar el ejercicio utilizando for...loop , loop...exit y while. EJERCICIO
  • 36. PL/SQL I VERSIÓN 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 número de fila leída 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 implícito por cada sentencia SQL que tenga que procesar. ♦ Nos referiremos a él como SQL% IMPORTANTE
  • 37. PL/SQL I VERSIÓN 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 número 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 número de departamento que no figura en la tabla DEPT. EJERCICIO
  • 38. PL/SQL I VERSIÓN 1 JPV-99 38 / 67 EJERCICIO 9 • Crear un bloque PL/SQL que modifique la tabla EMP de tal forma aquellos empleados cuyo número de empleado sea –1 pasen a tener como job ‘CLERK’. • Si no existiera ningún empleado con número –1, insertar dicho empleado con las siguientes características: ENAME: ‘PEDRO PEREZ’ JOB: ‘CLERK’ MGR: 7934 DPTNO: 20 • Capturar el error utilizando el cursor implícito SQL%. EJERCICIO
  • 39. PL/SQL I VERSIÓN 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 condición 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 parámetros en la SELECT. CURSOR NOMBRE_CURSOR (nombre_parametro tipo_parametro) IS SENTENCIA SELECT utilizando los parámetros; Variable de tipo %ROWTYPE. ♦ Un cursor es un área de trabajo que utiliza ORACLE para consultas que devuelven más de una fila, permitiendo la lectura y manipulación de cada una de ellas. ♦ Declaración: 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
  • 40. PL/SQL I VERSIÓN 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 más filas que devolver • Nombre_cursor%FOUND Contrario de %notfound • Nombre_cursor%ROWCOUNT Devuelve el número de fila leída. • 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 (parámetro). Para cursores sin parámetros recuperamos una fila utilizando: FETCH NOMBRE_CURSOR INTO VARIBLE1, VARIABLE2, VARIABLE3... Cerramos un cursor utilizando la sentencia CLOSE. BBUUCCLLEESS SSOOBBRREE CCUURRSSOORREESS Realiza automáticamente las siguientes acciones: • Abre el cursor. Se realiza la lectura y se ejecutan las sentencias del bucle hasta que no haya más filas.
  • 41. PL/SQL I VERSIÓN 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 continuación veremos un ejemplo de cursor con las siguientes características: Objetivo: Consultar las ventas de una fecha dada ordenadas de mayor a menor. Nombre:CVENTAS. Parámetros: cfecha, variable que contiene la fecha a consultar.
  • 42. PL/SQL I VERSIÓN 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;
  • 43. PL/SQL I VERSIÓN 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 continuación detallaremos las sentencias usadas en este procedimiento: DECLARE cursor Define el cursor, su consulta y la lista de parámetros que se pasan a la orden WHERE, es solo la declaración del cursor y no la realización 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 cómo está definida esa columna en la tabla y, en caso que la definición de la columna sea modificada, automáticamente se cambia la variable xarticulo. OPEN cventas(xfecha); Realiza la consulta asociada al cursor, pasando el valor del parámetro 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 numérico de repetición para poder consultar las 5 primeras ventas devueltas por el cursor. FETCH cventas INTO xarticulo,xvalor;
  • 44. PL/SQL I VERSIÓN 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 repetición, en caso que para una fecha dada se hayan efectuado menos de 5 ventas, ya que en esta situación 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 leídos desde el cursor. COMMIT; Actualización 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 añadirles 1000 al campo salario. EJERCICIO
  • 45. PL/SQL I VERSIÓN 1 JPV-99 45 / 67 EJERCICIO 11 EJERCICIO SOBRE CURSORES • Crear una tabla de totales por departamentos con dos campos: uno para los números de departamento y otro numérico para meter los totales por departamento. • El proceso consiste en pedir por pantalla el número de departamento y calcular el total de la suma de los salarios mas las comisiones. Utilizar un cursor. • Insertar el resultado en la tabla recién 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 cuántos 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 sólo aquellos trabajos que tengan más de 1 empleado. EJERCICIO
  • 46. PL/SQL I VERSIÓN 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 también %TYPE y %ROWTYPE. Se puede asignar un registro a otro del mismo tipo o sus campo individualmente, con la condición 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
  • 47. PL/SQL I VERSIÓN 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 Sería una asignación ilegal que elevaría el error PLS-382. */ v_Rec1 := v_Rec2; /* Estos campos, son del mismo tipo, por los que la asignación sería legal. */ v_Rec1.Field1 := v_Rec2.Field1; v_Rec2.Field2 := v_Rec2.Field2; END; /
  • 48. PL/SQL I VERSIÓN 1 JPV-99 48 / 67 TTAABBLLAASS EENN PPLL//SSQQLL Las tablas en PL/SQL se asemejan a los arrays del lenguaje C. Sintácticamente se las trata de la misma forma que a las matrices, aunque su implementación es distinta. DEFINICIÓN 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 definición. ♦ El máximo número de filas viene especificado por el número máximo de valores que se pueden representar mediante el tipo BINARY_INTEGER. IMPORTANTE
  • 49. PL/SQL I VERSIÓN 1 JPV-99 49 / 67 Dispone de control automático de asignación 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 número 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.
  • 50. PL/SQL I VERSIÓN 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 en v_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; /
  • 51. PL/SQL I VERSIÓN 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
  • 52. PL/SQL I VERSIÓN 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 posición 1 la cadena ‘Uno’ Insertar en la posición 3 la cadena ‘Tres Insertar en la posición –2 la cadena ‘Menos dos’ Insertar en la posición 0 la cadena ‘Cero’ Insertar en la posición 100 la cadena ‘Cien’ Mostrar un mensaje con el número total de filas de la tabla Elimina la fila de la posición 100 Mostrar un mensaje con el número de filas de la tabla Borrar las filas desde la posición 1 a la 3 Mostrar un mensaje con el número de filas de la tabla Borrar el elemento que se encuentre en la primera posición Mostrar el contenido la última posición Mostrar el contenido de la penúltima posición Mostrar el contenido de la posición –1 Borrar toda la tabla EJERCICIO
  • 53. PL/SQL I VERSIÓN 1 JPV-99 53 / 67 EJERCICIO 15 EJERCICIO SOBRE TABLAS DE REGISTROS • Crear una tabla (en el núcleo) 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 comisión no nula. Una vez realizada la carga del array se extraerán en orden inverso al que fueron introducidos y se insertarán 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. Sería 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 implícito. EJERCICIO
  • 54. PL/SQL I VERSIÓN 1 JPV-99 54 / 67 8. SENTENCIAS TRANSACCIONALES • Savepoint: Marcas que pone el usuario durante la transacción para deshacer los cambios por partes en vez de deshacer toda la transacción. SAVEPOINT <nombre_del_punto_salvaguarda>; • Commit: Realiza todas las transacciones pendientes de la actual transacción haciéndolas visibles para los demás usuarios. COMMIT [WORK]; • Rollback: Deshace todos los cambios pendientes de la transacción actual. ROLLBACK [WORK] [ TO [SAVEPOINT] punto_salvaguarda; ] ♦ Una transacción 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 transacción termina con la orden COMMIT o ROLLBACK. IMPORTANTE
  • 55. PL/SQL I VERSIÓN 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 comisión mayor que 350$ con un incremento del 15% de su salario. Si la operación afecta a más de tres empleados, deshacer la transacción, en cualquier otro caso validar la transacción. Introducir en la tabla TEMP la operación que se ha realizado. PRÁCTICA
  • 56. PL/SQL I VERSIÓN 1 JPV-99 56 / 67 EJERCICIO 17 EJERCICIO SOBRE UTILIZACIÓN DE SENTENCIAS TRANSACCIONALES • Crear un bloque PL/SQL que modifique el sal de los empleados que no tienen comisión a 1000. • Dentro del mismos bloque PL/SQL actualizar los empleados con una comisión mayor de 350 $ con un incremento del 15% de su salario. Si la operación afecta a más de tres empleados, deshacer la transacción, en cualquier otro caso validar dicha transacción. • Utilizar sólo un commit en el bloque PL/SQL. PRÁCTICA
  • 57. PL/SQL I VERSIÓN 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 anónimo o del procedimiento almacenado. WHEN NOMBRE_EXCEPCION1 [OR NOMBRE_EXCEPCION2....] THEN SENTENCIAS; IMPORTANTE La zona de excepciones no es obligatoria. NOTA
  • 58. PL/SQL I VERSIÓN 1 JPV-99 58 / 67 DEFINIDAS POR EL USUARIO: Mediante: a) Exception_init, basadas en errores ORACLE PRAGMA EXCEPTION_INIT (nombre_excepción, número_error); b) Declarándola como excepción con el tipo de dato EXCEPTION en el DECLARE. EEJJEECCUUCCIIÓÓNN DDEE EEXXCCEEPPCCIIOONNEESS La ejecución de excepciones se produce: • Automáticamente: Cuando ORACLE detecta un error, para el proceso y pasa automáticamente 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_excepción>; Nombre_excepción hay que definirlo antes con EXCEPTION. El número de error es un sqlcode que no se halla definido para otra excepción de Oracle , (p. Ej. NO DATA FOUND). NOTA
  • 59. PL/SQL I VERSIÓN 1 JPV-99 59 / 67 FFUUNNCCIIOONNEESS La función SQLCODE nos devuelve el número de error producido. Sólo tiene valor cuando ocurre un error ORACLE Sólo se habilita en la zona de excepciones. La función 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: Creación de tabla donde almacenarlos: Se puede emplear la función predefinida RAISE_APPLICATION_ERROR para la creación de mensajes de error por parte del usuario. Su sintaxis es: RAISE_APPLICATION_ERROR (código, ‘Mensaje’). Donde código es un número entre –20000 y –20999. NOTA
  • 60. PL/SQL I VERSIÓN 1 JPV-99 60 / 67 REM REM Creación 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; /
  • 61. PL/SQL I VERSIÓN 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 división–by–zero INSERT INTO stats (symbol, ratio) VALUES ('XYZ', pe_ratio); COMMIT; EXCEPTION -- COMIENZA EL BLOQUE DE EXCEPCIÓN WHEN ZERO_DIVIDE THEN -- Maneja el error de división por cero INSERT INTO stats (symbol, ratio) VALUES ('XYZ', NULL); COMMIT; ... WHEN OTHERS THEN -- maneja todos los demás errores ROLLBACK; END; -- fin de las excepciones y del bloque. /
  • 62. PL/SQL I VERSIÓN 1 JPV-99 62 / 67 CREACIÓN 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 sólo tienes privilegios de consulta ------------------------------------------------------- BEGIN ... EXCEPTION WHEN insufficient_privileges THEN Maneja el error ... END; / ELEVACIÓN DE MENSAJES DE ERROR PROPIOS DE USUARIO. DECLARE ... null_salary EXCEPTION; /* Número de Error mapeado devuelto por raise_application_error de una excepción definida por el usuario. */ PRAGMA EXCEPTION_INIT(null_salary, –20101);
  • 63. PL/SQL I VERSIÓN 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 excepción que se va a llamar SOLO_UN_EMPLEADO mostrando un mensaje por pantalla. • En el caso de recuperar más utilizaremos la excepción TOO_MANY_ROWS y mostraremos un mensaje indicativo en la pantalla. • En el caso de no recuperar ninguno utilizaremos las excepción NO_DATA_FOUND y mostraremos el respectivo mensaje. PRÁCTICA
  • 64. PL/SQL I VERSIÓN 1 JPV-99 64 / 67 10. RESUMEN PL/SQL, (Procedural Language / SQL), es un lenguaje de programación procedural estructurado en bloques que amplia la funcionalidad del lenguaje standard SQL a través 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 métodos, (a partir de versión 8) El Bloque PL/SQL es la unidad básica 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 implícito 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 más de una fila, permitiendo la lectura y manipulación de cada una de ellas.
  • 65. PL/SQL I VERSIÓN 1 JPV-99 65 / 67 Declaración 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 definición. El máximo número de filas viene especificado por el número máximo de valores que se pueden representar mediante el tipo BINARY_INTEGER. Una transacción 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 transacción 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 anónimo o del procedimiento almacenado.
  • 66. PL/SQL I VERSIÓN 1 JPV-99 66 / 67 11. EVALUACIÓN 1 En PL/SQL, pueden incorporarse órdenes DDL a) Siempre b) Sólo a través de SQL Dinámico c) Nunca 2 En un bloque PL/SQL, la declaracíon 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 daría 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 compilaría porque en la declaración no puede asignarse una variable a un número b) Mayor c) Otro
  • 67. PL/SQL I VERSIÓN 1 JPV-99 67 / 67 4 La sentencia ROLLBACK sirve para: a) Volver al bloque BEGIN / END anterior al que pertenece b) Reenvía de nuevo la transacción al usuario c) Deshace todos los cambios pendientes de la transacción actual 5 Defina bloque PL/SQL anónimo: ............................................................................................................... ............................................................................................................... ............................................................................................................... ............................................................................................................... 6 Definición y usos del tipo PLS_Integer: ............................................................................................................... ............................................................................................................... ............................................................................................................... ............................................................................................................... 7 Definición, usos y declaración de un cursor: ............................................................................................................... ............................................................................................................... ............................................................................................................... ...............................................................................................................
  • 68. PL/SQL II VERSIÓN 1 JPV-99 1 / 50 PPLL//SSQQLL IIII Javier Pérez-Vigo (Octubre 1999)
  • 69. PL/SQL II VERSIÓN 1 JPV-99 2 / 50 INTRODUCCIÓN En la unidad didáctica PL/SQL I se estudiaron los bloques PL/SQL anónimos que se compilaban cada vez que eran ejecutados. Las estructuras que se verán en esta unidad didáctica, (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 sólo puede contener órdenes DML y no DDL. Sin embargo esta restricción se supera a partir de la versión 2.1 con el paquete DBMS_SQL. Este paquete implementa código PL/SQL y SQL dinámico, al que se llama desde otros bloques PL/SQL. En el capítulo 4º de esta unidad se verá cómo utilizar el paquete DBMS_SQL y sus implicaciones.
  • 70. PL/SQL II VERSIÓN 1 JPV-99 3 / 50 CONTENIDO: 1. PROCEDIMIENTOS Y FUNCIONES PROCEDIMIENTOS FUNCIONES SUBPROGRAMAS LOCALES. CONTROL DE PROCEDIMIENTOS Y FUNCIONES. 2. DESARROLLO Y UTILIZACIÓN DE PAQUETES PAQUETES (PACKAGES) FUNCIONES DENTRO DE PAQUETES. 3. DISPARADORES (TRIGGERS) CONCEPTO DE DISPARADORES (TRIGGERS) CREACIÓN DE DISPARADORES CONCEPTO DE TABLA MUTANTE 4. PL/SQL DINÁMICO CONCEPTO MÉTODOS DE IMPLEMENTACIÓN 5. EJERCICIO DE DESARROLLO 6. RESUMEN 7. EVALUACIÓN
  • 71. PL/SQL II VERSIÓN 1 JPV-99 4 / 50 OBJETIVOS El alumno tras el estudio de esta unidad didáctica podrá: Conocer y utilizar los procedimientos y funciones almacenados a través del lenguaje PL/SQL. Crear y utilizar los paquetes, packages. Conocer y utilizar los disparadores. Entender los fundamentos del PL/SQL dinámico. EXPECTATIVAS • ·························································································································· ························································································································ • ·························································································································· ························································································································ • ·························································································································· ························································································································
  • 72. PL/SQL II VERSIÓN 1 JPV-99 5 / 50 1. PROCEDIMIENTOS Y FUNCIONES CONCEPTO DE PROCEDIMIENTOS Y FUNCIONES Los bloques PL/SQL forman una estructura de bloques anónimos, 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 función 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 función pueden llamarse desde multitud de lados: SQL*, Forms o cualquier otra herramienta ORACLE. NOTA
  • 73. PL/SQL II VERSIÓN 1 JPV-99 6 / 50 PPRROOCCEEDDIIMMIIEENNTTOOSS CREACIÓN 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; /
  • 74. PL/SQL II VERSIÓN 1 JPV-99 7 / 50 • Los tipos de los argumentos son: IN, OUT, IN OUT Indican si el parámetro es de entrada, salida o ambos. Si no se pone nada se supone que es IN. • IS o AS llevan implícito el DECLARE, así que las variables se declaran inmediatamente después de IS o AS. • Un procedimiento termina con END o con END seguido del nombre del procedimiento. No puede haber declaración de argumentos, es decir, en las declaraciones de tipo NUMBER, VARCHAR2 o DATE no puede figurar ni la escala ni la precisión. 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 sólamente CREATE, ya que de existir el procedimiento en el núcleo podemos destruirlo. NOTA
  • 75. PL/SQL II VERSIÓN 1 JPV-99 8 / 50 BORRADO Para borrar un procedimiento se utiliza: DROP PROCEDURE Nombre_procedimiento; EJECUCIÓN Los procedimientos (o funciones) que se declaran como locales a un bloque PL/SQL se situarán 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
  • 76. PL/SQL II VERSIÓN 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 comisión 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 número de departamento es el 20 se insertará en la tabla EMP con una comisión = 1000 y no se insertará en la tabla EMPLEADOS. En cualquier otro caso introducir el empleado en la tabla EMPLEADOS. • Modificar el número de argumentos pasados al procedimiento añadiendo uno que sea insertados el cual va a indicar el número de elementos que se han insertado en la tabla empleados. Mostrar dicho número desde el bloque PL/SQL con un mensaje. PRÁCTICA
  • 77. PL/SQL II VERSIÓN 1 JPV-99 10 / 50 FFUUNNCCIIOONNEESS CREACIÓN DE FUNCIONES Utilizaremos la siguiente sentencia: CREATE [OR REPLACE] FUNCTION nombre_función [(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; /
  • 78. PL/SQL II VERSIÓN 1 JPV-99 11 / 50 • Como TIPO: IN, OUT, IN OUT • Return de una función no lleva ni escala ni precisión. • Return puede llevar expresiones. • El tipo de dato no puede incluir escala o precisión. • Una función puede tener más de un return. • Si declaramos una sin return da un error. BORRADO Para borrar una función se utiliza: DROP FUNCTION Nombre_procedimiento; EJECUCIÓN Los argumentos OUT o IN OUT son válidos dentro de las funciones pero se usan raramente. NOTA ♦ Una función 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
  • 79. PL/SQL II VERSIÓN 1 JPV-99 12 / 50 • Una función se puede invocar desde una sentencia SELECT, WHERE, HAVING, cláusula 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 función dentro de una sentencia SQL: • Debe de ser una función 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 están 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
  • 80. PL/SQL II VERSIÓN 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 función que nos permita realizar una consulta del salario del empleado de la tabla EMP que se le pasa como parámetro desde SQL* (se le pasa el número del empleado). Si la consulta ha sido satisfactoria la función devuelve un SI, en caso contrario devuelve un NO. • Utilizar desde el SQL para llamar a la función: dbms_output.put_line(‘¿Existe el empleado?’||di_si_existe(&empleado)); PRÁCTICA
  • 81. PL/SQL II VERSIÓN 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 múltiplo 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 máximo jefe. • Obtener su máximo jefe utilizando una función. 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 través de un procedimiento a partir del cual se va a obtener el puesto que ocupa cada empleado en la empresa en cuestión de salario + comisión. • Utilizar un cursor para cargar la tabla.
  • 82. PL/SQL II VERSIÓN 1 JPV-99 15 / 50 CCOONNTTRROOLL DDEE PPRROOCCEEDDIIMMIIEENNTTOOSS YY FFUUNNCCIIOONNEESS.. DOCUMENTACIÓN DE PROCEDIMIENTOS Y FUNCIONES. A través 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 través de la vista del diccionario de datos USER_SOURCE se puede obtener el código de los siguientes elementos dentro de un esquema: • FUNCTION • PACKAGE • PACKAGE BODY • PROCEDURE
  • 83. PL/SQL II VERSIÓN 1 JPV-99 16 / 50 • Para visualizar el nombre de un procedimiento o función y su lista de argumentos utilizaremos el comando DESCRIBE. DESC[RIBE] Nombre_procedimiento o Nombre_función; • Para mostrar el texto de los errores de compilación utilizaremos la vista USER_ERRORS. • Para visualizar los errores de compilación utilizaremos la siguiente sentencia: SHOW ERRORS PROCEDURE o FUNCTION o PACKAGE o PACKAGE BODY o TRIGGER nombre_objeto; DEPURACIÓN DE PROCEDIMIENTOS Y FUNCIONES. • Para activar este procedimiento utilizaremos la opción SET SERVEROUTPUT ON • Para preparar el texto del mensaje de salida se utiliza PUT. DBMS_OUTPUT.PUT (Texto); ♦ Para la depuración de procedimientos y funciones se utiliza el procedimiento suministrado por Oracle: DBMS_OUTPUT IMPORTANTE
  • 84. PL/SQL II VERSIÓN 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 (opción más utilizada) • Estos procedimientos están 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
  • 85. PL/SQL II VERSIÓN 1 JPV-99 18 / 50 Este sería el diagrama en el que se explica el funcionamiento del DBMS_OUTPUT: La salida DBMS_OUTPUT es independiente para cada sesión. NOTA Para que no nos dé un error debido a que el buffer es muy pequeño, conviene inicializarlo mediante el comando: SET SERVEROUTPUT ON size 1000000 NOTA
  • 86. PL/SQL II VERSIÓN 1 JPV-99 19 / 50 2. DESARROLLO Y UTILIZACIÓN DE PAQUETES PPAAQQUUEETTEESS ((PPAACCKKAAGGEESS)) Estructura de un paquete: PÚBLICA Variable Pública Declaración del Procedimiento A Procedimiento Público Variable Privada Definición del Procedimiento B Definición del Procedimiento A Variable local Procedimiento Privado Procedimiento Público PRIVADA PACKAGE PACKAGE BODY Zona de Especificación Cuerpo del paquete ♦ Un paquete es un grupo de identificadores y rutinas agrupadas dentro de la misma construcción. IMPORTANTE
  • 87. PL/SQL II VERSIÓN 1 JPV-99 20 / 50 CREACIÓN DE PAQUETES Para crear un paquete: CREATE [OR REPLACE] PACKAGE Nombre_paquete IS O AS Declaración variable Declaración cursor Declaración excepción Declaración procedimiento Declaración función END Nombre_paquete Para la creación del cuerpo del paquete: CREATE [OR REPLACE] PACKAGE BODY Nombre_paquete IS O AS Declaración variable Declaración cursor Declaración excepción Código del procedimiento Código de la función [BEGIN Código de inicialización del paquete] END Nombre_paquete • Para borrar un paquete y el cuerpo del paquete se utiliza. DROP PACKAGE Nombre_paquete
  • 88. PL/SQL II VERSIÓN 1 JPV-99 21 / 50 • Para borrar el cuerpo del paquete se utiliza. DROP PACKAGE BODY Nombre_paquete • Para invocar un procedimiento o función 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_función ó 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
  • 89. PL/SQL II VERSIÓN 1 JPV-99 22 / 50 • Los packages disponen de la opción de sobrecarga de procedimientos y funciones, es decir, con el mismo nombre y distintos argumentos. No se pueden sobrecargar si difieren sólo en el modo (IN OUT). No se pueden sobrecargar si difieren sólo en el tipo de dato devuelto. No se pueden sobrecargar si difieren sólo en la familia del tipo de dato. NOTA DECLARE FUNCTION value_ok (date_in IN DATE) RETURN BOOLEAN IS BEGIN RETURN date_in <= SYSDATE; Date Version END; FUNCTION value_ok (num_in IN NUMBER) RETURN BOOLEAN IS BEGIN RETURN number_in > 0; Number Version END; BEGIN IF value_ok (SYSDATE) THEN ... END IF; IF value_ok (total_sales) THEN ... END IF; END;
  • 90. PL/SQL II VERSIÓN 1 JPV-99 23 / 50 • Podemos cambiar el cuerpo sin cambiar la cabecera. Si cambiamos la cabecera y no el cuerpo éste queda inválido, siendo necesario volver a compilarlo. • Para compilar los objetos inválidos 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 depuración de una función dentro de un paquete cuando se crea un paquete (en la especificación). • El nivel de depuración determina qué operaciones no van a ser realizadas por la función del paquete. • No se puede utilizar una función que está dentro de un paquete en una sentencia SQL. Es necesario indicar el nivel de depuración.
  • 91. PL/SQL II VERSIÓN 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 especificación del paquete detrás de todas las funciones. El argumento WNDS debe indicarse SIEMPRE que se utilice RESTRICT_REFERENCES. WNDS -> (Writes No Database State) Indica que la función no va modificar tablas de la base de datos WNPS -> (Writes No Package Status) Indica que la función no va a cambiar los valores de variables de un paquete público. RNDS -> (Reads No Database State) Indica que la función no va aconsultar ninguna tabla de la base de datos. RNPS-> (Reads No Package Status) Indica que la función no va a referenciar los valores de las variables de un paquete público. 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; /
  • 92. PL/SQL II VERSIÓN 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; /
  • 93. PL/SQL II VERSIÓN 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 trataría de recuperar desde un bloque PL/SQL los elementos de la tabla EMP cuya suma de su salario + comisión > 2000 e ir introduciéndolos en la tabla del paquete recién creado a partir de la función pr_insertar. • Consultar desde el bloque PL/SQL el índice del paquete y obtener el número 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 función, 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 función desde SQL*. • La función fu_inicializa borra la tabla y pone el índice a 0. PRÁCTICA
  • 94. PL/SQL II VERSIÓN 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 número me va a devolver el salario de la persona que se encuentra en la posición 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 número 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 pública) las personas con una antigüedad mayor que la pasada como parámetro de forma ordenada por fecha . Se trata de una tabla de registros con los campos Nombre, antigüedad. Extraer cada uno de esos empleados de la tabla, visualizando el nombre del empleado y el número de días que lleva en la empresa. EJERCICIO 10 • Ampliar el primer paquete creado con la función 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 comisión sea mayor que el valor devuelto por la función fu_media_comision.
  • 95. PL/SQL II VERSIÓN 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 implícitamente cuando se ejecuta una sentencia de manipulación 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. (Común en desnormalizaciones). En la auditoría de la información contenida en la tabla, registrando los cambios realizados y la identidad de quien lo llevó a cabo. El aviso automático a otros programas de que hay que llevar a cabo una determinada acción, 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 instrucción SQL se va a ejecutar sobre dicha tabla. IMPORTANTE
  • 96. PL/SQL II VERSIÓN 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 través de la vista del diccionario de datos USER_TRIGGERS. Clasificación: Según el momento en el que salta el disparador *BEFORE * AFTER Según el tipo de operación que provoca su actuación * INSERT * UPDATE * DELETE Según las veces que se ejecuta el cuerpo del disparador * Sentencia * Fila En la figura de abajo se disparan los triggers para la operación que contiene la cláusula WHERE: WHERE ENAME LIKE 'J%': • Dentro de un disparador están prohibidas sentencias transaccionales: COMMIT, ROLLBACK y SAVEPOINT. NOTA
  • 97. PL/SQL II VERSIÓN 1 JPV-99 30 / 50 • Para borrar un trigger utilizaremos: DROP TRIGGER Nombre_trigger CCRREEAACCIIÓÓNN 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 Condición_restricción] [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 inserción el valor antiguo es NULL, durante el borrado el valor nuevo es NULL. • El cualificador :NEW puede aparecer a la izquierda de una asignación en el cuerpo PL/SQL solamente en disparadores de fila BEFORE. No puede aparecer en la
  • 98. PL/SQL II VERSIÓN 1 JPV-99 31 / 50 parte izquierda de una asignación 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 asignación. ACTIVACIÓN 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 compilación, 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 sintácticamente 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
  • 99. PL/SQL II VERSIÓN 1 JPV-99 32 / 50 ORDEN DE EJECUCIÓN DE LOS DISPARADORES Los disparadores se ejecutan según 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 modificación sobre la misma tabla. Esto provoca que la tabla quede mutante por la incosistencia de la información en ese instante y da un error por pantalla. ♦ Una tabla mutante es una tabla que está modificándose actualmente por una orden DML (INSERT, UPDATE, DELETE). Para un disparador, ésta es la tabla sobre la que está definido. IMPORTANTE
  • 100. PL/SQL II VERSIÓN 1 JPV-99 33 / 50 La solución del error de la tabla mutante consistiría 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 utilizarán los valores almacenados por el disparador de sentencia: BEFORE -> Inicializa BEFORE EACH ROW -> Almacena AFTER -> Procesa Si una operación INSERT afecta a una única fila, entonces los disparadores de fila previo y posterior por dicha fila no tratarán 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;
  • 101. PL/SQL II VERSIÓN 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 más 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 número de departamento, compruebe que este número sea múltiplo de diez. PRÁCTICA
  • 102. PL/SQL II VERSIÓN 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 operación sobre la tabla EMP (inserción, modificación,borrado), realice una inserción 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 máximo y el mínimo 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 más 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.
  • 103. PL/SQL II VERSIÓN 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 comisión no sea mayor que la del jefe con menor comisión. • 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.
  • 104. PL/SQL II VERSIÓN 1 JPV-99 37 / 50 4. PL/SQL DINÁMICO CCOONNCCEEPPTTOO Mediante el DBMS_SQL podemos manejar también órdenes DML. Las órdenes SQL Dinámicas tienen muy pocas restricciones, porque si se desea, la orden completa SQl se puede determinar en el momento de la ejecución, en lugar de en la compilación. Desventajas: • El SQL Dinámico no se ejecuta con la misma eficiencia que el estático. • Aquellas tablas a las que se hace referencia no aparecerán en USER_DEPENDENCES. ♦ El PL/SQL dinámico 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 dinámicamente surge al hacer referencia a una tabla, que se creará en ejecución; por lo que si la orden que la refiere estuviera en SQL estático, no compilaría. NOTA
  • 105. PL/SQL II VERSIÓN 1 JPV-99 38 / 50 • Cuando se borra una tabla dinámicamente, es labor del usuario el cambiar el estado de los paquetes que hagan referencia a dicha tabla. PROCEDIMIENTOS DE SQL DINÁMICO: • Función 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 • Función DBMS_SQL.IS_OPEN (c IN INTEGER) RETURN BOOLEAN; Comprueba si el cursor ya está abierto. • Procedure DBMS_SQL.BIND_VARIABLE (cursor IN INTEGER, ‘:variable_usada’ IN VARCHAR2, dato a incluir IN <datatype>); Asigna las variables a la sentencia. • Procedure DBMS_SQL.DEFINE_COLUMN (cursor IN INTEGER, position_en_la_select_de_la_columna IN INTEGER, columna_variable IN <column_datatype>); Tipos de datos de las columnas para crear variables locales. • Función DBMS_SQL.EXECUTE (cursor IN INTEGER) RETURN INTEGER; Ejecuta la sentencia asociada al cursor. • FUNCTION DBMS_SQL.FETCH_ROWS
  • 106. PL/SQL II VERSIÓN 1 JPV-99 39 / 50 (cursor IN INTEGER) RETURN INTEGER; Recoge la siguiente fila del cursor • PROCEDURE DBMS_SQL.COLUMN_VALUE (cursor IN INTEGER, posicion IN INTEGER, valor OUT <datatype>, [, column_error OUT NUMBER] [, actual_length OUT INTEGER ]); Introduce el valor del cursor en variables locales • PROCEDURE DBMS_SQL.CLOSE_CURSOR (cursor IN OUT INTEGER); Cierra el cursor. MMÉÉTTOODDOOSS DDEE IIMMPPLLEEMMEENNTTAACCIIÓÓNN ♦ Existen varios métodos distintos de implementar SQL Dinámico: • Ejecución de órdenes DML • Ejecución de órdenes DDL que no sean consultas • Ejecución de consultas IMPORTANTE
  • 107. PL/SQL II VERSIÓN 1 JPV-99 40 / 50 EJECUCIÓN DE ÓRDENES DML Estructura de la orden: • Abir el cursor (OPEN_CURSOR) • Analizar la orden (PARSE) • Cerrar el cursor (CLOSE_CURSOR) DECLAREt_owner varchar2(30) := 'ACADEMIA'; CURSOR all_obj_cur IS SELECT table_name ,trigger_name FROM user_triggers WHERE STATUS='DISABLED' order by table_name,trigger_name; disable_cursor INTEGER; out_str VARCHAR2(1000); BEGIN FOR obj_rec IN all_obj_cur LOOP disable_cursor := DBMS_SQL.OPEN_CURSOR; out_str := 'ALTER TRIGGER ' || obj_rec.trigger_name || ' ENABLE'; DBMS_SQL.PARSE (disable_cursor, out_str, DBMS_SQL.NATIVE); DBMS_SQL.CLOSE_CURSOR (disable_cursor); END LOOP; END; /
  • 108. PL/SQL II VERSIÓN 1 JPV-99 41 / 50 CREATE OR REPLACE PROCEDURE UpdateSal( p_Department IN emp.deptno%TYPE, p_NewSal IN emp.sal%TYPE, p_RowsUpdated OUT INTEGER) AS v_CursorID INTEGER; v_UpdateStmt VARCHAR2(100); BEGIN -- Open the cursor for processing. v_CursorID := DBMS_SQL.OPEN_CURSOR; --Determine the SQL string. v_UpdateStmt := 'UPDATE emp SET sal = :nc WHERE deptno = :dept'; --Parse the statement. DBMS_SQL.PARSE(v_CursorID, v_UpdateStmt, DBMS_SQL.V7); --Bind p_NewSal to the placeholder :nc. EJECUCIÓN DE ÓRDENES DDL QUE NO SEAN CONSULTAS Estructura de la orden: • Abir el cursor (OPEN_CURSOR) • Analizar la orden (PARSE) • Acoplar todas las variables de entrada (BIND_VARIABLE) • Ejecutar la orden (EXECUTE) • Cerrar el cursor (CLOSE_CURSOR)
  • 109. PL/SQL II VERSIÓN 1 JPV-99 42 / 50 EJECUCIÓN DE CONSULTAS Estructura de la orden: • Abir el cursor (OPEN_CURSOR) • Analizar la orden (PARSE) • Acoplar todas las variables de entrada (BIND_VARIABLE) • Definir las variables de salida (DEFINE_COLUMN) • Ejecutar la consulta (EXECUTE) • Extraer las filas (FETCH_ROWS) • Devolver los resultados a variables (COLUMN_VALUE) • Cerrar el cursor (CLOSE_CURSOR) DBMS_SQL.BIND_VARIABLE(v_CursorID, ':nc', p_NewSal); --Bind p_Department to the placeholder :dept. DBMS_SQL.BIND_VARIABLE(v_CursorID, ':dept', p_Department); -- Execute the statement. p_RowsUpdated := DBMS_SQL.EXECUTE(v_CursorID); -- Close the cursor. DBMS_SQL.CLOSE_CURSOR(v_CursorID); EXCEPTION WHEN OTHERS THEN -- Close the cursor, then raise the error again. DBMS_SQL.CLOSE_CURSOR(v_CursorID); RAISE; END UpdateSal; /
  • 110. PL/SQL II VERSIÓN 1 JPV-99 43 / 50 CREATE OR REPLACE FUNCTION obtener_nombre (empno_in IN emp.empno%TYPE) RETURN VARCHAR2 IS cur INTEGER; out_str varchar2(1000); fdbk INTEGER; return_value emp.ename%TYPE := NULL; BEGIN cur := DBMS_SQL.OPEN_CURSOR; out_str := ('SELECT ename FROM emp WHERE empno = :id'); DBMS_SQL.PARSE (cur, out_str, DBMS_SQL.NATIVE); /* Define the first/only column as a string. */ DBMS_SQL.DEFINE_COLUMN (cur, 1, return_value, 100); /* Bind the specified contact ID into the SELECT. */ DBMS_SQL.BIND_VARIABLE (cur, 'id', empno_in); /* Execute and fetch from the cursor. */ fdbk := DBMS_SQL.EXECUTE (cur); fdbk := DBMS_SQL.FETCH_ROWS (cur); /* Fetch the row. If feedback is 0, no match found */ IF fdbk = 1 THEN /* A record was fetched. Retrieve the name. */ DBMS_SQL.COLUMN_VALUE (cur, 1, return_value); END IF; DBMS_SQL.CLOSE_CURSOR (cur); RETURN return_value; END obtener_nombre; /
  • 111. PL/SQL II VERSIÓN 1 JPV-99 44 / 50 Procurar siempre cerrar todos los cursores una vez ejecutada la sentencia, incluso a través de las excepciones. NOTA No utilice comentario especificados con – dentro de un bloque PL/SQL ejecutado con DBMS_SQL. El símbolo de doble guión hace que se considere como comentario todo lo que sigue, hasta encontrar un carácter de avance de linea. Sin embargo, dado que el bloque completo se encuentra en una cadena, todo el resto del bloque sería considerado un comentario. Utilice los comentarios de estilo C delimitados por /* y */ en su lugar. NOTA
  • 112. PL/SQL II VERSIÓN 1 JPV-99 45 / 50 EJERCICIO SOBRE CURSORES DINÁMICOS EJERCICIO 17 • Desactivar todas las constraints de la base de datos teniendo en cuenta que en primer lugar hay que desactivar las Primary y Unique y en segundo lugar las Foreign y Check constraints. NOTA: La notación del campo CONSTRAINT_TYPE es la siguiente: P Primary Key U Unique Key R Foreign Key C Check constraint • Crear el procedimiento contrario siguiendo el orden inverso. EJERCICIO 18 • Crear un procedimiento que nos obtenga dinámicamente el nombre del departamento y la localización del número del departamento que le pasemos. EJERCICIO 19 • Codificar un procedimiento que cree una tabla copia de la de empleado y a través de un parámetro en que le pasamos el nombre del empleado, copiar los datos del empleado requerido en la nueva tabla. PRÁCTICA
  • 113. PL/SQL II VERSIÓN 1 JPV-99 46 / 50 5. EJERCICIO DE DESARROLLO 1.-Crear una tabla TMP+Nombre_usuario que sea una copia de la de Empleado 1.1- Añadirle los campos Usuario y Fecha modificación. 1.2- Crear un disparador que audite el usuario y la fecha en que se inserta o se modifica dicha tabla. 2.- Mediante un cursor Modificar dicha tabla y subir el sueldo a los empleados que pertenezcan al departamento SALES 3.- Crear una función que devuelva la media de sueldo de los empleados que tengan el mismo puesto (JOB) pasándole como parámetro en formato texto dicho cargo. 4.- Crear un disparador tal que cuando modifiquemos el sueldo del presidente, se encargue de recalcular el resto de los sueldos de todos los empleados en el mismo porcentaje. 5.- Crear un procedimiento que actualice la fecha HIREDATE al primer día del siguiente mes del día de la semana que coincida con la fecha anterior. 6.- Crear un procedimiento dinámico que borre todos los objetos de la base de datos del tipo que nosotros le pasemos como parámetro del usuario que está conectado. Si no se le pasa ningún parámetro, debe borrar todos. (Excepto el propio procedimiento creado).
  • 114. PL/SQL II VERSIÓN 1 JPV-99 47 / 50 6. RESUMEN Un procedimiento es un conjunto de instrucciones PL/SQL que puede ser llamado usando el nombre que se le haya asignado. Una función 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. Un procedimiento se invoca con la sentencia EXEC[UTE] desde SQL*. Desde un bloque PL/SQL simplemente es necesario nombrarlo para ejecutarlo. Una función 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. Los subprogramas se incluyen en el DECLARE del bloque y es necesario incluir el subprograma entero. Para la depuración de procedimientos y funciones se utiliza el procedimiento suministrado por Oracle: DBMS_OUTPUT Un paquete es un grupo de identificadores y rutinas agrupadas dentro de la misma construcción.
  • 115. PL/SQL II VERSIÓN 1 JPV-99 48 / 50 Un disparador es un bloque PL/SQL asociado a una tabla que se ejecuta cuando una determinada instrucción SQL se va a ejecutar sobre dicha tabla. Una tabla mutante es una tabla que está modificándose actualmente por una orden DML (INSERT, UPDATE, DELETE). Para un disparador, ésta es la tabla sobre la que está definido. El PL/SQL dinámico nace de la necesidad de implementar órdenes DDL dentro de un bloque de PL/SQL. Se implementa en el paquete DBMS_SQL Existen varios métodos distintos de implementar SQL Dinámico: Ejecución de órdenes DML Ejecución de órdenes DDL que no sean consultas Ejecución de consultas
  • 116. PL/SQL II VERSIÓN 1 JPV-99 49 / 50 7. EVALUACIÓN 1. Para ejecutar un procedimiento desde SQLPLUS utilizaremos la sentencia: a) START procedimiento b) EXEC procedimiento c) RUN procedimiento 2. ¿Cual de estas sentencias es incorrecta? a) Las funciones no pueden llevar argumentos, sólo devuelven valores b) Los procedimientos pueden llevar parámetros IN y OUT c) Las funciones PL/SQl que están dentro de sentencias SQL no pueden modificar datos en las tablas. 3. ¿Cual de estas sentencias es incorrecta? a) La sobrecarga de los packages surge a partir del décimo procedimiento b) Los packages disponen de la opción de sobrecarga de procedimientos y funciones c) Para que no haya sobrcarga en un package debemos indicar en la cabecera el nivel de depuración
  • 117. PL/SQL II VERSIÓN 1 JPV-99 50 / 50 4. Un disparador .. a) Permite argumentos b) No permite sentencias transaccionales (Commit, rollback…) c) Permite ejecutarse desde un procedimiento mediante la orden EXEC TRIGGER nombre_de_trigger 5. Una tabla mutante es: a) Una tabla que se altera cuando dos usuarios modifican los datos de una tabla a la vez. b) Una tabla que se está modificándose actualmente por una orden DML debido a un trigger FOR_EACH_ROW c) Un tabla que se modifica porque un usuario ejecuta un procedimiento a la vez que otro ejecuta una sentencia DML 6. ¿Qué tipo de error puede dar lugar en un cursor? a) NO_DATA_FOUND b) TOO_MANY_ROWS c) VALUE_ERROR
  • 118. ANEXOS A CURSO PL/SQL VERSIÓN 1 JPV- 99 1 / 49 AANNEEXXOOSS AA CCUURRSSOO PPLL//SSQQLL Javier Pérez-Vigo (Octubre 1999)
  • 119. ANEXOS A CURSO PL/SQL VERSIÓN 1 JPV- 99 2 / 49 AANNEEXXOO 11:: SSQQLL**PPLLUUSS La herramienta que nos proporciona ORACLE para interactuar con la base de datos se llama SQL*Plus. Básicamente, es un intérprete SQL con algunas opciones de edición y formateo de resultados. Conceptos previos antes de conectarse a SQL*Plus: • Usuario/Clave Para poder acceder a una base de datos gestionada por ORACLE debemos ser un usuario autorizado de la misma y conocer la palabra clave, password, asociada al usuario. • Variable de ambiente ORACLE_SID Indica la base de datos con la que vamos a trabajar. 11 CCOONNEEXXIIÓÓNN Para entar en SQL*Plus se debe ejecutar el comando $ sqlplus usuario/passwd donde le indicamos al SGBD Oracle quién somos y nuestra palabra clave. Si la configuración del SGBD Oracle se corresponde a una configuración cliente-servidor asentada sobre una red (SQL*Net v2) deberemos indicar, además, el sevicio (o base de datos) con el que queremos contactar. Esto se hace colocando el símbolo @ antes del nombre del servicio como se indica a continuación: $ sqlplus usuario/passwd@servicio Otra circunstancia que hay que tener en cuenta a la hora de conectarnos a SQL*Plus es el modo establecido por el DBA para la autentificación del usuario de la base de datos. La primera posibilidad es que recaiga sobre el SGBD Oracle la autentificación de los usuarios, por lo que tendremos que darle nuestro nombre de usuario y la palabra de paso. Pero existe la posibilidad de que el SGBD Oracle deje en manos del Sistema Operativo esta responsabilidad. Así, no será necesario demostrarle al SGBD Oracle quién somos ya que el SO se ha encargado previamente de comprobar que todo es correcto. En este segundo caso, el comando de conexión con SQL*Plus debe omitir el nombre de usuario y la palabra clave, pero manteniendo el resto de esta manera: $ sqlplus /@servicio
  • 120. ANEXOS A CURSO PL/SQL VERSIÓN 1 JPV- 99 3 / 49 Una vez que hemos conseguido entrar en SQL*Plus nos presenta el prompt y espera la insercción de sentencias SQL. Todas las sentencias deben acabar con un ';'. Una sentencia puede continuar en varias líneas, que SQL*Plus va numerando. Si queremos anular la sentencia actual podemos hacerlo colocando un '.' como único carácter en una línea. Si queremos volver a ejecutar la última sentencia se puede hacer con el comando '/'. Si queremos ejecutar las sentencias que almacena un fichero .sql podemos hacerlo anteponiendo el símbolo '@' al nombre del fichero. Para cerrar la sesión vale con teclear 'exit'. 22 PPOOSSIIBBIILLIIDDAADDEESS DDEE EEDDIICCIIÓÓNN SQL*Plus almacena en un buffer la última sentencia SQL introducida. El buffer mantiene sólo una sentencia cada vez, y si se introduce una nueva sentencia se sobreescribe sobre la anterior. La sentencia en el buffer puede ser recuperada para ejecutarla de nuevo con los comandos: • RUN que visualiza la sentencia en el buffer antes de ejecutarla; • / que ejecuta la sentencia sin visualizarla. SQL*Plus también nos permite editar la sentencia SQL alamacenada en el buffer mediante un sencillo (y limitado) editor en línea, cuyos comandos se enumeran a continuación: Comando Abreviatura Descripción APPEND texto A texto Añade texto al final de la línea. CHANGE/fuente/destino C/fuente/destino Cambia el contenido 'fuente' por el 'destino' CHANGE/texto C/texto Quita 'texto' de una línea. CLEAR BUFFER CL BUFF Borra el buffer DEL DEL Borra una línea. INPUT I Inserta una o más líneas. INPUT texto I texto Inserta una línea con 'texto'. LIST L Lista las líneas del buffer LIST n L n ó n Lista la línea n-ésima. LIST * L * Lista la línea actual. LIST LAST L LAST Lista la última línea. LIST m n L m n Lista las líneas desde la m-ésima a la n-ésima. Al contenido del buffer también se puede acceder desde el editor del Sistema Operativo. Así, el buffer podrá ser manipulado con las posibilidades del editor con el que estemos
  • 121. ANEXOS A CURSO PL/SQL VERSIÓN 1 JPV- 99 4 / 49 acostumbrados a trabajar. Al salir del editor se devuelve el control al SQL*Plus. Para conseguir trabajar con el editor del Sistema Operativo basta con colocar la variable DEFINE_EDITOR y luego llamar al editor. SQL> define_editor=vi SQL> edit 33 UUTTIILLIIZZAACCIIÓÓNN DDEE FFIICCHHEERROOSS SQL*Plus considera dos tipos de ficheros: de spool y de comandos. Un fichero de spool almacena los resultados de una consulta (o varias) en un fichero con la extensión .lst (o lo manda a la impresora). Los comandos asociados con los ficheros spool son SPOOL fichero Manda el resultado de las consultas al fichero. SPOOL OUT Manda el resultado de las consultas a la impresora. SPOOL OFF Cierra el fichero de spool. EXIT Al salir de SQL*Plus se cierran los ficheros de spool. Los archivos de comandos almacenan comandos SQL y SQL*Plus para ser editado, almacenado y/o ejecutado; y tienen por defecto la extensión .sql : • Para editarlo se puede utilizar el comando edit fichero. • Para ejecutarlo se utilizará el comando START fichero o @fichero 44 AALLMMAACCEENNAAMMIIEENNTTOO YY RREECCUUPPEERRAACCIIÓÓNN DDEE FFIICCHHEERROOSS DDEE CCOOMMAANNDDOOSS Un fichero de comandos es una secuencia de órdenes SQL y SQL*Plus almacenados en un fichero del sistema operativo. • Comando SAVE: Almacena en un fichero en disco el contenido del búffer activo. SAVE nombre_fichero [APPEND|CREATE|REPLACE] • Comando GET: Para recuperar un fichero de comandos. GET nombre_fichero [LIST|NOLIST]