Está en la página 1de 56

FEBRERO - 2009

CURSO BASE DE DATOS

PL / SQL

Resumen PL/SQL II
Resumen PL/SQL II

Curso Base de Datos


Pgina 1

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 <LISTA_CAMPOS> <LISTA_VARIABLES> <TABLA>

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 2

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 3

Sentencia de control - IF
Toma de decisiones. Permite especificar que ciertas instrucciones se ejecuten o no dependiendo de una condicin IF simple Sintaxis: IF <CONDICIN> THEN <INSTRUCCIONES> 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 <CONDICIN> THEN <INSTRUCCIONES> ELSE <INSTRUCCIONES> END IF; En este caso las instrucciones bajo el ELSE se ejecutan si la condicin es falsa.

Resumen PL/SQL II

Pgina 4

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 <CONDICIN> THEN <INSTRUCCIONES> ELSIF <CONDICIN> THEN <INSTRUCCIONES> ELSIF <CONDICIN> THEN <INSTRUCCIONES> ELSE <INSTRUCCIONES> 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 5

Resumen PL/SQL II

Pgina 6

Sentencia de control - CASE


La sentencia CASE devuelve un resultado tras evaluar una expresin.

CASE <SELECTOR> WHEN <EXPRESION1> THEN <RESULTADO1> WHEN <EXPRESION2> THEN <RESULTADO2> WHEN <EXPRESION3> THEN <RESULTADO3> ... [ELSE <RESULTADO_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 7

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 <CONDICION1> THEN <RESULTADO1> WHEN <CONDICION2> THEN <RESULTADO2> ... [ELSE <RESULTADO_ELSE> ] END;

Resumen PL/SQL II

Pgina 8

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 <INSTRUCCIONES> ... EXIT [ WHEN <CONDICION> ] 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 9

Sentencia de control repetitiva - WHILE


Genera un bucle cuyas instrucciones se repiten mientras la condicin que sigue a la palabra WHILE sea verdadera. WHILE <CONDICION> LOOP <INSTRUCCIONES> ... 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 10

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 <CONTADOR> IN [REVERSE] <VALOR_BAJO> . . <VALOR_ALTO> LOOP <INSTRUCCIONES> ... END LOOP;

BEGIN FOR CONT IN 101 .. 105 LOOP DBMS_OUTPUT.PUT_LINE(CONT); END LOOP; END;

Resumen PL/SQL II

Pgina 11

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 << y >> 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 << BUCLE_1 >> FOR CONT_1 IN 101 .. 200 LOOP << BUCLE_2 >> 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 12

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 <TIPO_REGISTRO> IS RECORD ( <CAMPO1> <TIPO> [NOT NULL] [ := <EXPRESIN> ] , <CAMPO2> <TIPO> [NOT NULL] [ := <EXPRESIN> ] , ......... <CAMPON> <TIPO> [NOT NULL] [ := <EXPRESIN> ] ,);

Donde <TIPO_REGISTRO> es el nombre del nuevo tipo definido, <CAMPO1> a <CAMPON> son los nombres de los campos incluidos en el registro, y <TIPO> 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 V_REC2 REGISTRO_EJEMPLO; REGISTRO_EJEMPLO; );

Para hacer referencia a uno de los campos de un registro se emplea la notacin de punto. La sintaxis ser <nombre_variable_registro>.<nombre_campo> v_Rec1.Field1

Resumen PL/SQL II

Pgina 13

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 14

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 15

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 <NOMBRE_CURSOR > IS

<SENTENCIA_SELECT>

Tambin es posible declarar una lista de parmetros: CURSOR <NOMBRE_CURSOR > ( <PARAM_1> <TIPO_1>, ..., <PARAM_N> <TIPO_N> ) IS <SENTENCIA_SELECT>

Resumen PL/SQL II

Pgina 16

Abrir el cursor La sintaxis es: OPEN <NOMBRE_CURSOR> ;

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 <NOMBRE_CURSOR> INTO <LISTA_VARIABLES>; FETCH <NOMBRE_CURSOR> INTO <REGISTRO_PL/SQL>;

Cerrar el cursor La sintaxis es: CLOSE <NOMBRE_CURSOR> ;

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 FALSE TRUE Al finalizar la recuperacin TRUE FALSE TRUE ** Despus de cerrar ORA-1001 ORA-1001 FALSE ORA-1001

%NOTFOUND ORA-1001 NULL %FOUND %ISOPEN ORA-1001 NULL FALSE

TRUE TRUE *

%ROWCOUNT ORA-1001 0
*

**

Nmero de registros que ha recuperado hasta el momento Nmero de total de registros

Resumen PL/SQL II

Pgina 17

Manejo del cursor por medio de ciclos


Por medio de ciclo LOOP. Debe tenerse cuidado de agregar una condicin para salir del ciclo: OPEN <NOMBRE_CURSOR>; LOOP FETCH <NOMBRE_CURSOR> INTO <LISTA_VARIABLES>; EXIT WHEN <NOMBRE_CURSOR>%NOTFOUND; /* Procesamiento de los registros recuperados */ END LOOP; CLOSE <NOMBRE_CURSOR>;

Resumen PL/SQL II

Pgina 18

Por medio de un ciclo WHILE LOOP. La instruccin FETCH aparece dos veces. OPEN <NOMBRE_CURSOR>; FETCH <NOMBRE_CURSOR> INTO <LISTA_VARIABLES>; WHILE <NOMBRE_CURSOR>%FOUND LOOP /* Procesamiento de los registros recuperados */ FETCH <NOMBRE_CURSOR> INTO <LISTA_VARIABLES>; END LOOP; CLOSE <NOMBRE_CURSOR>;

Resumen PL/SQL II

Pgina 19

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 <NOMBRE_CURSOR> LOOP /* Procesamiento de los registros recuperados */ END LOOP;

Resumen PL/SQL II

Pgina 20

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 21

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 22

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 <CAMPO> ] [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 <CURSOR>

Resumen PL/SQL II

Pgina 23

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 En tiempo de compilacin En tiempo de ejecucin

Reportado por Compilador de PL/SQL

Cmo es manejado El programador corrige los errores que reporta el compilador

El motor de ejecucin Las excepciones son lanzadas y capturadas por los de PL/SQL 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 24

Excepciones predefinidas Las excepciones predefinidas corresponden a errores comunes en SQL. Error de Oracle
ORA-0001 ORA-0051 ORA-0061 ORA-1001 ORA_1012 ORA-1017 ORA-1403 ORA-1422 ORA-1476 ORA-1722 ORA-6500 ORA-6501 ORA-6502

Excepcin equivalente DUP_VAL_ON_INDEX TIMEOUT_ON_RESOURCE TRANSACTION_BACKED_OUT INVALID_CURSOR NOT_LOGGED_ON LOGIN_DENIED NO_DATA_FOUND TOO_MANY_ROWS ZERO_DIVIDE INVALID_NUMBER STORAGE_ERROR PROGRAM_ERROR VALUE_ERROR

Descripcin

Restriccin de unicidad violada Tiempo fuera ocurrido mientras esperaba un recurso La transaccin fue desecha por un bloqueo Operacin ilegal con un cursor Sin conexin a Oracle Nombre de usuario o password invlido No se encontraron datos La instruccin SELECT ... INTO devuelve ms de un registro Divisin por cero Conversin invlida a un nmero Error PL/SQL interno lanzado al exceder la memoria Error PL/SQL interno Error al trucar o convertir valores, o en una operacin aritmtica Una referencia a una tabla anidada o ndice de varray se encuentra fuera del rango declarado. Una referencia a una tabla anidada o ndice de varray es mayor que el nmero de elementos de la coleccin. Al intentar abrir un cursor que ya est abierto

ORA-6532

SUBSCRIPT_OUTSIDE_LIMIT

ORA-6533 ORA-6511

SUBSCRIPT_BEYOND_COUNT CURSOR_ALREADY_OPEN

Resumen PL/SQL II

Pgina 25

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 <nombre_excepcion1> [ OR <nombre_excepcion2>] THEN <secuencia_de_instrucciones1>; WHEN <nombre_excepcion3> [ OR <nombre_excepcion4>] THEN <secuencia_de_instrucciones2>; WHEN OTHERS THEN <secuencia_de_instrucciones3>; END;

Resumen PL/SQL II

Pgina 26

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 27

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: <NOMBRE_DE_EXCEPCION> EXCEPTION; Debemos asociar ese nombre al nmero de error correspondiente en el apartado DECLARE mediante la siguiente sintaxis: PRAGMA EXCEPTION_INIT(<NOMBRE_DE_EXCEPCION> , <N_DE_EXCEPCION> ); En el apartado EXCEPTION capturaremos el nombre de la excepcin como si fuera una excepcin normal.

Resumen PL/SQL II

Pgina 28

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.

<NOMBRE_DE_EXCEPCION> EXCEPTION; En la seccin BEGIN utilizar la instruccin RAISE para lanzar la excepcin: RAISE <NOMBRE_DE_EXCEPCION> ; En el apartado de excepciones capturar el nombre de excepcin declarado. EXCEPTION WHEN <NOMBRE_DE_EXCEPCION> THEN . .

Resumen PL/SQL II

Pgina 29

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( <numero_de_error>, <mensaje_de_error> [, <mantener_error>]);

<numero_de_error> <mensaje_de_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.

<mantener_error>

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 30

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 2 al bloque interno

Se aplica la regla 1 para manejar la excepcin DECLARE A EXCEPTION; B EXCEPTION; C EXCEPTION; BEGIN BEGIN RAISE C; EXCEPTION WHEN A THEN . . . END; EXCEPTION WHEN B THEN ... END; La excepcin se propaga y el bloque no concluye exitosamente. BEGIN DECLARE v1 NUMBER(3):='abc'; BEGIN ... EXCEPTION WHEN OTHERS THEN ... END; EXCEPTION WHEN OTHERS THEN ... END; En este caso, el bloque interno lanza la excepcin, y el bloque externo la maneja.

DECLARE v1 NUMBER(3) := 'abc'; BEGIN ... EXCEPTION WHEN OTHERS THEN ... END;

Esta excepcin es inmediatamente propagada, sin ejecutar las instrucciones asociadas al manejador WHEN OTHERS DECLARE A EXCEPTION; B EXCEPTION; BEGIN RAISE A; EXCEPTION WHEN A THEN RAISE B; WHEN B THEN ... END;

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; BEGIN RAISE A; EXCEPTION WHEN A THEN ... RAISE; END;

DECLARE A EXCEPTION; B EXCEPTION; BEGIN BEGIN RAISE A; EXCEPTION WHEN A THEN RAISE B; WHEN B THEN ... END; EXCEPTION WHEN B THEN ... 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 31

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 <TIPO_TABLA> IS TABLE OF <TIPO> INDEX BY BINARY_INTEGER | PLS_INTEGER;

Donde <TIPO_TABLA> 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:

<NOMBRE_TABLA> ( <NDICE> )

Donde <NOMBRE_TABLA>, es el nombre que hemos dado al definir una variable de <TIPO_TABLA> e <NDICE> 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 32

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 33

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:

<NOMBRE_TABLA> ( <NDICE> ) . <NOMBRE_CAMPO>

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 34

Resumen PL/SQL II

Pgina 35

MTODOS PARA LAS TABLAS INDEXADAS

Las tablas indexadas tienen definidos una serie de mtodos. Utilizan la siguiente sintaxis:

<NOMBRE_TABLA>.<METODO> [ (<PARAMETRO>) ]

EXISTS
Se utiliza para averiguar si existe en la coleccin el elemento indicado a partir de un ndice dado. Su sintaxis es EXISTS( <NMERO> ). 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( <NMERO> ).

PRIOR
Devuelve el ndice del elemento anterior de una coleccin respecto a un ndice dado. Su sintaxis es PRIOR( <NMERO> ).

Resumen PL/SQL II

Pgina 36

DELETE
DELETE Elimina todos los elementos de una tabla PL/SQL. DELETE(<NMERO>) Elimina el elemento de la posicin indicada por <NMERO> de la tabla PL/SQL. DELETE(<NMERO_INICIAL>, <NMERO_FINAL>) Elimina los elementos del rango indicado por <NMERO_INICIAL> y <NMERO_FINAL> de la tabla PL/SQL.

Resumen PL/SQL II

Pgina 37

--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 <= V_NUM LOOP DBMS_OUTPUT.PUT_LINE(' - '||V_ENT(V_IND).ARTICULO ); V_IND := V_ENT.NEXT(V_IND); V_CONT := V_CONT + 1; END LOOP; EXCEPTION WHEN NO_DATA_FOUND THEN DBMS_OUTPUT.PUT_LINE('POSICIONAMIENTO INCORRECTO'); END; /

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_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 39

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 <NOMBRE_TABLA> IS TABLE OF <TIPO_TABLA> [ NOT NULL ];

Donde <NOMBRE_TABLA> es el nombre del nuevo tipo declarado y <TIPO_TABLA> es el tipo de cada elemento de la tabla anidada. El tipo <TIPO_TABLA> 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 40

DECLARE TYPE TABLA_NUMERO IS TABLE OF NUMBER; V_TAB1 TABLA_NUMERO := TABLA_NUMERO(-1); V_TAB2 TABLA_NUMERO := TABLA_NUMERO(); V_TAB3 TABLA_NUMERO := TABLA_NUMERO(1, 2, 3, 5, 7); -- Crea una tabla con un elemento -- Crea una tabla sin ningn elemento. -- 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 41

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 42

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 43

MTODOS PARA LAS TABLAS INDEXADAS, ANIDADAS Y VARRAYS

Las tablas indexadas, anidadas y varrays tienen definidos una serie de mtodos. Utilizan la siguiente sintaxis:

<NOMBRE_TABLA>.<METODO> [ (<PARAMETRO>) ]

EXISTS
Se utiliza para averiguar si existe en la coleccin el elemento indicado a partir de un ndice dado. Su sintaxis es EXISTS( <NMERO> ). 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 44

NEXT
Devuelve el ndice del elemento siguiente de una coleccin respecto a un ndice dado. Su sintaxis es NEXT( <NMERO> ). 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( <NMERO> ). Vlido para tablas indexadas, tablas anidadas y varrays.

DELETE
DELETE Elimina todos los elementos de una tabla PL/SQL. DELETE(<NMERO>) Elimina el elemento de la posicin indicada por <NMERO> de la tabla PL/SQL. DELETE(<NMERO_INICIAL>, <NMERO_FINAL>) Elimina los elementos del rango indicado por <NMERO_INICIAL> y <NMERO_FINAL> 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 45

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(<NMERO>)
Aade <NMERO> elementos de valor NULL al final de la coleccin.

EXTEND(<NMERO>, <ELEMENTO> )
Aade <NMERO> copias del elemento <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(<NMERO> ) Elimina <NMERO> elementos al final de una coleccin. Si <NMERO> es mayor que COUNT se genera la excepcin SUBSCRIPT_BEYOND_COUNT. Vlido para tablas anidadas, varrays.

Resumen PL/SQL II

Pgina 46

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 <= v_Numeros.last LOOP DBMS_OUTPUT.PUT_LINE(' valores ' || v_Numeros(contador)); contador:=v_Numeros.next(contador); END LOOP; v_Numeros.delete(9); v_Numeros.trim(1); DBMS_OUTPUT.PUT_LINE('NUEVOS VALORES '); contador:=v_Numeros.first; WHILE contador <= v_Numeros.last LOOP DBMS_OUTPUT.PUT_LINE(' valores ' || v_Numeros(contador)); contador:=v_Numeros.next(contador); END LOOP; EXCEPTION WHEN NO_DATA_FOUND THEN DBMS_OUTPUT.PUT_LINE('Datos no existentes '); END; /

Resumen PL/SQL II

Pgina 47

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 <NOMBRE_TIPO> IS VARRAY <TAMAO_MXIMO> OF <TIPO_ELEMENTO> [ NOT NULL ];

Donde <NOMBRE_TIPO> es el nombre del nuevo tipo de varray, <TAMAO_MXIMO> es un entero que especifica el nmero mximo de elementos del varray y <TIPO_ELEMENTO> 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 48

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 49

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 <= v_Numeros.last LOOP DBMS_OUTPUT.PUT_LINE(' valores ' || v_Numeros(contador)); contador:=v_Numeros.next(contador); END LOOP;

v_Numeros.trim(3); v_Numeros.extend; v_Numeros(10) := 110; DBMS_OUTPUT.PUT_LINE('NUEVOS VALORES '); contador:=v_Numeros.first; WHILE contador <= v_Numeros.last LOOP DBMS_OUTPUT.PUT_LINE(' valores ' || v_Numeros(contador)); contador:=v_Numeros.next(contador); END LOOP;

EXCEPTION WHEN NO_DATA_FOUND THEN DBMS_OUTPUT.PUT_LINE('Datos no existentes '); END;

Resumen PL/SQL II

Pgina 50

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 51

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 52

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 53

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 <NOMBRE_TABLA> AS <TIPO_TABLA> ;

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 curso CHAR(30), NUMBER(3),

lectura_obligada lista_libros );

Resumen PL/SQL II

Pgina 54

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 num_sacados NUMBER, 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 55

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; /

Resumen PL/SQL II

Pgina 56

También podría gustarte