Top Banner

of 56

Plsql Oracle

Oct 18, 2015

Download

Documents

Rodrigo Oviedo
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
  • 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;

    /