Plsql Oracle
-
Upload
rodrigo-oviedo -
Category
Documents
-
view
181 -
download
3
Transcript of Plsql Oracle
-
Resumen PL/SQL II Pgina 1
FEBRERO - 2009
Resumen PL/SQL II Curso Base de Datos
CURSO
BASE DE
DATOS PL / SQL
-
Resumen PL/SQL II Pgina 2
Sentencia SELECT en PL/SQL
PL/SQL admite el uso de un SELECT que permite almacenar valores en variables. Es el llamado
SELECT INTO.
Su sintaxis es:
SELECT
INTO
FROM
La clusula INTO es obligatoria en PL/SQL y adems la expresin SELECT slo puede devolver
una nica fila, de otro modo, ocurre un error.
-
Resumen PL/SQL II Pgina 3
Sentencias DML y de transicin
Se pueden utilizar instrucciones DML dentro del cdigo ejecutable. Se permiten las
instrucciones INSERT, UPDATE y DELETE, con la ventaja de que en PL/SQL pueden utilizar
variables.
Las instrucciones de transaccin ROLLBACK y COMMIT tambin estn permitidas para anular o
confirmar instrucciones.
-
Resumen PL/SQL II Pgina 4
Sentencia de control - IF
Toma de decisiones. Permite especificar que ciertas instrucciones se ejecuten o no
dependiendo de una condicin
IF simple
Sintaxis:
IF THEN
END IF;
Las instrucciones se ejecutan en el caso de que la condicin sea verdadera. La condicin es
cualquier expresin que devuelva verdadero o falso.
DECLARE
V_STOCK NUMBER;
V_CODIGO VARCHAR2(13);
BEGIN
V_CODIGO := '&V_CODIGO';
SELECT STOCK_ART INTO V_STOCK FROM TARTICULO WHERE CODIGO_ART = V_CODIGO ;
IF V_STOCK > 0
THEN
DBMS_OUTPUT.PUT_LINE('STOCK '|| V_STOCK );
END IF;
END;
IF-THEN-ELSE
Sintaxis:
IF THEN
ELSE
END IF;
En este caso las instrucciones bajo el ELSE se ejecutan si la condicin es falsa.
-
Resumen PL/SQL II Pgina 5
DECLARE
V_STOCK NUMBER;
V_CODIGO VARCHAR2(13);
BEGIN
V_CODIGO := '&V_CODIGO';
SELECT STOCK_ART INTO V_STOCK FROM TARTICULO WHERE CODIGO_ART = V_CODIGO ;
IF V_STOCK > 0
THEN
DBMS_OUTPUT.PUT_LINE('STOCK '|| V_STOCK );
ELSE
DBMS_OUTPUT.PUT_LINE('No hay existencias de ste artculo' );
END IF;
END;
IF-THEN-ELSIF
Cuando se utilizan sentencias de control es comn desear anidar un IF dentro de otro IF.
IF THEN
ELSIF THEN
ELSIF THEN
ELSE
END IF;
DECLARE
V_STOCK NUMBER;
V_CODIGO VARCHAR2(13);
BEGIN
V_CODIGO := '&V_CODIGO';
SELECT STOCK_ART INTO V_STOCK FROM TARTICULO WHERE CODIGO_ART = V_CODIGO ;
IF V_STOCK > 1000
THEN
DBMS_OUTPUT.PUT_LINE('Demasiadas existencias STOCK '|| V_STOCK );
ELSIF V_STOCK > 100
THEN
DBMS_OUTPUT.PUT_LINE('Existencias correctas STOCK '|| V_STOCK );
ELSIF V_STOCK > 0
THEN
DBMS_OUTPUT.PUT_LINE('Escasas existencias STOCK '|| V_STOCK );
ELSE
DBMS_OUTPUT.PUT_LINE('No hay existencias de ste artculo' );
END IF;
END;
-
Resumen PL/SQL II Pgina 6
-
Resumen PL/SQL II Pgina 7
Sentencia de control - CASE
La sentencia CASE devuelve un resultado tras evaluar una expresin.
CASE
WHEN THEN
WHEN THEN
WHEN THEN
...
[ELSE ]
END;
Hay que tener en cuenta que la sentencia CASE sirve para devolver un valor y no para ejecutar
una instruccin.
-
Resumen PL/SQL II Pgina 8
Otra posibilidad de la sentencia CASE, es utilizar en las expresiones, condiciones. Este segundo
formato facilita la escritura de sentencias CASE ms complicadas.
CASE
WHEN THEN
WHEN THEN
...
[ELSE ]
END;
-
Resumen PL/SQL II Pgina 9
Sentencia de control repetitiva - LOOP
Se trata de una instruccin que contiene instrucciones que se repiten indefinidamente (bucle
infinito). Se inicia con la palabra LOOP y finaliza con la palabra END LOOP y dentro de esas
palabras se colocan las instrucciones que se repetirn.
Lgicamente no tiene sentido utilizar un bucle infinito, por eso existe una instruccin llamada
EXIT que permite abandonar el bucle. Cuando Oracle encuentra esa instruccin, el programa
contina desde la siguiente instruccin al END LOOP.
Lo normal es colocar EXIT dentro de una sentencia IF a fin de establecer una condicin de
salida del bucle. Tambin se puede acompaar a la palabra EXIT de la palabra WHEN seguida
de una condicin. Si se condicin es cierta, se abandona el bucle, sino continuamos dentro.
LOOP
...
EXIT [ WHEN ]
END LOOP;
DECLARE
CONT NUMBER ;
BEGIN
CONT :=101;
LOOP
DBMS_OUTPUT.PUT_LINE(CONT);
CONT:=CONT+1;
EXIT WHEN CONT>105;
END LOOP;
END;
-
Resumen PL/SQL II Pgina 10
Sentencia de control repetitiva - WHILE
Genera un bucle cuyas instrucciones se repiten mientras la condicin que sigue a la palabra
WHILE sea verdadera.
WHILE LOOP
...
END LOOP;
DECLARE
CONT NUMBER ;
BEGIN
CONT :=101;
WHILE CONT< 106 LOOP
DBMS_OUTPUT.PUT_LINE(CONT);
CONT:=CONT+1;
END LOOP;
END;
-
Resumen PL/SQL II Pgina 11
Sentencia de control repetitiva - FOR
Se utilizar para bucles con contador, bucles que se recorren un nmero concreto de veces.
Para ello se utiliza una variable (contador) que no tiene que estar declarada en el DECLARE,
esta variable es declarada automticamente en el propio FOR y se elimina cuando ste finaliza.
Se indica el valor inicial de la variable y el valor final (el incremento ir de uno en uno). Si se
utiliza la clusula REVERSE, entonces el contador cuenta desde el valor alto al bajo restando 1.
FOR IN [REVERSE] . . LOOP
...
END LOOP;
BEGIN
FOR CONT IN 101 .. 105 LOOP
DBMS_OUTPUT.PUT_LINE(CONT);
END LOOP;
END;
-
Resumen PL/SQL II Pgina 12
Sentencia de control - Bucles anidados
Se puede colocar un bucle dentro de otro sin ningn problema, puede haber un WHILE dentro
de un FOR, un LOOP dentro de otro LOOP, etc.
Hay que tener en cuenta que en ese caso, la sentencia EXIT abandonara el bucle en el que
estamos.
No obstante hay una variante de la instruccin EXIT que permite salir incluso del bucle ms
exterior. Eso se consigue poniendo una etiqueta a los bucles que se deseen. Una etiqueta es
un identificador que se coloca dentro de los signos > delante del bucle. Eso permite
poner nombre al bucle.
No es obligatorio poner la etiqueta en la instruccin END LOOP, pero se suele hacer por dar
mayor claridad al cdigo.
BEGIN
>
FOR CONT_1 IN 101 .. 200 LOOP
>
FOR CONT_2 IN 1 .. 5 LOOP
DBMS_OUTPUT.PUT_LINE(CONT_1||' - '|| CONT_2);
EXIT BUCLE_1 WHEN CONT_2 = 3;
END LOOP BUCLE_2;
END LOOP BUCLE_1;
END;
-
Resumen PL/SQL II Pgina 13
REGISTROS PL/SQL
Los registros de PL/SQL proporcionan un mecanismo para tratar con variables de distintos
tipos, pero relacionadas entre s. Es un tipo de dato compuesto, que debe ser definido por el
propio usuario. Antes de poder declarar una variable, debemos definir primero el tipo
compuesto.
TYPE IS RECORD (
[NOT NULL] [ := ] ,
[NOT NULL] [ := ] ,
.........
[NOT NULL] [ := ] ,);
Donde es el nombre del nuevo tipo definido, a
son los nombres de los campos incluidos en el registro, y son los tipos
correspondientes a dichos campos. Un registro podr tener tantos campos como se desee.
Cada declaracin de un campo dentro de un registro es semejante a la declaracin de una
variable, pudiendo incluir la restriccin NOT NULL y la especificacin de un valor inicial, siendo
ambas opcionales.
DECLARE
TYPE REGISTRO_EJEMPLO IS RECORD (
CAMPO1 NUMBER NOT NULL,
CAMPO2 VARCHAR2(5),
CAMPO3 VARCHAR2(5) := GETAFE );
V_REC1 REGISTRO_EJEMPLO;
V_REC2 REGISTRO_EJEMPLO;
Para hacer referencia a uno de los campos de un registro se emplea la notacin de punto. La
sintaxis ser .
v_Rec1.Field1
-
Resumen PL/SQL II Pgina 14
Para poder asignar un registro a otro, ambos registro deben de ser del mismo tipo. Una
asignacin de registros usa la semntica de copia, es decir, los valores de los campos del
registro de la derecha en la asignacin, son asignados a los campos correspondientes del
registro de la izquierda. No es permitida la asignacin de registros de distinto tipo, aunque
estos tuvieran exactamente la misma definicin de campos.
V_REC1 := V_REC2;
Tambin podemos asignar un valor a un registro mediante una instruccin SELECT, que
obtenga datos de una tabla y los almacene en un registro. Los campos del registro deben
corresponderse con los campos en la lista de seleccin de la consulta.
-
Resumen PL/SQL II Pgina 15
Resulta bastante habitual definir un registro con los mismos tipos que una fila de una tabla,
para facilitar esta tarea tenemos el operador %ROWTYPE. De forma similar al operador
%TYPE, %ROWTYPE devuelve un tipo basndose en la definicin de la tabla.
No se incluyen las restricciones NOT NULL, pero si modificamos la estructura de la tabla,
%ROWTYPE tambin lo hace si llamamos a un bloque annimo o compilando el objeto
almacenado.
-
Resumen PL/SQL II Pgina 16
Cursores
INTRODUCCION
El rea de contexto es la memoria designada para procesar una instruccin SQL, la cual incluye
El nmero de registros procesados.
Un apuntador a la representacin de la instruccin SQL analizada.
En el caso de una consulta, el conjunto de registros que regresan de la consulta.
Un cursor es un manejador o apuntador para el rea de contexto. Por medio de ste un programa PL/SQL puede controlar el rea de contexto.
Los cursores explcitos son aquellos que se declaran, generalmente por medio de una consulta SQL.
Los cursores implcitos son creados por Oracle para manejar alguna instruccin SQL y no son declarados por el programador.
El cursor implcito sirve para procesar las rdenes INSERT, UPDATE, DELETE y SELECT.....INTO de una sola fila. Puesto que es el motor de PL/SQL quien abre y cierra el cursor, las instrucciones OPEN, FETCH y CLOSE, no son necesarias para este tipo de cursor.
Pasos para procesar un cursor explcito
Declaracin del cursor
La consulta no debe contener la clusula INTO.
Se puede hacer referencia a variables dentro de la clusula WHERE.
CURSOR IS
Tambin es posible declarar una lista de parmetros:
CURSOR ( , ..., ) IS
-
Resumen PL/SQL II Pgina 17
Abrir el cursor
La sintaxis es: OPEN ;
Se examinan los valores de las variables.
El apuntador para el conjunto activo se establece en el primer registro.
Recuperar los resultados en variables PL/SQL
Tenemos dos formas:
FETCH INTO ;
FETCH INTO ;
Cerrar el cursor
La sintaxis es: CLOSE ;
Cuando se cierra el cursor, es ilegal tratar de usarlo. Es ilegal tratar de cerrar un
cursor que ya est cerrado o no ha sido abierto.
Atributos de cursores explcitos
Toman los valores TRUE, FALSE o NULL dependiendo de la situacin:
Atributo Antes de
abrir
Al
abrir
Durante la
recuperacin
Al finalizar la
recuperacin
Despus de
cerrar
%NOTFOUND ORA-1001 NULL FALSE TRUE ORA-1001
%FOUND ORA-1001 NULL TRUE FALSE ORA-1001
%ISOPEN FALSE TRUE TRUE TRUE FALSE
%ROWCOUNT ORA-1001 0 * ** ORA-1001
* Nmero de registros que ha recuperado hasta el momento ** Nmero de total de registros
-
Resumen PL/SQL II Pgina 18
Manejo del cursor por medio de ciclos
Por medio de ciclo LOOP. Debe tenerse cuidado de agregar una condicin para salir del ciclo:
OPEN ;
LOOP
FETCH INTO ;
EXIT WHEN %NOTFOUND;
/* Procesamiento de los registros recuperados */
END LOOP;
CLOSE ;
-
Resumen PL/SQL II Pgina 19
Por medio de un ciclo WHILE LOOP. La instruccin FETCH aparece dos veces.
OPEN ;
FETCH INTO ;
WHILE %FOUND LOOP
/* Procesamiento de los registros recuperados */
FETCH INTO ;
END LOOP;
CLOSE ;
-
Resumen PL/SQL II Pgina 20
Por medio de un ciclo FOR LOOP. Es la forma ms corta ya que el cursor es implcito, se
ejecutan las instrucciones OPEN, FETCH y CLOSE.
FOR variable IN LOOP
/* Procesamiento de los registros recuperados */
END LOOP;
-
Resumen PL/SQL II Pgina 21
Derivada de esta ltima forma, se puede utilizar un FOR, donde, sin previa declaracin del
cursor, se puede incluir la SELECT destinada a dicho cursor.
FOR variable IN ( SELECT . . . ) LOOP
/* Procesamiento de los registros recuperados */
END LOOP;
-
Resumen PL/SQL II Pgina 22
CURSORES CON PARMETROS
En muchas ocasiones se podra desear que el resultado de un cursor dependa de una variable.
Para hacer que el cursor vare segn esos parmetros, se han de indicar los mismos en la
declaracin del cursor. Para ello se pone entre parntesis su nombre y tipo sin longitud de
campo, tras el nombre del cursor en la declaracin.
Es al abrir el cursor cuando se indica el valor de los parmetros, lo que significa que se puede
abrir varias veces el cursor y que ste obtenga distintos resultados dependiendo del valor del
parmetro.
Se pueden indicar los parmetros tambin en el bucle FOR.
-
Resumen PL/SQL II Pgina 23
ACTUALIZACIONES AL RECORRER REGISTROS
En muchas ocasiones se realizan operaciones de actualizacin de registros sobre el cursor que
se est recorriendo. Para evitar problemas se deben bloquear los registros del cursor a fin de
detener otros procesos que tambin desearan modificar los datos. El mtodo consta de dos
partes: la clusula FOR UPDATE en la declaracin del cursor, y la clusula WHERE CURRENT OF
en una instruccin UPDATE o DELETE.
La clusula FOR UPDATE se coloca al final de la sentencia SELECT del cursor, ira detrs de
ORDER BY. Opcionalmente se puede colocar el texto NOWAIT para que el programa no se
quede esperando en caso de que la tabla est bloqueada por otro usuario. Se usa el texto OF
seguido del nombre del campo que se modificar, no es necesaria esa clusula, pero se
mantiene para clarificar el cdigo.
CURSOR ...
SELECT...
FOR UPDATE [ OF ] [NOWAIT]
A continuacin en la instruccin UPDATE que modifica los registros se puede utilizar una nueva
clusula llamada WHERE CURRENT OF seguida del nombre de un cursor, que hace que se
modifique slo el registro actual del cursor.
WHERE CURRENT OF
-
Resumen PL/SQL II Pgina 24
Excepciones
Introduccin al manejo de errores
La implementacin que hace Oracle para el manejo de errores es por medio de excepciones y
manejadores de excepciones.
Los errores pueden ser clasificados de acuerdo a la siguiente tabla:
Tipo de error Reportado por Cmo es manejado
En tiempo de
compilacin Compilador de PL/SQL
El programador corrige los errores que reporta el
compilador
En tiempo de
ejecucin
El motor de ejecucin
de PL/SQL
Las excepciones son lanzadas y capturadas por los
manejadores de excepciones
Las excepciones estn diseadas para manejar errores en tiempo de ejecucin.
Cuando un error ocurre, una excepcin es lanzada y el control pasa al manejador de la excepcin.
Declaracin de excepciones
Hay dos tipos de excepciones: las predefinidas y las definidas por el usuario.
Excepciones definidas por el usuario
Son errores que estn definidas en el programa, el cual no necesariamente es un error de Oracle. Las excepciones se declaran en la seccin declarativa de un bloque PL/SQL.
Las excepciones tienen un tipo (EXCEPTION) y un ambiente.
DECLARE E_ERROR1 EXCEPTION; BEGIN . . . END;
-
Resumen PL/SQL II Pgina 25
Excepciones predefinidas
Las excepciones predefinidas corresponden a errores comunes en SQL.
Error de
Oracle Excepcin equivalente Descripcin
ORA-0001 DUP_VAL_ON_INDEX Restriccin de unicidad violada
ORA-0051 TIMEOUT_ON_RESOURCE Tiempo fuera ocurrido mientras esperaba un recurso
ORA-0061 TRANSACTION_BACKED_OUT La transaccin fue desecha por un bloqueo
ORA-1001 INVALID_CURSOR Operacin ilegal con un cursor
ORA_1012 NOT_LOGGED_ON Sin conexin a Oracle
ORA-1017 LOGIN_DENIED Nombre de usuario o password invlido
ORA-1403 NO_DATA_FOUND No se encontraron datos
ORA-1422 TOO_MANY_ROWS La instruccin SELECT ... INTO devuelve ms de un
registro
ORA-1476 ZERO_DIVIDE Divisin por cero
ORA-1722 INVALID_NUMBER Conversin invlida a un nmero
ORA-6500 STORAGE_ERROR Error PL/SQL interno lanzado al exceder la memoria
ORA-6501 PROGRAM_ERROR Error PL/SQL interno
ORA-6502 VALUE_ERROR Error al trucar o convertir valores, o en una operacin
aritmtica
ORA-6532 SUBSCRIPT_OUTSIDE_LIMIT Una referencia a una tabla anidada o ndice de varray se
encuentra fuera del rango declarado.
ORA-6533 SUBSCRIPT_BEYOND_COUNT Una referencia a una tabla anidada o ndice de varray es
mayor que el nmero de elementos de la coleccin.
ORA-6511 CURSOR_ALREADY_OPEN Al intentar abrir un cursor que ya est abierto
-
Resumen PL/SQL II Pgina 26
Lanzamiento y manejo de excepciones
Las excepciones definidas por el usuario son lanzadas por medio de la instruccin RAISE, mientras que las excepciones predefinidas son lanzadas cuando ocurre el error de Oracle asociado.
Cuando la excepcin es lanzada, el control pasa a la seccin de excepciones de un bloque PL/SQL. Si no existe esta seccin, en el caso de bloques anidados el error se propaga al bloque que contiene al que reporta el error.
DECLARE -- Declaracin de la excepcin a EXCEPTION; BEGIN ... RAISE a; -- El resto del cdigo de esta seccin no es ejecutado ... EXCEPTION -- El control pasa al manejador cuando se lanza a WHEN a THEN -- Cdigo a ejecutar para manejar la excepcin END;
La seccin de excepciones consiste de una serie de manejadores. Un manejador de excepcin consiste del cdigo que es ejecutado cuando la excepcin es lanzada. La sintaxis es la siguiente:
EXCEPTION WHEN [ OR ] THEN ; WHEN [ OR ] THEN ; WHEN OTHERS THEN ; END;
-
Resumen PL/SQL II Pgina 27
Cuando se usa WHEN OTHERS y se desea saber que error ocurri, las funciones SQLCODE y SQLERRM proporcionan esta informacin.
SQLCODE
Regresa el cdigo del error que lanz la excepcin
SQLERRM
Regresa el mensaje de error correspondiente al error que lanz la excepcin.
Esta funcin tambin acepta un argumento numrico, el cual debe de corresponder al
texto asociado con ese nmero.
-
Resumen PL/SQL II Pgina 28
Excepciones sin definir
Pueden ocurrir otras muchas excepciones que no estn en la lista de ORACLE. En ese caso
aunque no tienen un nombre asignado, s tienen un nmero asignado. Ese nmero es el que
aparece cuando Oracle muestra el mensaje de error tras la palabra ORA.
Por ejemplo en un error por restriccin nica Oracle lanza un mensaje encabezado por el
texto:
ORA-00001: restriccin nica (A01.PK_TCATEGORIA_CODIGO_CAT) violada
Por lo tanto el error de integridad nica es el -00001.
Si deseamos capturar excepciones sin definir hay que declarar un nombre para la excepcin
que capturaremos. Eso se hace en el apartado DECLARE:
EXCEPTION;
Debemos asociar ese nombre al nmero de error correspondiente en el apartado DECLARE
mediante la siguiente sintaxis:
PRAGMA EXCEPTION_INIT( , );
En el apartado EXCEPTION capturaremos el nombre de la excepcin como si fuera una
excepcin normal.
-
Resumen PL/SQL II Pgina 29
Definicin de mensajes de error propios
El programador puede lanzar sus propias excepciones simulando errores del programa.
Para ello hay que declarar un nombre para la excepcin en el apartado DECLARE, al igual que para las excepciones sin definir.
EXCEPTION;
En la seccin BEGIN utilizar la instruccin RAISE para lanzar la excepcin:
RAISE ;
En el apartado de excepciones capturar el nombre de excepcin declarado.
EXCEPTION
WHEN THEN
. .
-
Resumen PL/SQL II Pgina 30
Para definir mensajes de error se usa la funcin RAISE_APPLICATION_ERROR.
Esta instruccin se coloca en la seccin ejecutable o en la de excepciones. Lo que hace es
lanzar un error cuyo nmero debe de estar entre el -20000 y el -20999 y hace que Oracle
muestre el mensaje indicado. El tercer parmetro opciones puede ser TRUE o FALSE (por
defecto TRUE) e indica si el error se aade a la pila de errores existentes.
RAISE_APPLICATION_ERROR( , [, ]);
Es un numero entre -20.000 y -20.999.
Es el texto asociado con este error. Su longitud debe ser menor de 512
caracteres.
Es booleano y opcional. Si su valor es TRUE, el error es agregado a la
lista de errores lanzados. Si es FALSE, el error reemplaza a la lista actual
de errores.
Propagacin de excepciones
Cuando ocurre se lanza una excepcin dentro de la seccin ejecutable de un bloque ocurre lo siguiente:
1. Si el bloque actual tiene un manejador para la excepcin, se ejecutan las instrucciones asociadas al manejador y control pasa al bloque que engloba a ste.
2. Si no hay un manejador para la excepcin, ste se propaga lanzndola en el bloque que engloba al actual. El primer paso se repite para el bloque que engloba.
-
Resumen PL/SQL II Pgina 31
DECLARE
A EXCEPTION;
BEGIN
BEGIN
RAISE A;
EXCEPTION
WHEN A THEN
...
END;
END;
DECLARE
A EXCEPTION;
B EXCEPTION;
BEGIN
BEGIN
RAISE B;
EXCEPTION
WHEN A THEN
...
END;
EXCEPTION
WHEN B THEN
...
END;
Se aplica la regla 1 para manejar la
excepcin
Se aplica la regla 2 al bloque interno
DECLARE
A EXCEPTION;
B EXCEPTION;
C EXCEPTION;
BEGIN
BEGIN
RAISE C;
EXCEPTION
WHEN A THEN
. . .
END;
EXCEPTION
WHEN B THEN
...
END;
DECLARE
v1 NUMBER(3) := 'abc';
BEGIN
...
EXCEPTION
WHEN OTHERS THEN
...
END;
La excepcin se propaga y el bloque no
concluye exitosamente.
Esta excepcin es inmediatamente propagada, sin ejecutar las
instrucciones asociadas al manejador WHEN OTHERS
BEGIN
DECLARE
v1 NUMBER(3):='abc';
BEGIN
...
EXCEPTION
WHEN OTHERS THEN
...
END;
EXCEPTION
WHEN OTHERS THEN
...
END;
DECLARE
A EXCEPTION;
B EXCEPTION;
BEGIN
RAISE A;
EXCEPTION
WHEN A THEN
RAISE B;
WHEN B THEN
...
END;
En este caso, el bloque interno lanza la
excepcin, y el bloque externo la maneja.
La excepcin A es lanzada y manejada, pero su manejador lanza B y
esta es propagada hacia un bloque exterior, por lo que este bloque
no termina exitosamente.
DECLARE
A EXCEPTION;
B EXCEPTION;
BEGIN
BEGIN
RAISE A;
EXCEPTION
WHEN A THEN
RAISE B;
WHEN B THEN
...
END;
EXCEPTION
WHEN B THEN
...
END;
DECLARE
A EXCEPTION;
BEGIN
RAISE A;
EXCEPTION
WHEN A THEN
...
RAISE;
END;
En este caso, si se tiene una conclusin
exitosa.
Cuando RAISE no tiene argumento, la excepcin actual es
propagada a un bloque externo.
-
Resumen PL/SQL II Pgina 32
COLECCIONES
Frecuentemente es conveniente manipular muchas variables a la vez como si fueran una nica
unidad. Estos tipos de datos se les denominan como colecciones. Oracle7 proporciona la tabla
indexada. Oracle8 incorpora las tablas anidadas y los varrays. Oracle9i contempla la posibilidad
de crear colecciones multinivel, es decir, colecciones de colecciones.
Las colecciones son tipos compuestos, como los registros, sin embargo no combinan variables
de diferentes tipos, sino que deben ser del mismo tipo.
TABLAS INDEXADAS
Las tablas indexadas son similares sintcticamente a los arrays (matrices) de C o JAVA. Para
declarar una tabla indexada, primero se define el tipo de tabla dentro de un bloque y luego se
declara la variable de dicho tipo. La sintaxis de una tabla indexada es:
TYPE IS TABLE OF INDEX BY BINARY_INTEGER | PLS_INTEGER;
Donde es el nombre del nuevo tipo que se est definiendo y tipo es un
determinado tipo de dato existente o una referencia a un tipo mediante %TYPE o %ROWTYPE.
La clusula INDEX BY BINARY_INTEGER es obligatoria como parte de la definicin de la tabla.
Dicha clusula no est disponible para las tablas anidadas.
Una vez declarado el tipo y la variable, podemos hacer referencia a un elemento individual de
la tabla, utilizando la siguiente sintaxis:
( )
Donde , es el nombre que hemos dado al definir una variable de
e es una variable de tipo BINARY_INTEGER | PLS_INTEGER o una
variable o expresin que pueda convertirse al tipo BINARY_INTEGER | PLS_INTEGER.
-
Resumen PL/SQL II Pgina 33
Aunque la asignacin de valores a elementos de una tabla es sintcticamente similar a la
asignacin de valores en arrays de C o JAVA, las tablas indexadas se implementan de otra
manera. Una tabla indexada es similar a una tabla de base de datos con dos columnas: key
(clave) y value (valor). El tipo de clave es BINARY_INTEGER | PLS_INTEGER y el valor podr ser
cualquier tipo de dato especificado en la declaracin.
Las tablas indexadas no estn restringidas, el nico lmite que nos encontramos depende
directamente del numero de filas permitidas por la clave de tipo BINARY_INTEGER |
PLS_INTEGER, pero espero que no os haga falta, crear ms elementos, ya que el rango de un
BINARY_INTEGER | PLS_INTEGER oscila entre 2.147.483.647 al +2.147.483.647 .
Los elementos de una tabla indexada no necesariamente se encuentran en un orden
determinado ya que no se tienen que guardarse en memoria de forma consecutiva como los
arrays de C o Java. Las claves utilizadas no tienen por qu ser secuenciales. El ndice puede ser
un valor negativo.
-
Resumen PL/SQL II Pgina 34
Se puede crear una tabla indexada de registros. Dado que cada elemento de la tabla es un
registro, se puede hacer referencia a los campos contenidos en dicho registro, para ello habr
que usar la siguiente sintaxis:
( ) .
Se puede crear una tabla indexada de tipo de objeto.
CREATE OR REPLACE TYPE MYOBJETO AS OBJECT (
CAMPO1 NUMBER(3),
CAMPO2 VARCHAR2(20),
CAMPO3 DATE);
/
DECLARE
TYPE OBJETOTAB IS TABLE OF MYOBJETO
INDEX BY BINARY_INTEGER;
V_OBJETO OBJETOTAB;
BEGIN
V_OBJETO(1) := MYOBJETO(1, NULL, NULL);
V_OBJETO(1).CAMPO2 := '...TEXTO .....';
V_OBJETO(1).CAMPO3 := SYSDATE;
DBMS_OUTPUT.PUT_LINE(V_OBJETO(1).CAMPO1||','||V_OBJETO(1).CAMPO2||','||V_OBJETO(1).CAMPO3);
END;
/
-
Resumen PL/SQL II Pgina 35
-
Resumen PL/SQL II Pgina 36
MTODOS PARA LAS TABLAS INDEXADAS
Las tablas indexadas tienen definidos una serie de mtodos. Utilizan la siguiente sintaxis:
. [ () ]
EXISTS
Se utiliza para averiguar si existe en la coleccin el elemento indicado a partir de un ndice
dado. Su sintaxis es EXISTS( ).
Devuelve TRUE si la entrada especfica existe dentro de la coleccin.
COUNT
Devuelve el nmero de elementos de una coleccin.
FIRST
Devuelve el ndice del primer elemento de una coleccin.
LAST
Devuelve el ndice del ltimo elemento de una coleccin.
NEXT
Devuelve el ndice del elemento siguiente de una coleccin respecto a un ndice dado. Su
sintaxis es NEXT( ).
PRIOR
Devuelve el ndice del elemento anterior de una coleccin respecto a un ndice dado. Su
sintaxis es PRIOR( ).
-
Resumen PL/SQL II Pgina 37
DELETE
DELETE
Elimina todos los elementos de una tabla PL/SQL.
DELETE()
Elimina el elemento de la posicin indicada por de la tabla
PL/SQL.
DELETE(, )
Elimina los elementos del rango indicado por y
de la tabla PL/SQL.
-
Resumen PL/SQL II Pgina 38
--SET SERVEROUTPUT ON;
CREATE OR REPLACE TYPE O_ENTRADAS AS OBJECT (
ARTICULO VARCHAR2(40),
CANT NUMBER(5),
FECHA_ENTRADA DATE);
/
DECLARE
TYPE TABLA_ENTRADAS IS TABLE OF O_ENTRADAS INDEX BY BINARY_INTEGER;
V_ENT TABLA_ENTRADAS;
V_CONT NUMBER:=1;
V_NUM NUMBER;
V_IND NUMBER;
BEGIN
V_ENT(1) := O_ENTRADAS('DISCO DURO MULTIMEDIA',50,SYSDATE);
V_ENT(3) := O_ENTRADAS('PC COMPAQ PRESARIO',4,SYSDATE+2);
V_NUM:=V_ENT.COUNT;
V_IND:=V_ENT.FIRST;
DBMS_OUTPUT.PUT_LINE('ELEMENTOS EN LA TABLA.....'||V_NUM);
WHILE V_CONT
-
Resumen PL/SQL II Pgina 39
--SET SERVEROUTPUT ON;
CREATE OR REPLACE TYPE O_ENTRADAS AS OBJECT (
ARTICULO VARCHAR2(40),
CANT NUMBER(5),
FECHA_ENTRADA DATE);
/
DECLARE
TYPE TABLA_ENTRADAS IS TABLE OF O_ENTRADAS INDEX BY BINARY_INTEGER;
V_ENT TABLA_ENTRADAS;
V_IND NUMBER;
E_NINGUNO EXCEPTION;
BEGIN
V_ENT(1) := O_ENTRADAS('DISCO DURO MULTIMEDIA',50,SYSDATE);
V_ENT(3) := O_ENTRADAS('PC COMPAQ PRESARIO',4,SYSDATE+2);
V_ENT(8) := O_ENTRADAS('DVD LG',4,SYSDATE+2);
V_IND:=V_ENT.FIRST;
IF V_ENT.COUNT = 0 THEN
RAISE E_NINGUNO;
ELSE
DBMS_OUTPUT.PUT_LINE('ELEMENTOS EN LA TABLA.....'||V_ENT.COUNT);
WHILE V_ENT.EXISTS(V_IND) LOOP
DBMS_OUTPUT.PUT_LINE(' - '||V_ENT(V_IND).ARTICULO );
V_IND := V_ENT.NEXT(V_IND);
END LOOP;
END IF;
EXCEPTION
WHEN E_NINGUNO THEN
DBMS_OUTPUT.PUT_LINE('TABLA VACIA');
WHEN NO_DATA_FOUND OR VALUE_ERROR THEN
DBMS_OUTPUT.PUT_LINE('POSICIONAMIENTO INCORRECTO');
END;
/
-
Resumen PL/SQL II Pgina 40
TABLAS ANIDADAS
La funcionalidad de una tabla anidada es la misma que de una tabla indexada. Sin embargo
una tabla anidada debe crearse con una clave secuencial, y la clave no puede ser negativa.
Adems una tabla anidada puede ser almacenada en una base de datos, mientras que una
tabla indexada no. El nmero mximo de filas en una tabla anidada es de 2 giga bites que es el
valor mximo de la clave.
La sintaxis de creacin de una tabla anidada es:
TYPE IS TABLE OF [ NOT NULL ];
Donde es el nombre del nuevo tipo declarado y es el tipo
de cada elemento de la tabla anidada. El tipo puede ser un tipo declarado por
el usuario.
Cuando se crea una tabla indexada, pero todava no contiene ningn dato, simplemente est
vaca; pero cuando se declara una tabla anidada y todava no contiene ningn elemento, sta
se inicializa para ser automticamente nula, al igual que cuando declaramos otros tipos de
variables. Entonces, si intentamos aadir un elemento a una tabla anidada que tenga el valor
NULL se producir un error que corresponde a la excepcin predefinida COLLECTION_IS_NULL.
Entonces, para inicializar una tabla anidada debe hacerse usando un constructor. El
constructor para una tabla anidada tiene el mismo nombre que el propio tipo de tabla. Sin
embargo, toma un nmero variable de argumentos, cada uno de los cuales debe de ser
compatible con el tipo de elemento de la tabla, comenzando secuencialmente con el ndice 1.
-
Resumen PL/SQL II Pgina 41
DECLARE
TYPE TABLA_NUMERO IS TABLE OF NUMBER;
V_TAB1 TABLA_NUMERO := TABLA_NUMERO(-1); -- Crea una tabla con un elemento
V_TAB2 TABLA_NUMERO := TABLA_NUMERO(); -- Crea una tabla sin ningn elemento.
V_TAB3 TABLA_NUMERO := TABLA_NUMERO(1, 2, 3, 5, 7); -- Crea una tabla con cinco elementos.
BEGIN
DBMS_OUTPUT.PUT_LINE('TAB_1...............'||V_TAB1(1));
-- Asigna un valor a V_TAB1(1). ste reemplazar al valor que estaba inicializado .
V_TAB1(1) := 12345;
DBMS_OUTPUT.PUT_LINE('TAB_1...............'||V_TAB1(1));
--V_TAB1(2) := 678; ERROR , NO EXITE EL ELEMENTO CON INDICE 2
FOR CONT IN 1..5 LOOP
DBMS_OUTPUT.PUT_LINE(V_TAB3(CONT));
END LOOP;
END;
/
-
Resumen PL/SQL II Pgina 42
Una tabla anidada podr estar creada, pero sta, podr estar vaca, con valor NULL o con un
elemento NULL.
DECLARE
TYPE TABLA_NOMBRES IS TABLE OF VARCHAR2(50);
V_TAB1 TABLA_NOMBRES; -- Crea una tabla con valor NULL.
V_TAB2 TABLA_NOMBRES:= TABLA_NOMBRES (); -- Crea una tabla con un elemento, que es l mismo NULL.
BEGIN
IF V_TAB1 IS NULL THEN
DBMS_OUTPUT.PUT_LINE('V_TAB1 es NULL');
ELSE
DBMS_OUTPUT.PUT_LINE(' V_TAB1 no es NULL');
END IF;
IF V_TAB2 IS NULL THEN
DBMS_OUTPUT.PUT_LINE(' V_TAB2 es NULL');
ELSE
DBMS_OUTPUT.PUT_LINE(' V_TAB2 no es NULL');
END IF;
END;
/
-
Resumen PL/SQL II Pgina 43
Aunque una tabla no est restringida, no se puede asignar un valor a un elemento que no
exista, y que por tanto diera lugar a que la tabla aumentara de tamao. Si intentamos hacer
esto en una tabla anidada, obtendremos el siguiente error controlado por la excepcin
predefinida SUBSCRIPT_BEYOND_COUNT.
DECLARE
TYPE TABLA_NUMERO IS TABLE OF NUMBER;
V_NUMEROS TABLA_NUMERO := TABLA_NUMERO(10, 2, 3 );
BEGIN
V_NUMEROS (2) := 20;
V_NUMEROS (3) := V_NUMEROS (3) + 27;
FOR V_CONT IN 1..3 LOOP
DBMS_OUTPUT.PUT_LINE(V_NUMEROS(V_CONT));
END LOOP;
V_NUMEROS (4) := 40;
EXCEPTION
WHEN SUBSCRIPT_BEYOND_COUNT THEN
DBMS_OUTPUT.PUT_LINE('Para aadir nuevo elemento usa EXTEND ');
END;
/
Se puede aadir un nuevo elemento a una tabla anidada utilizando el mtodo EXTEND.
-
Resumen PL/SQL II Pgina 44
MTODOS PARA LAS TABLAS INDEXADAS, ANIDADAS Y VARRAYS
Las tablas indexadas, anidadas y varrays tienen definidos una serie de mtodos. Utilizan la
siguiente sintaxis:
. [ () ]
EXISTS
Se utiliza para averiguar si existe en la coleccin el elemento indicado a partir de un ndice
dado. Su sintaxis es EXISTS( ).
Devuelve TRUE si la entrada especfica existe dentro de la coleccin.
Vlido para tablas indexadas, tablas anidadas y varrays.
COUNT
Devuelve el nmero de elementos de una coleccin.
Vlido para tablas indexadas, tablas anidadas y varrays.
FIRST
Devuelve el ndice del primer elemento de una coleccin.
Vlido para tablas indexadas, tablas anidadas y varrays.
LAST
Devuelve el ndice del ltimo elemento de una coleccin.
Vlido para tablas indexadas, tablas anidadas y varrays.
-
Resumen PL/SQL II Pgina 45
NEXT
Devuelve el ndice del elemento siguiente de una coleccin respecto a un ndice dado. Su
sintaxis es NEXT( ).
Vlido para tablas indexadas, tablas anidadas y varrays.
PRIOR
Devuelve el ndice del elemento anterior de una coleccin respecto a un ndice dado. Su
sintaxis es PRIOR( ).
Vlido para tablas indexadas, tablas anidadas y varrays.
DELETE
DELETE
Elimina todos los elementos de una tabla PL/SQL.
DELETE()
Elimina el elemento de la posicin indicada por de la tabla
PL/SQL.
DELETE(, )
Elimina los elementos del rango indicado por y
de la tabla PL/SQL.
Vlido para tablas indexadas, tablas anidadas.
LIMIT
Devuelve el nmero mximo de elementos de una coleccin.
Vlido para varrays.
-
Resumen PL/SQL II Pgina 46
EXTEND
Aade elementos a una coleccin. Admite tres formatos distintos:
EXTEND
Simplemente aade un elemento de valor NULL al final de la coleccin, con el
ndice LAST+1.
EXTEND()
Aade elementos de valor NULL al final de la coleccin.
EXTEND(, )
Aade copias del elemento al final de la coleccin.
Vlido para tablas anidadas, varrays.
TRIM
Elimina elementos del final de una coleccin. Admite dos formatos distintos:
TRIM
Elimina un elemento al final de una coleccin.
TRIM( )
Elimina elementos al final de una coleccin. Si es mayor que COUNT
se genera la excepcin SUBSCRIPT_BEYOND_COUNT.
Vlido para tablas anidadas, varrays.
-
Resumen PL/SQL II Pgina 47
DECLARE
TYPE tabla_numerica IS TABLE OF NUMBER ;
v_Numeros tabla_numerica:=tabla_numerica();
contador BINARY_INTEGER;
BEGIN
v_Numeros.EXTEND(12);
FOR contador IN 1..10 LOOP
v_Numeros(contador) := contador * 10;
END LOOP;
v_Numeros(11) := -30;
v_Numeros(12) := 888;
DBMS_OUTPUT.PUT_LINE('Total elementos ' || v_Numeros.count);
DBMS_OUTPUT.PUT_LINE('Ultimo ndice ' || v_Numeros.last);
DBMS_OUTPUT.PUT_LINE('Primer ndice ' || v_Numeros.first);
DBMS_OUTPUT.PUT_LINE('Siguiente es ' || v_Numeros.next(10));
DBMS_OUTPUT.PUT_LINE('Anterior es ' || v_Numeros.prior(-1));
DBMS_OUTPUT.PUT_LINE(' ELEMENTOS');
contador:=v_Numeros.first;
WHILE contador
-
Resumen PL/SQL II Pgina 48
VARRAYS
Un varray, matriz de longitud variable, es un tipo de dato muy similar a un array en C o Java.
Sintcticamente a un varray se accede de forma muy similar a como se hace con una tabla
indexada o anidada. Sin embargo, un varray tiene un lmite superior fijo para su tamao, que
se especifica como parte de la declaracin de tipo. En lugar de ser una estructura de datos
dispersa sin lmite superior, los elementos se insertan en un varray comenzando en el ndice 1,
hasta la longitud mxima declarada.
El tamao mximo de un varray es de 2 gigabytes, como las tablas anidadas.
El almacenamiento de los datos se realiza de la misma forma que en un array en C o Java, es
decir, los elementos se almacenan de forma contigua en memoria.
La sintaxis para declarar un varray es la siguiente:
TYPE IS VARRAY OF
[ NOT NULL ];
Donde es el nombre del nuevo tipo de varray, es un
entero que especifica el nmero mximo de elementos del varray y es el
tipo que define los elementos del varray.
Tipos de varray vlidos.
-- Lista de nmeros.
TYPE NumeroList IS VARRAY(10) OF NUMBER(3) NOT NULL;
-- Una lista de registros PL/SQL.
TYPE ProovedoresList IS VARRAY(100) OF Tproveedores%ROWTYPE;
-- Una lista de objetos.
TYPE ObjetoList is VARRAY(25) OF MyObjeto;
-
Resumen PL/SQL II Pgina 49
Los varrays se inicializan utilizando un constructor, al igual que las tablas anidadas. El nmero
de argumentos pasados al constructor se convierte en la longitud inicial del varray y debe ser
menor o igual que la longitud mxima especificada en la definicin. Si intentamos realizar
asignaciones a elementos no creados inicialmente, obtendremos el siguiente error controlado
por la excepcin predefinida SUBSCRIPT_BEYOND_COUNT.
Se puede aadir un nuevo elemento a un varray utilizando el mtodo EXTEND. Las
asignaciones a elementos con valores por encima del tamao mximo del varray, o los intentos
de ampliar el varray sobrepasando el tamao mximo, generar el siguiente error controlado
por la excepcin predefinida SUBSCRIPT_OUTSIDE_LIMIT.
DECLARE
TYPE MESES IS VARRAY(12) OF VARCHAR2(10);
V_LIST MESES := Meses('Enero','Febrero','Marzo','Abril','Mayormente','Junio','Julio',
'Agosto','Septiembre','Octubre','Noviembre' );
BEGIN
V_LIST(5) := 'Mayo';
-- Ampla el varray a 12 elementos y asigna el valor.
V_LIST.EXTEND;
V_LIST(12) := 'Diciembre';
FOR CONTADOR IN 1..12 LOOP
DBMS_OUTPUT.PUT_LINE(V_LIST(CONTADOR));
END LOOP;
V_LIST.EXTEND;
EXCEPTION
WHEN SUBSCRIPT_OUTSIDE_LIMIT THEN
DBMS_OUTPUT.PUT_LINE('Limite superado por EXTEND ');
END;
-
Resumen PL/SQL II Pgina 50
DECLARE
TYPE tabla_numerica IS VARRAY(12) OF NUMBER ;
v_Numeros tabla_numerica:=tabla_numerica();
contador BINARY_INTEGER;
BEGIN
v_Numeros.extend(12);
FOR contador IN 1..10 LOOP
v_Numeros(contador) := contador * 10;
END LOOP;
v_Numeros(11) := -30;
v_Numeros(12) := 888;
DBMS_OUTPUT.PUT_LINE('Total elementos ' || v_Numeros.count);
DBMS_OUTPUT.PUT_LINE('Ultimo ndice ' || v_Numeros.last);
DBMS_OUTPUT.PUT_LINE('Primer ndice ' || v_Numeros.first);
DBMS_OUTPUT.PUT_LINE('Siguiente es ' || v_Numeros.next(10));
DBMS_OUTPUT.PUT_LINE('Anterior es ' || v_Numeros.prior(55));
DBMS_OUTPUT.PUT_LINE(' ELEMENTOS');
contador:=v_Numeros.first;
WHILE contador
-
Resumen PL/SQL II Pgina 51
COLECCIONES MULTINIVEL
Las colecciones tablas indexadas, tablas anidadas y varrays que estamos viendo, son de una
dimensin, pero se pueden definir colecciones de ms de un nivel, es decir, colecciones de
colecciones. Esta estructura es conocida como colecciones multinivel.
Las colecciones multinivel se definen igual que las colecciones de una dimensin, con la
diferencia de que el tipo de la coleccin es una coleccin en s misma.
Un elemento de una coleccin multinivel es por s mismo una coleccin, por lo que se emplea
dos pares de parntesis para acceder a un elemento de la coleccin contenida.
DECLARE
-- Primero declara una tabla de nmeros indexada
TYPE t_Numeros IS TABLE OF NUMBER INDEX BY BINARY_INTEGER;
-- Ahora declara un tipo que es una tabla indexada de t_Numeros.
-- Esto es una coleccin multinivel.
TYPE t_MultiNumeros IS TABLE OF t_Numeros INDEX BY BINARY_INTEGER;
-- Tambin podemos tener un varray de la tabla indexada
TYPE t_MultiVarray IS VARRAY(10) OF t_Numeros;
-- O una tabla anidada
TYPE t_MultiAnidada IS TABLE OF t_Numeros;
v_MultiNumeros t_MultiNumeros;
BEGIN
v_MultiNumeros(1)(1) := 26;
DBMS_OUTPUT.PUT_LINE(v_MultiNumeros(1)(1));
END;
Y as sucesivamente una coleccin de otra coleccin.
DECLARE
TYPE t_Numeros IS TABLE OF NUMBER INDEX BY BINARY_INTEGER;
TYPE t_MultiNumeros IS TABLE OF t_Numeros INDEX BY BINARY_INTEGER;
TYPE t_MultiNumeros3 IS TABLE OF t_MultiNumeros INDEX BY BINARY_INTEGER;
TYPE t_MultiNumeros4 IS TABLE OF t_MultiNumeros3 INDEX BY BINARY_INTEGER;
v_MultiNumeros t_MultiNumeros;
v_MultiNumeros3 t_MultiNumeros3;
v_MultiNumeros4 t_MultiNumeros4;
BEGIN
v_MultiNumeros(1)(1) := 26;
v_MultiNumeros3(1)(1)(1) := 29;
v_MultiNumeros4(1)(1)(1)(1) := 44;
DBMS_OUTPUT.PUT_LINE(v_MultiNumeros(1)(1));
DBMS_OUTPUT.PUT_LINE(v_MultiNumeros3(1)(1)(1));
DBMS_OUTPUT.PUT_LINE(v_MultiNumeros4(1)(1)(1)(1));
END;
-
Resumen PL/SQL II Pgina 52
DECLARE
TYPE t_Varray IS TABLE OF NUMBER INDEX BY BINARY_INTEGER;
TYPE t_MultiVarray IS VARRAY(10) OF t_Varray ;
v_MultiVarray t_MultiVarray:=t_MultiVarray();
BEGIN
v_MultiVarray.extend;
v_MultiVarray(1)(1) := 26;
DBMS_OUTPUT.PUT_LINE(v_MultiVarray(1)(1));
END;
DECLARE
TYPE t_Varray IS VARRAY(3) OF NUMBER(5);
TYPE t_MultiVarray IS VARRAY(3) OF t_Varray ;
v_MultiVarray t_MultiVarray:=t_MultiVarray(t_Varray(1,2,3),t_Varray(4,5,6),t_Varray(7,8,9));
BEGIN
FOR cont1 IN 1..3 LOOP
FOR cont2 IN 1..3 LOOP
DBMS_OUTPUT.PUT_LINE(v_MultiVarray(cont1)(cont2));
END LOOP;
END LOOP;
END;
DECLARE
TYPE t_Varray IS VARRAY(3) OF NUMBER(5);
TYPE t_MultiVarray IS VARRAY(3) OF t_Varray ;
v_MultiVarray t_MultiVarray:=t_MultiVarray(t_Varray(1),t_Varray(4,5,6),t_Varray(7,8));
BEGIN
v_MultiVarray(1).extend;
v_MultiVarray(1)(2) := 2;
v_MultiVarray(1).extend;
v_MultiVarray(1)(3) := 3;
v_MultiVarray(3).extend;
v_MultiVarray(3)(3) := 9;
FOR cont1 IN 1..3 LOOP
FOR cont2 IN 1..3 LOOP
DBMS_OUTPUT.PUT_LINE(v_MultiVarray(cont1)(cont2));
END LOOP;
END LOOP;
END;
-
Resumen PL/SQL II Pgina 53
DECLARE
TYPE t_Varray IS VARRAY(3) OF NUMBER(5);
TYPE t_MultiVarray IS VARRAY(5) OF t_Varray ;
v_MultiVarray t_MultiVarray:=t_MultiVarray(t_Varray(1,2,3),t_Varray(4,5,6),t_Varray(7,8,9));
BEGIN
v_MultiVarray.extend;
v_MultiVarray(4):=t_Varray(14,15);
v_MultiVarray(4).extend;
v_MultiVarray(4)(3):=16;
v_MultiVarray.extend;
v_MultiVarray(5):=t_Varray(114,115,116);
FOR cont1 IN 1..5 LOOP
FOR cont2 IN 1..3 LOOP
DBMS_OUTPUT.PUT_LINE(v_MultiVarray(cont1)(cont2));
END LOOP;
END LOOP;
v_MultiVarray:= t_MultiVarray(t_Varray(11,22,33),
t_Varray(44,55,66),t_Varray(77,88,99),
t_Varray(111,222,333),t_Varray(444,555,666));
FOR cont1 IN 1..5 LOOP
FOR cont2 IN 1..3 LOOP
DBMS_OUTPUT.PUT_LINE(v_MultiVarray(cont1)(cont2));
END LOOP;
END LOOP;
END;
-
Resumen PL/SQL II Pgina 54
COLECCIONES EN LA BASE DE DATOS
Las tablas anidadas y los varrays pueden almacenarse en tablas de la base de datos. El
almacenamiento de colecciones en la base de datos tiene implicaciones en la forma en la que
deben declararse los tipos de tablas y en la sintaxis de creacin de tablas con columnas de
coleccin.
Para almacenar y recuperar una coleccin en una tabla de base de datos, el tipo de coleccin
debe ser conocido tanto para PL/SQL como para SQL. Esto significa que no puede ser local a un
bloque PL/SQL y debe declararse utilizando una instruccin CREATE TYPE.
CREATE OR REPLACE TYPE AS ;
CREATE OR REPLACE TYPE LISTA_NOMBRES AS VARRAY(20) OF VARCHAR2(30);
Un tipo creado en el nivel de esquema se considera global en PL/SQL. Un tipo de nivel de
esquema se puede usar como una columna de base de datos.
Estructura de los varrays almacenados
Un varray se puede usar como tipo para una columna de base de datos. En este caso, el varray
completo se almacena en una fila de la base de datos, junto con las dems columnas. Cada fila
contiene un varray diferente.
CREATE OR REPLACE TYPE lista_libros AS VARRAY(10) OF NUMBER(4);
CREATE TABLE material (
asignatura CHAR(30),
curso NUMBER(3),
lectura_obligada lista_libros
);
-
Resumen PL/SQL II Pgina 55
Tablas anidadas en la base de datos
Una tabla anidada puede almacenarse como una columna de la base de datos. Cada fila de la
tabla puede contener una tabla anidada diferente.
CREATE OR REPLACE TYPE lista_socios AS TABLE OF NUMBER(5);
CREATE TABLE catalogo_libros (
catalog_number NUMBER(4),
num_copias NUMBER,
num_sacados NUMBER,
control lista_socios )
NESTED TABLE control STORE AS control_tab;
Hay que incluir la clusula NESTED TABLE para cada tabla anidada en una tabla de base de
datos. Esta clusula indica el nombre de la tabla de almacenamiento.
Una tabla de almacenamiento es una tabla generada por el sistema que se usa para almacenar
los datos reales de la tabla anidada. A diferencia de un varray almacenado, los datos de una
tabla anidada nunca se almacenan junto con el resto de las columnas de la tabla en la que est
contenida, sino que se almacena por separado.
La columna definida de tipo tabla anidada almacena realmente una referencia a la tabla de
almacenamiento generada por NESTED TABLE, en la que se almacena la lista de valores.
-
Resumen PL/SQL II Pgina 56
BULK COLLECT
PL/SQL nos permite leer varios registros en una tabla de PL con un nico acceso a travs de la
instruccin BULK COLLECT.
Esto nos permitir reducir el nmero de accesos a disco, por lo que optimizaremos el
rendimiento de nuestras aplicaciones. Como contrapartida el consumo de memoria ser
mayor.
DECLARE
TYPE T_COD IS TABLE OF TCATEGORIA.CODIGO_CAT%TYPE;
TYPE T_CAT IS TABLE OF TCATEGORIA.NOMBRE_CAT%TYPE;
V_COD T_COD;
V_CAT T_CAT;
BEGIN
SELECT CODIGO_CAT,NOMBRE_CAT BULK COLLECT INTO V_COD, V_CAT FROM TCATEGORIA;
FOR i IN V_COD.FIRST .. V_COD.LAST LOOP
DBMS_OUTPUT.PUT_LINE(V_COD(i) || ', ' || V_CAT(i));
END LOOP;
END;
/
--Trabajando con registros PL/SQL
DECLARE
TYPE R_CATEGORIA IS RECORD (COD NUMBER(3) , CAT VARCHAR2(20));
TYPE T_CAT IS TABLE OF R_CATEGORIA;
V_CAT T_CAT;
BEGIN
SELECT CODIGO_CAT,NOMBRE_CAT BULK COLLECT INTO V_CAT FROM TCATEGORIA;
FOR i IN V_CAT.FIRST .. V_CAT.LAST LOOP
DBMS_OUTPUT.PUT_LINE(V_CAT(i).COD || ', ' || V_CAT(i).CAT );
END LOOP;
END;
/
--Trabajando con registros SQL
DECLARE
TYPE T_CAT IS TABLE OF TCATEGORIA%ROWTYPE;
V_CAT T_CAT;
BEGIN
SELECT CODIGO_CAT,NOMBRE_CAT BULK COLLECT INTO V_CAT FROM TCATEGORIA;
FOR i IN V_CAT.FIRST .. V_CAT.LAST LOOP
DBMS_OUTPUT.PUT_LINE(V_CAT(i).CODIGO_CAT || ', ' || V_CAT(i).NOMBRE_CAT );
END LOOP;
END;
/