0% encontró este documento útil (0 votos)
483 vistas32 páginas

t09 Oracle PL SQL

El documento introduce PL/SQL de Oracle, un lenguaje de programación que extiende SQL con variables, estructuras de control y otras características de lenguajes de tercera generación. PL/SQL permite almacenar programas en la base de datos y ejecutarlos de forma más eficiente. También es necesario para crear disparadores que implementen reglas complejas de negocio y auditoría.
Derechos de autor
© Attribution Non-Commercial (BY-NC)
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
483 vistas32 páginas

t09 Oracle PL SQL

El documento introduce PL/SQL de Oracle, un lenguaje de programación que extiende SQL con variables, estructuras de control y otras características de lenguajes de tercera generación. PL/SQL permite almacenar programas en la base de datos y ejecutarlos de forma más eficiente. También es necesario para crear disparadores que implementen reglas complejas de negocio y auditoría.
Derechos de autor
© Attribution Non-Commercial (BY-NC)
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
Está en la página 1/ 32

Tema 9. PL/SQL de ORACLE.

Pgina 1 de 32

Introduccin.
El trabajo realizado hasta ahora con la base de datos se ha hecho de forma interactiva: el usuario introduca una orden (en SQL) y Oracle proporcionaba una respuesta. Esta forma de trabajar no resulta operativa en un entorno de produccin, porque todos los usuarios no conocen ni utilizan SQL, y adems suelen producirse frecuentes errores. Para superar estas limitaciones, Oracle incorpora un gestor PL/SQL en el servidor de la BD y en algunas de sus herramientas (Forms, Reports, Graphics, etc.). Este lenguaje incorpora todas las caractersticas propias de los lenguajes de tercera generacin: manejo de variables, estructura modular (procedimientos y funciones), estructuras de control (bifurcaciones, bucles y dems estructuras), control de excepciones, y una total integracin en el entorno Oracle. Los programas creados con PL/SQL se pueden almacenar en la base de datos como un objeto ms de sta; as se facilita a todos los usuarios autorizados el acceso a estos programas, y en consecuencia, la distribucin, instalacin y mantenimiento de software. Adems, los programas se ejecutan en el servidor, suponiendo un significativo ahorro de recursos en los clientes y de disminucin del trfico de red. El uso del lenguaje PL/SQL es tambin imprescindible para construir disparadores de bases de datos, que permiten implementar reglas complejas de negocio y auditoria en la BD. PL/SQL soporta todos los comandos de consulta y manipulacin de datos, aportando sobre SQL las estructuras de control y otros elementos propios de los lenguajes procedimentales de tercera generacin. Su unidad de trabajo es el bloque, formado por un conjunto de declaraciones, instrucciones y mecanismos de gestin de errores y excepciones.

Transacciones.
Oracle es un sistema de base de datos puramente transaccional, de tal forma, que la instruccin BEGIN TRANSACTION no existe. Una transaccin es un conjunto de sentencias SQL que se ejecutan en una base de datos como una nica operacin, confirmndose o deshacindose todo el conjunto de sentencias SQL. La transaccin puede quedar finalizada (con las sentencias apropiadas) o implcitamente (terminando la sesin). Durante la transaccin, todas las modificaciones que hagamos sobre base de datos, no son definitivas, ms concretamente, se realizan sobre un tablespace especial que se denomina tablespace de ROLLBACK, o RBS (RollBack Segment). Este tablespace tiene reservado un espacio para cada sesin activa en el servidor, y es en ese espacio donde se almacenan todas las modificaciones de cada transaccin. Una vez que la transaccin se ha finalizado, las modificaciones temporales almacenadas en el RBS, se vuelcan al tablespace original, donde est almacenada nuestra tabla. Esto permite que ciertas modificaciones que se realizan en varias sentencias, se puedan validar todas a la vez, o rechazar todas a la vez. Dentro de una transaccin se pueden crear los llamados punto de control mediante la sentencia:
SAVEPOINT Nombre_punto_control

I.E.S. Francisco Ayala ( P.C. - Dpto. Informtica)

Tema 9. PL/SQL de ORACLE.

Pgina 2 de 32

Las sentencias de finalizacin de transaccin son: COMMIT: la transaccin termina correctamente, se vuelcan los datos al tablespace original y se vaca el RBS. ROLLBACK: se rechaza la transaccin y el vaca el RBS. Cualquier cambio realizado desde que se inici la transaccin se deshace, quedando la base de datos en el mismo estado que antes de iniciarse la transaccin.

A la hora de hacer un ROLLBACK o un COMMIT se podr hacer hasta cierto punto con la sintaxis:
COMMIT TO punto_control; ROLLBACK TO punto_control;

Cuando tenemos abierta una sesin (WorkSheet), los cambios que realizamos no son visibles a otra sesin hasta que no hagamos un COMMIT. Este se puede realizar de forma manual, ejecutando el comando COMMIT; o bien, de forma automtica, cuando cerramos la sesin. En una transaccin los datos modificados no son visibles por el resto de usuarios hasta que se confirme la transaccin. Si alguna de las tablas afectadas por la transaccin tiene triggers, las operaciones que realiza el trigger estn dentro del mbito de la transaccin, y son confirmadas o deshechas conjuntamente con la transaccin. Durante la ejecucin de una transaccin, una segunda transaccin no podr ver los cambios realizados por la primera transaccin hasta que esta se confirme. El siguiente ejemplo muestra una supuesta transaccin bancaria:
DECLARE importe NUMBER; ctaOrigen VARCHAR2(23); ctaDestino VARCHAR2(23); BEGIN importe := 100; ctaOrigen := '2530 10 2000 1234567890'; ctaDestino := '2532 10 2010 0987654321'; UPDATE CUENTAS SET SALDO = SALDO importe WHERE CUENTA = ctaOrigen; UPDATE CUENTAS SET SALDO = SALDO + importe WHERE CUENTA = ctaDestino; INSERT INTO MOVIMIENTOS VALUES (ctaOrigen, ctaDestino, importe*(-1), SYSDATE); INSERT INTO MOVIMIENTOS VALUES (ctaDestino,ctaOrigen, importe, SYSDATE); COMMIT; EXCEPTION WHEN OTHERS THEN dbms_output.put_line('Error en la transaccion:'||SQLERRM); dbms_output.put_line('Se deshacen las modificaciones); ROLLBACK; END;

I.E.S. Francisco Ayala ( P.C. - Dpto. Informtica)

Tema 9. PL/SQL de ORACLE.

Pgina 3 de 32

Programacin PL/SQL.
SQL es un lenguaje de consulta para los sistemas de bases de datos relacinales, pero que no posee la potencia de los lenguajes de programacin. PL/SQL (Procedural Language/Structured Query Language) apareci por primera vez en la versin 6 de Oracle (1988) y amplia SQL con los elementos caractersticos de los lenguajes de programacin: variables, sentencias de control de flujo, bucles... Cuando se desea realizar una aplicacin completa para el manejo de una base de datos relacional, resulta necesario utilizar alguna herramienta que soporte la capacidad de consulta del SQL y la versatilidad de los lenguajes de programacin tradicionales. PL/SQL es el lenguaje de programacin que proporciona Oracle para extender el SQL estndar con otro tipo de instrucciones. Para poder trabajar necesitaremos tener los siguientes elementos:

Una instancia de ORACLE o superior funcionando correctamente. Herramientas cliente de ORACLE, (WorkSheet o SQL*Plus) para poder ejecutar los ejemplos. Haber configurado correctamente una conexin a ORACLE.

Con PL/SQL vamos a poder programar las unidades de programa de la base de datos ORACLE, estn son:

Procedimientos almacenados Funciones Triger Scripts

Pero adems PL/SQL nos permite realizar programas sobre las siguientes herramientas de ORACLE:

Oracle Forms Oracle Reports Oracle Graphics Oracle Aplication Server

Fundamentos de PL/SQL

Para programar en PL/SQL es necesario conocer sus fundamentos. Como introduccin vamos a ver algunos elementos y conceptos bsicos del lenguaje.

PL/SQL no es CASE-SENSITIVE, es decir, no diferencia maysculas de minsculas como otros lenguajes de programacin como C o Java. Sin embargo debemos recordar que ORACLE es CASE-SENSITIVE en la bsqueda de texto. Una lnea en PL/SQL contiene grupos de caracteres conocidos como UNIDADES LEXICAS, que pueden ser clasificadas como: DELIMITADOR: Es un smbolo simple o compuesto que tiene una funcin especial en PL/SQL. Estos pueden ser: o o Operadores Aritmticos Operadores Lgicos

I.E.S. Francisco Ayala ( P.C. - Dpto. Informtica)

Tema 9. PL/SQL de ORACLE.

Pgina 4 de 32

Operadores Relacinales

IDENTIFICADOR: Se emplean para dar nombre a los objetos PL/SQL, tales como variables, cursores, tipos y subprogramas. Los identificadores constan de una letra, seguida por una secuencia opcional de caracteres, que pueden incluir letras, nmeros, signos de dlar ($), caracteres de subrayado y smbolos de almohadilla (#). Los dems caracteres no pueden emplearse. La longitud mxima de un identificador es de 30 caracteres y todos los caracteres son significativos. LITERAL: Es un valor de tipo numrico, carcter, cadena o lgico no representado por un identificador (es un valor explcito). COMENTARIO: Es una aclaracin que el programador incluye en el cdigo. Son soportados 2 estilos de comentarios, el de lnea simple y de multilnea, para lo cual son empleados ciertos caracters especiales como son:
-- Linea simple /* Conjunto de Lneas */

Cuando se escribe cdigo en PL/SQL, este puede estar agrupado en unidades denominadas conjunto de instrucciones. Un conjunto de instrucciones puede contener otros subconjuntos y as sucesivamente. Un conjunto de instrucciones queda delimitado por las palabras reservadas BEGIN y END.
BEGIN Sentencias . . . Sentencias . . . BEGIN Sentencias . . . Sentencias . . . Sentencias . . . END; Sentencias . . . Sentencias . . . END;

Bloques PL/SQL

Los bloques PL/SQL son de varios tipos: Annimos (Anonymous blocks). Se construyen de forma dinmica y se ejecutan una sola vez. Con nombre (Named blocks). Son bloques con nombre, que al igual que el anterior se construyen, generalmente, de forma dinmica y se ejecutan una sola vez. Subprogramas. Procedimientos, paquetes o funciones almacenados en la BD. No suelen cambiar despus de su construccin y se ejecutan mltiples veces mediante una llamada call. Disparadores(Triggers). Son bloques con nombre que tambin se almacenan en la BD. Tampoco suelen cambiar despus de su construccin y se ejecutan varias veces. Se ejecutan de forma automtica ante algn suceso de disparo, que ser una orden del lenguaje de

I.E.S. Francisco Ayala ( P.C. - Dpto. Informtica)

Tema 9. PL/SQL de ORACLE.

Pgina 5 de 32

manipulacin de datos (INSERT, UPDATE o DELETE) que se ejecuta sobre una tabla de la BD. Los bloques PL/SQL presentan una estructura especfica compuesta de tres partes bien diferenciadas:

La seccin declarativa en donde se declaran todas las constantes y variables que se van a utilizar en la ejecucin del bloque. Esta seccin es opcional. La seccin de ejecucin que incluye las instrucciones a ejecutar en el bloque PL/SQL. Estas instrucciones pueden ser tanto de tipo DML como DDL, as como ordenes procedimentales. Esta es la nica seccin que es obligatoria. La seccin de excepciones en donde se definen los manejadores de errores que soportar el bloque PL/SQL. Esta seccin es opcional y no se ejecutar a menos que aparezca un error.

Cada una de las partes anteriores se delimita por una palabra reservada, de modo que un bloque PL/SQL se puede representar como sigue:
[DECLARE Declaracin de variables] /*Parte declarativa*/ BEGIN Sentencias SQL y PL/SQL /*Parte de ejecucion*/ [EXCEPTION Manejadores de excepciones] /*Parte de excepciones*/ END;

Un bloque annimo es aquel bloque que no tiene asignado un nombre.


SET SERVEROUTPUT ON; DECLARE A VARCHAR(10) := ; BEGIN SELECT TO_CHAR(SYSDATE) INTO A FROM DUAL; DBMS_OUTPUT.PUT_LINE('LA FECHA ACTUAL ES : ' || A); EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE('HOLA'); END;

Para que la salida pueda verse al ejecutar el programa tiene que estar activa la siguiente variable:
SET SEVEROUTPUT ON;

Para mostrar el contenido de una expresin se debe utilizar la sentencia:


DBMS_OUTPUT.PUT_LINE (cadena_caracteres) Declaracin de variables

Las variables deben declararse dentro de la seccin DECLARE y deben seguir la siguiente sintaxis:
Nombre_variable [CONSTANT] TIPO [NOT NULL] [:= inicializacin];

I.E.S. Francisco Ayala ( P.C. - Dpto. Informtica)

Tema 9. PL/SQL de ORACLE.

Pgina 6 de 32

Cualquier variable que se declare y no se inicialice tiene por defecto el valor NULL. Los tipos posibles son todos aquellos vlidos para SQL aadiendo algunos propios de PL/SQL. Para ms informacin sobre los tipos propios de PL/SQL consultar el PL/SQL Users Guide and Referente. Podemos hacer que una variable nunca tome valores nulos utilizando la clusula NOT NULL, en este caso, hay que inicializar la variable. La declaracin de una constante es similar a la declaracin de una variable, aadiendo la palabra CONSTANT y asignndole a continuacin un valor a la constante. Ejemplos:
Interes NUMBER(5,3); Descripcion VARCHAR2(50) := inicial; Fecha_max DATE; Contabilizado BOOLEAN := TRUE; PI CONSTANT REAL := 3.14159

Otra forma de asignarle un valor a una variable es mediante la clausula INTO de la sentencia SELECT:
SELECT COUNT(*) INTO xNumFac FROM FACTURAS;

Atributos %TYPE y %ROWTYPE.

Se puede declarar el tipo de una variable tomndolo de otro identificador, usando el atributo %TYPE y se puede declarar el tipo de una variable tambin cuando es un tipo estructurado con el atributo %ROWTYPE. Esto es particularmente til cuando una variable va a tomar valores de una columna de una tabla. Declarar variables con el atributo %TYPE tiene dos ventajas. Primero, no necesitamos conocer el tipo exacto de la columna de la tabla. Segundo, si cambiamos la definicin y/o tipo de la columna de la tabla, el tipo de la variable cambia automticamente en tiempo de ejecucin. En la declaracin: si tenemos una variable y por ejemplo, y est declarada de tipo char podemos declarar otra variable j de la siguiente forma:
J y%type;

Lo mismo ocurrira para declarar una estructura que ya esta declarada como por ejemplo una tabla que ya tenemos declarada. Ejemplo:
J employee%rowtype J tendra la misma estructura que la tabla employee.

En este caso para acceder a cada campo que tuviera el tabla employee mediante la variable J tendramos que usar la estructura variable.nombre_campo. Un bloque tiene acceso a los objetos identificados dentro de su esquema. Solo podremos acceder a los objetos del usuario donde estemos conectados y a los que ese usuario pueda acceder porque le hayan otorgado permisos.

I.E.S. Francisco Ayala ( P.C. - Dpto. Informtica)

Tema 9. PL/SQL de ORACLE.

Pgina 7 de 32

Estructuras bsicas de control

Como PL/SQL es un lenguaje 3GL, cuenta con las estructuras tpicas de control de flujo: bifurcaciones condicionales y bucles:
Bifurcaciones condicionales:

a. IF. La sintaxis bsica es:


IF condicin THEN --Se ejecuta si se cumple condicin Bloque de instrucciones; [ELSIF condicin THEN --Se ejecuta si no se cumple condicin Bloque de instrucciones;] ... [ELSE --Se ejecuta si no se cumple condicin Bloque de instrucciones;] END IF;

Como en cualquier lenguaje de programacin, condicin es cualquier expresin que de cmo resultado un valor booleano. Hay que saber que las estructuras IF se pueden anidar unas dentro de otras.
a. IF THEN

Se evala la condicin y si resulta verdadera, se ejecutan uno o ms lneas de cdigo de programa. En el caso de que la condicin resulte falsa o nula, NO se realiza NINGUNA accin.
IF fecha_nac < 1-01-1970 THEN Salario := salario *1.15; END IF; --No termina con un ; --aumento de salario en un 15%

Se pueden anidar varias instrucciones:


IF fecha_nac < 1-01-1970 THEN IF apellido =Martnez THEN salario:= salario *1.15; END IF; END IF; b. IF THEN ELSE --IF ANIDADO --aumento de salario en un 15% --END IF OBLIGATORIO

Se evala la condicin y si resulta verdadera, se ejecutan uno o ms lneas de cdigo de programa. En el caso de que la condicin resulte falsa, se ejecutan las instrucciones que siguen a la instruccin ELSE. Slo se permite una instruccin ELSE en cada instruccin IF.
IF fecha_nac <1-01-1970 THEN salario:= salario *1.15; ELSE salario:= salario* 1.05; END IF; --No termina con un ; --aumento de salario en un 15% --No termina con un ; --aumento de salario en un 5%

I.E.S. Francisco Ayala ( P.C. - Dpto. Informtica)

Tema 9. PL/SQL de ORACLE. c. IF THEN ELSIF

Pgina 8 de 32

Se evala la condicin y si resulta verdadera, se ejecutan uno o ms lneas de cdigo de programa. En el caso de que la condicin resulte ser falsa, se evala la condicin especificada en el ELSIF.

IF apellido =Prez THEN salario:= salario *1.10; --aumento de salario en un 10% ELSIF apellido =Martnez THEN salario:= salario *1.15; --aumento de salario en un 15% ELSIF apellido=Alvarez THEN salario:= salario *1.20; --aumento de salario en un 20% ELSE salario:= salario* 1.05; --aumento de salario en un 5% END IF; --Slo se necesita un nico END IF

b. CASE La instruccin CASE puede evaluar mltiples expresiones y devolver para cada una de ellas un valor/bloque de instrucciones. El resultado de cada WHEN puede ser un valor o una sentencia; en el primer caso el resultado de una sentencia CASE se puede guardar en una variable. Su sintaxis es:
CASE variable WHEN expresin1 THEN valor1/bloque de instrucciones WHEN expresin2 THEN valor2/bloque de instrucciones WHEN expresin3 THEN valor3/bloque de instrucciones WHEN expresin4 THEN valor4/bloque de instrucciones ELSE valor5/bloque de instrucciones END

Ejemplos:
CREATE TABLE C2 ( Nombre VARCHAR2(20 ), EC VARCHAR2(1) ); COMMIT; INSERT INTO C2 ( NOMBRE, EC ) VALUES ('Juan ', 'S'); INSERT INTO C2 ( NOMBRE, EC ) VALUES ('Maria', 'C'); INSERT INTO C2 ( NOMBRE, EC ) VALUES ('Ana', 'D'); INSERT INTO C2 ( NOMBRE, EC ) VALUES ('Luis', 'S'); INSERT INTO C2 ( NOMBRE, EC ) VALUES ('Pepe', NULL); COMMIT;

I.E.S. Francisco Ayala ( P.C. - Dpto. Informtica)

Tema 9. PL/SQL de ORACLE.

Pgina 9 de 32

SELECT Nombre, CASE EC WHEN 'C' THEN 'Casado/a' WHEN 'S' THEN 'Soltero/a' WHEN 'D' THEN 'Divorciado/a' ELSE 'Otros' END AS "Estado Civil" FROM C2;

Otra sintaxis es:


CASE WHEN condicin1 THEN expresin1/bloque de instrucciones WHEN condicin2 THEN expresin2/bloque de instrucciones WHEN condicin3 THEN expresin3/bloque de instrucciones WHEN condicin4 THEN expresin4/bloque de instrucciones ELSE expresin5/bloque de instrucciones END

En esta sintaxis despus del CASE no aparece ninguna variable y cada WHEN tiene su propia condicin a evaluar.
Bucles LOOP sentencias END LOOP;

Las sentencias de dentro del bucle se ejecutarn durante un nmero indefinido de vueltas, hasta que aparezca la instruccin EXIT; que finalizar el bucle. Este tipo de bucle se denomina bucle incondicional.
LOOP Sentencias IF (expresion) THEN Sentencias EXIT; END IF; END LOOP;

Otra opcin es incluir la estructura EXIT WHEN condicin, se terminar el bucle cuando la condicin se cumpla:
LOOP Sentencias EXIT WHEN condicin; Sentencias END LOOP;

Ejemplo
DECLARE -- declare and assign values to variables total NUMBER(9) := 0; counter NUMBER(6) := 0; BEGIN LOOP

I.E.S. Francisco Ayala ( P.C. - Dpto. Informtica)

Tema 9. PL/SQL de ORACLE. counter := counter + 1; -- increment counter variable total := total + counter * counter; -- compute total -- exit loop when condition is true EXIT WHEN total > 25000; -- LOOP until condition is met END LOOP; DBMS_OUTPUT.PUT_LINE('Counter: ' || TO_CHAR(counter) || ' Total: ' || TO_CHAR(total)); END;

Pgina 10 de 32

Un tipo de bucle ms comn son los bucles condicionales:


WHILE condicion LOOP Sentencias END LOOP;

Ejemplo
DECLARE i NUMBER := 1; i_cubed NUMBER; BEGIN WHILE i <= 10 LOOP i_cubed := i**3; DBMS_OUTPUT.PUT_LINE('Number: ' || TO_CHAR(i) || ' Cube: ' || TO_CHAR(i_cubed)); i := i + 1; END LOOP; END;

En los bucles WHILE tambin se pueden utilizar las rdenes EXIT o EXIT WHEN para salirnos sin esperar a que la condicin devuelva un valor falso. Y por ltimo el bucle FOR:
FOR contador IN [REVERSE] limite_inferior..limite_superior LOOP sentencias END LOOP; Contador deber ser una variable de tipo numrico que sea capaz de contener los valores comprendidos entre limite_inferior y limite_superior, los cuales debern ser expresiones numricas, ya sean constantes (1,10) o funciones (ROUND(max,0), ASCII(A)) .

Si la variable contador no est definida, PL/SQL definir una variable de tipo INTEGER al iniciar el bucle, y la liberar al finalizar el bucle.
SET SERVEROUTPUT ON; BEGIN FOR loop_counter IN 1..10 LOOP DBMS_OUTPUT.PUT_LINE('Number: ' || TO_CHAR(loop_counter) || ' Square: ' || TO_CHAR(loop_counter**2)); END LOOP; END;

En el caso de especificar REVERSE el bucle se recorre en sentido inverso.

I.E.S. Francisco Ayala ( P.C. - Dpto. Informtica)

Tema 9. PL/SQL de ORACLE. Excepciones.

Pgina 11 de 32

Anteriormente dijimos que un bloque de cdigo puede contener una seccin denominada EXCEPTION. Esta seccin es la encargada de recoger todas las anomalas que se puedan producir dentro del bloque de cdigo. Una excepcin es una situacin especial dentro de la ejecucin de un programa, que puede ser capturada para asignar un nuevo comportamiento. Una excepcin puede ser un error de ejecucin (una divisin entre 0) o cualquier otro tipo de suceso. Las excepciones deben ser declaradas dentro de la seccin DECLARE, como si de una variable se tratase:
DECLARE e_sin_alumnos EXCEPTION;

Una vez que la excepcin est definida, sta debe ser lanzada, ya sea automticamente por Oracle ( cuando se produce un error controlado por Oracle ), o lanzada manualmente por el usuario a travs de la instruccin RAISE <excepcin>. La sintaxis del manejador de excepciones es:
EXCEPTION WHEN nb_excepcion_1 THEN instrucciones excep1; WHEN nb_excepcion_2 THEN instrucciones excep2; ... WHEN nb_excepcion_n THEN instrucciones excepn; [WHEN OTHERS THEN instrucciones;]

Ejemplo:
DECLARE VALOR_NEGATIVO EXCEPTION; valor NUMBER; BEGIN valor := -1; IF valor < 0 THEN RAISE VALOR_NEGATIVO; END IF; EXCEPTION WHEN VALOR_NEGATIVO THEN dbms_output.put_line('El valor no puede ser negativo'); END;

Cuando se produce un error, se ejecuta el bloque EXCEPTION. Si existe un bloque de excepcin apropiado para el tipo de error producido se ejecuta dicho bloque. Si este ltimo no existe, se ejecutar el bloque de excepcin WHEN OTHERS THEN ( en el caso de haberlo definido; este bloque debe ser el ltimo manejador de excepciones ). Una vez finalizada la ejecucin del bloque de EXCEPTION no se contina ejecutando el bloque anterior.

I.E.S. Francisco Ayala ( P.C. - Dpto. Informtica)

Tema 9. PL/SQL de ORACLE.

Pgina 12 de 32

En ocasiones queremos enviar un mensaje de error personalizado al producirse una excepcin PL/SQL. Para ello es necesario utilizar la instruccion RAISE_APPLICATION_ERROR;
RAISE_APPLICATION_ERROR(<error_num>,<mensaje>);

donde:

error_num es un entero negativo comprendido entre -20001 y -20999 mensaje la descripcin del error
DECLARE v_div NUMBER; BEGIN SELECT 1/0 INTO v_div FROM DUAL; EXCEPTION WHEN OTHERS THEN RAISE_APPLICATION_ERROR(-20001,'No se puede dividir por cero'); END;

Dentro del bloque de excepciones conviene recordar la existencia de la excepcin OTHERS, que simboliza cualquier condicin de excepcin que no ha sido declarada. Se utiliza comnmente para controlar cualquier tipo de error que no ha sido previsto. En ese caso, es comn observar la sentencia ROLLBACK en el grupo de sentencias de la excepcin o alguna de las funciones SQLCODE SQLERRM. SQLCODE devuelve el nmero del error de Oracle y un 0 (cero) en caso de xito al ejecutarse una sentencia SQL. SQLERRM devuelve el la descripcin del correspondiente mensaje de error. Tambin es posible entregarle a la funcin SQLERRM un nmero negativo que represente un error de Oracle y sta devolver el mensaje asociado. Estas funciones no pueden ser utilizadas directamente en una sentencia SQL, pero s se puede asignar su valor a alguna variable de programa y luego usar esta ltima en alguna sentencia.
SET SERVEROUTPUT ON;

DECLARE err_num NUMBER; err_msg VARCHAR2(255); result NUMBER; msg VARCHAR2(255); BEGIN msg := SQLERRM(-1403); DBMS_OUTPUT.put_line(MSG); SELECT 1/0 INTO result FROM DUAL; EXCEPTION WHEN OTHERS THEN err_num := SQLCODE; err_msg := SQLERRM; DBMS_OUTPUT.put_line('Error:'||TO_CHAR(err_num)); DBMS_OUTPUT.put_line(err_msg); END;

I.E.S. Francisco Ayala ( P.C. - Dpto. Informtica)

Tema 9. PL/SQL de ORACLE. DECLARE e_sinreg EXCEPTION; a number(10) := 25; b number(10) := 0; c number(10); BEGIN Select count(*) INTO a FROM Articulos; If a < 10 THEN RAISE e_sinreg; END IF; c := a / b; DBMS_OUTPUT.PUT_LINE(' Esto nunca llegar a mostrarse. ');

Pgina 13 de 32

EXCEPTION WHEN ZERO_DIVIDE THEN DBMS_OUTPUT.PUT_LINE('No se puede dividir por 0'); WHEN e_sinreg THEN DBMS_OUTPUT.PUT_LINE('Hay menos de 10 articulos.'); WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE('Se ha producido otra excepcin.'); END;

Las lneas de cdigo debajo del manejador especfico se ejecutarn cuando esa excepcin se produzca. Algunas excepciones se lanzarn automticamente cuando se produzcan ciertos tipos de errores en la ejecucin del bloque de cdigo. Cada excepcin automtica tiene asociado un cdigo de error ORA-XXXX el cual si se produce, har que se lance la excepcin correspondiente. A continuacin se muestra una lista de las excepciones automticas predefinidas por Oracle:

I.E.S. Francisco Ayala ( P.C. - Dpto. Informtica)

Tema 9. PL/SQL de ORACLE. CURSORES.

Pgina 14 de 32

Un cursor es el nombre para un rea memoria privada que contiene informacin procedente de la ejecucin de una sentencia SELECT. Cada cursor tiene unos atributos que nos devuelven informacin til sobre el estado del cursor en la ejecucin de la sentencia SQL. Cuando un cursor est abierto y los datos referenciados por la consulta SELECT cambian, estos cambios no son recogidos por el cursor. PL/SQL crea implcitamente un cursor para todas las sentencias SQL de manipulacin de datos sobre un conjunto de filas, incluyendo aquellas que solo devuelven una sola fila. En PL/SQL no se pueden utilizar sentencias SELECT de sintaxis bsica ( SELECT <lista> FROM <tabla(s)> ). PL/SQL utiliza cursores para gestionar las instrucciones SELECT. Un cursor es un conjunto de registros devuelto por una instruccin SQL. Podemos distinguir dos tipos de cursores:

Cursores implcitos. Este tipo de cursores se utiliza para operaciones SELECT INTO. Se usan cuando la consulta devuelve un nico registro. Cursores explcitos. Son los cursores que son declarados y controlados por el programador. Se utilizan cuando la consulta devuelve un conjunto de registros. Ocasionalmente tambin se utilizan en consultas que devuelven un nico registro por razones de eficiencia. Son ms rpidos.

Un cursor se define como cualquier otra variable de PL/SQL y debe nombrarse de acuerdo a los mismos convenios que cualquier otra variable. Los cursores implcitos se utilizan para realizar consultas SELECT que devuelven un nico registro. Deben tenerse en cuenta los siguientes puntos cuando se utilizan cursores implcitos:

Los cursores implcitos no deben ser declarados Con cada cursor implcito debe existir la palabra clave INTO. Las variables que reciben los datos devueltos por el cursor tienen que contener el mismo tipo de dato que las columnas de la tabla. Los cursores implcitos solo pueden devolver una nica fila. En caso de que se devuelva ms de una fila (o ninguna fila) se producir una excepcin. Las ms comunes son :
Excepcin

NO_DATA_FOUND Se produce cuando una sentencia SELECT intenta recuperar datos

pero ninguna fila satisface sus condiciones. Es decir, cuando "no hay datos"
TOO_MANY_ROWS Dado que cada cursor implcito slo es capaz de recuperar una fila ,

esta excepcin detecta la existencia de ms de una fila.

SET SERVEROUTPUT ON; declare vdescripcion VARCHAR2(50); begin SELECT DESCRIPCION INTO vdescripcion from PAISES WHERE CO_PAIS = 'ESP'; dbms_output.put_line('La lectura del cursor es: ' || vdescripcion); end;

I.E.S. Francisco Ayala ( P.C. - Dpto. Informtica)

Tema 9. PL/SQL de ORACLE.

Pgina 15 de 32

Para procesar instrucciones SELECT que devuelvan ms de una fila, son necesarios cursores explcitos combinados con una estructura de bloque. A partir de ahora, cuando hagamos referencia a cursores nos referiremos a cursores explcitos. Para trabajar con un cursor hay que realizar los siguientes pasos: 1.- Declarar el cursor 2.- Abrir el cursor en el servidor 3.- Recuperar cada una de sus filas (bucle) 4.- Cerrar el cursor
1. Declarar el cursor

Al igual que cualquier otra variable, el cursor se declara en la seccin DECLARE. Se define el nombre que tendr el cursor y qu consulta SELECT ejecutar. No es ms que una declaracin. La sintaxis bsica es:
CURSOR nombre_cursor IS instruccin_SELECT CURSOR nombre_cursor(param1 tipo1, ..., paramN tipoN) IS instruccin_SELECT

Una vez que el cursor est declarado ya podr ser utilizado dentro del bloque de cdigo. Antes de utilizar un cursor se debe abrir. En ese momento se ejecuta la sentencia SELECT asociada y se almacena el resultado en el rea de contexto (estructura interna de memoria que maneja el cursor). Un puntero seala a la primera fila
2. Abrir el cursor

Al abrir el cursor se ejecuta la sentencia SELECT asociada y cuyo resultado se guarda en el servidor en un rea de memoria interna (tablas temporales) de las cuales se va retornando cada una de las filas segn se va pidiendo desde el cliente. Al abrir un cursor, un puntero sealar al primer registro. La sintaxis de apertura de un cursor es:
OPEN nombre_cursor; OPEN nombre_cursor(valor1, valor2, ..., valorN);

Una vez que el cursor est abierto, se podr empezar a pedir los resultados al servidor.
3. Recuperar cada una de sus filas.

Una vez que el cursor est abierto en el servidor se podr hacer la peticin de recuperacin de fila. En cada recuperacin solo se acceder a una nica fila. La sintaxis de recuperacin de fila de un cursor es:
FETCH nombre_cursor INTO variables;

Podremos recuperar filas mientras la consulta SELECT tenga filas pendientes de recuperar. Para saber cundo no hay ms filas podemos consultar los siguientes atributos de un cursor:

I.E.S. Francisco Ayala ( P.C. - Dpto. Informtica)

Tema 9. PL/SQL de ORACLE.

Pgina 16 de 32

Al recuperar un registro, la informacin recuperada se guarda en una o varias variables. Si slo se hace referencia a una variable, sta se puede declarar con %ROWTYPE. Si se utiliza una lista de variables, cada variable debe coincidir en tipo y orden con cada una de las columnas de la sentencia SELECT. As lo accin ms tpica es recuperar filas mientras queden alguna por recuperar en el servidor. Esto lo podremos hacer a travs de los siguientes bloques:
OPEN nombre_cursor; LOOP FETCH nombre_cursor INTO variables; EXIT WHEN nombre_cursor%NOTFOUND; <procesar cada una de las filas> END LOOP; 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;

FOR variable IN nombre_cursor LOOP /* Procesamiento de los registros recuperados */ END LOOP; 4. Cerrar el cursor

Una vez que se han recuperado todas las filas del cursor, hay que cerrarlo para que se liberen de la memoria del servidor los objetos temporales creados. Si no cerrsemos el cursor, la tabla temporal quedara en el servidor almacenada con el nombre dado al cursor y la siguiente vez ejecutsemos ese bloque de cdigo, nos dara la excepcin CURSOR_ALREADY_OPEN (cursor ya abierto) cuando intentsemos abrir el cursor. Para cerrar el cursor se utiliza la siguiente sintaxis:
CLOSE nombre_cursor;

Cuando trabajamos con cursores debemos considerar:


Cuando un cursor est cerrado, no se puede leer. Cuando leemos un cursor debemos comprobar el resultado de la lectura utilizando los atributos de los cursores. Cuando se cierra el cursor, es ilegal tratar de usarlo. El nombre del cursor es un identificador, no una variable. Se utiliza para identificar la consulta, por eso no se puede utilizar en expresiones.

Atributos en cursores implcitos Los cursores implcitos no se pueden manipular por el usuario, pero Oracle s permite el uso de sus atributos. Las sentencia a travs de las que podemos obtener informacin de estos atributos son: SELECT...INTO, INSERT, UPDATE, DELETE.

I.E.S. Francisco Ayala ( P.C. - Dpto. Informtica)

Tema 9. PL/SQL de ORACLE.

Pgina 17 de 32

En este caso, se debe anteponer al nombre del atributo el prefijo SQL, en lugar del nombre del cursor. SQL%NOTFOUND devuelve TRUE cuando la ltima sentencia SELECT no recuper ninguna fila, o cuando INSERT, DELETE o UPDATE no afectan a ninguna fila SQL%FOUND devuelve TRUE cuando la ltima sentencia SELECT devuelve alguna fila, o cuando INSERT, DELETE o UPDATE afectan a alguna fila SQL%ROWCOUNT devuelve el nmero de filas afectadas por INSERT, DELETE o UPDATE o las filas devueltas por una sentencia SELECT SQL%ISOPEN siempre devuelve FALSE, porque Oracle cierra automticamente el cursor implcito cuando termina la ejecucin de la sentencia SELECT

Ejemplos:

DECLARE CURSOR cpaises IS SELECT CO_PAIS, DESCRIPCION, CONTINENTE FROM PAISES; co_pais VARCHAR2(3); descripcion VARCHAR2(50); continente VARCHAR2(25); BEGIN OPEN cpaises; FETCH cpaises INTO co_pais,descripcion,continente; DBMS_OUTPUT.PUT_LINE(continente); CLOSE cpaises; END; DECLARE CURSOR cpaises IS SELECT CO_PAIS, DESCRIPCION, CONTINENTE FROM PAISES; registro cpaises%ROWTYPE; BEGIN OPEN cpaises; FETCH cpaises INTO registro; DBMS_OUTPUT.PUT_LINE(continente); CLOSE cpaises; END; DECLARE r ARTICULOS%ROWTYPE; BEGIN FOR r IN ( SELECT * FROM ARTICULOS ) LOOP DBMS_OUTPUT.PUT_LINE(r.cArtDsc); END LOOP; END; BEGIN UPDATE ARTICULOS SET cArtDsc = `Pantalla LCD WHERE cCodArt = LCD; IF SQL%NOTFOUND THEN -- Otra opcin : SQL%ROWCOUNT = 0 INSERT INTO ARTICULOS (cCodArt,cDesArt) VALUES (LCD,Pantalla LCD); END IF; END;

I.E.S. Francisco Ayala ( P.C. - Dpto. Informtica)

Tema 9. PL/SQL de ORACLE. Cursores Parametrizados

Pgina 18 de 32

Los cursores son aquellos que permiten utilizar la orden OPEN para pasarle al cursor el valor de uno o varios de sus parmetros.
DECLARE CURSOR cArt (cFml Articulos.cArtFml%TYPE) IS SELECT cArtCdg,cArtDsc FROM Articulos WHERE cArtFml = cFml; xCod Articulos.cArtCdg%TYPE; xDes Articulos.cArtDsc%TYPE; BEGIN OPEN cArt('F1'); LOOP FETCH cArt INTO xCod,xDes; EXIT WHEN cArt%NOTFOUND; DBMS_OUTPUT.PUT_LINE (xDes); END LOOP; CLOSE cArt; END; Cursores de actualizacin

Los cursores de actualizacin se declaran igual que los cursores explcitos, aadiendo FOR UPDATE al final de la sentencia SELECT.
CURSOR nombre_cursor IS instruccin_SELECT FOR UPDATE

Para actualizar los datos del cursor hay que ejecutar una sentencia UPDATE especificando la clusula WHERE CURRENT OF <cursor_name>.
UPDATE <nombre_tabla> SET <campo_1> = <valor_1>[,<campo_2> = <valor_2>] WHERE CURRENT OF <cursor_name>

Cuando trabajamos con cursores de actualizacin debemos tener en cuenta que la sentencia UPDATE genera bloqueos en la base de datos ( transacciones, disparadores,etc).
DECLARE CURSOR cpaises IS select CO_PAIS, DESCRIPCION, CONTINENTE from paises FOR UPDATE; co_pais VARCHAR2(3); descripcion VARCHAR2(50); continente VARCHAR2(25); BEGIN OPEN cpaises; FETCH cpaises INTO co_pais,descripcion,continente; WHILE cpaises%found LOOP UPDATE PAISES SET CONTINENTE = CONTINENTE || '.' WHERE CURRENT OF cpaises; FETCH cpaises INTO co_pais,descripcion,continente; END LOOP; CLOSE cpaises; COMMIT; END;

I.E.S. Francisco Ayala ( P.C. - Dpto. Informtica)

Tema 9. PL/SQL de ORACLE. FUNCIONES, PROCEDIMIENTOS Y PAQUETES.

Pgina 19 de 32

Una vez que tenemos escrito un bloque de cdigo, podemos guardarlo en un fichero .SQL para su posterior uso, o bien guardarlo en base de datos para que pueda ser ejecutado por cualquier aplicacin. El segundo caso se realiza mediante procedimientos almacenados (Stored Procedure). A la hora de guardar un bloque de cdigo hay que tener en cuenta ciertas normas: Palabra reservada DECLARE desaparece. Podremos crear procedimientos y funciones. Los procedimientos no podrn retornar ningn valor sobre su nombre, mientras que las funciones deben retornar un valor de un tipo de dato bsico.

Un procedimiento [almacenado] es un subprograma que ejecuta una accin especfica y que no devuelve ningn valor por si mismo, como sucede con las funciones. Un procedimiento tiene un nombre, un conjunto de parmetros (opcional) y un bloque de cdigo. Para crear un procedimiento (stored procedure: procedimiento almacenado) usaremos la siguiente sintaxis:
CREATE {OR REPLACE} PROCEDURE nombre_proc( param1 [IN | OUT | IN OUT] tipo,... ) IS -- Declaracin de variables locales BEGIN -- Instrucciones de ejecucin [EXCEPTION] -- Instrucciones de excepcin END;

Tras crear el procedimiento, ste se compila y luego se almacena en la BD de forma compilada. Este procedimiento luego puede ser invocado desde cualquier bloque PL/SQL. El uso de OR REPLACE permite sobrescribir un procedimiento existente. Si se omite, y el procedimiento existe, se producir, un error. Debemos especificar el tipo de datos de cada parmetro. Al especificar el tipo de dato del parmetro no debemos especificar la longitud del tipo, aunque si puede ser utilizando el operador %TYPE. Los parmetros pueden ser de entrada (IN), de salida (OUT) o de entrada salida (IN OUT). El valor por defecto es IN, y se toma ese valor en caso de que no especifiquemos nada.
CREATE OR REPLACE PROCEDURE Actualiza_Saldo(cuenta NUMBER, new_saldo NUMBER) IS -- Declaracion de variables locales BEGIN UPDATE SALDOS_CUENTAS SET SALDO = new_saldo, FX_ACTUALIZACION = SYSDATE WHERE CO_CUENTA = cuenta; END Actualiza_Saldo;

Tambin podemos asignar un valor por defecto a los parmetros, utilizando la clusula DEFAULT o el operador de asignacin (:=) .
CREATE OR REPLACE PROCEDURE Actualiza_Saldo(cuenta NUMBER, new_saldo NUMBER DEFAULT 10)

I.E.S. Francisco Ayala ( P.C. - Dpto. Informtica)

Tema 9. PL/SQL de ORACLE.

Pgina 20 de 32

Una vez creado y compilado el procedimiento almacenado podemos ejecutarlo. Existen dos formas de pasar argumentos a un procedimiento almacenado a la hora de ejecutarlo. Estas son:

Notacin posicional: Se pasan los valores de los parmetros en el mismo orden en que el procedure los define.
BEGIN Actualiza_Saldo(200501,2500); COMMIT; END;

Notacin nominal: Se pasan los valores en cualquier orden nombrando explcitamente el parmetro y su valor separados por el smbolo => .
BEGIN Actualiza_Saldo(cuenta => 200501,new_saldo => 2500); COMMIT; END; CREATE OR REPLACE PROCEDURE today_is AS BEGIN DBMS_OUTPUT.PUT_LINE( 'Hoy es ' || TO_CHAR(SYSDATE, ' DD/MM/YYYY') ); END today_is; / -- para ejecutarlo SET SERVEROUTPUT ON; BEGIN today_is(); -- the parentheses are optional here END; CREATE OR REPLACE PROCEDURE today2_is ( fecha DATE ) AS BEGIN DBMS_OUTPUT.PUT_LINE( 'Hoy es ' || TO_CHAR(fecha, ' DD/MM/YYYY') ); END; -- para ejecutarlo SET SERVEROUTPUT ON; BEGIN today2_is(to_date('01/02/2008')); -- the parentheses are optional here END; -- para ejecutarlo SET SERVEROUTPUT ON; BEGIN today2_is(fecha => to_date('01/02/2008')); -- the parentheses are optional here END;

Para crear una funcin usaremos la siguiente sintaxis:


CREATE {OR REPLACE} FUNCTION nombre_func(param1 tipo,param2 tipo,... ) RETURN tipo_dato IS -- Declaracin de variables locales BEGIN -- Instrucciones de ejecucin [EXCEPTION] -- Instrucciones de excepcin END;

I.E.S. Francisco Ayala ( P.C. - Dpto. Informtica)

Tema 9. PL/SQL de ORACLE.

Pgina 21 de 32

Packages.
Adems de brindarnos mltiples elementos que nos permiten desarrollar una aplicacin robusta, Oracle nos ofrece la posibilidad de programar en forma modular, clara y eficiente. En este apartado veremos cmo embeber procedimientos, funciones, definiciones de tipos de datos y declaraciones de variables en una misma estructura que los agrupe y relacione lgicamente. Esta estructura se denomina Package (Paquete) y su uso nos permite no slo mejorar la calidad de diseo de nuestras aplicaciones sino tambin optimizar el desempeo de las mismas. Un Paquete es un objeto PL/Sql que agrupa lgicamente otros objetos PL/Sql relacionados entre s, encapsulndolos y convirtindolos en una unidad dentro de la base de datos. Los Paquetes estn divididos en 2 partes: especificacin (obligatoria) y cuerpo (no obligatoria). La especificacin o encabezado es la interfaz entre el Paquete y las aplicaciones que lo utilizan y es all donde se declaran los tipos, variables, constantes, excepciones, cursores, procedimientos y funciones que podrn ser invocados desde fuera del paquete. En el cuerpo del paquete se implementa la especificacin del mismo. El cuerpo contiene los detalles de implementacin y declaraciones privadas, mantenindose todo esto oculto a las aplicaciones externas, siguiendo el conocido concepto de caja negra. Slo las declaraciones hechas en la especificacin del paquete son visibles y accesibles desde fuera del paquete (por otras aplicaciones o procedimientos almacenados) quedando los detalles de implementacin del cuerpo del paquete totalmente ocultos e inaccesibles para el exterior. Para acceder a los elementos declarados en un paquete basta con anteceder el nombre del objeto referenciado con el nombre del paquete donde est declarado y un punto, de esta manera: Paquete.Objeto donde Objeto puede ser un tipo, una variable, un cursor, un procedimiento o una funcin declarados dentro del paquete. Para referenciar objetos desde adentro del mismo paquete donde han sido declarados no es necesario especificar el nombre del paquete y pueden (deberan) ser referenciados directamente por su nombre. Finalmente y siguiendo a la parte declarativa del cuerpo de un paquete puede, opcionalmente, incluirse la seccin de inicializacin del paquete. En esta seccin pueden, por ejemplo, inicializarse variables que utiliza el paquete. La seccin de inicializacin se ejecuta slo la primera vez que una aplicacin referencia a un paquete, esto es, se ejecuta slo una vez por sesin. Como hemos dicho anteriormente, la creacin de un paquete pasa por dos fases: Crear la cabecera del paquete donde se definen que procedimientos, funciones, variables, cursores, etc. Disponibles para su uso posterior fuera del paquete. En esta parte solo se declaran los objetos, no se implementa el cdigo. Crear el cuerpo del paquete, donde se definen los bloques de cdigo de las funciones y procedimientos definidos en la cabecera del paquete.
CREATE {OR REPLACE} PACKAGE nombre_de_paquete IS < Declaraciones > END; Para crear el cuerpo del paquete utilizaremos la siguiente instruccin: CREATE {OR REPLACE} PACKAGE BODY nombre_paquete IS < Bloques de cdigo> END;

Para crear la cabecera del paquete utilizaremos la siguiente instruccin:

I.E.S. Francisco Ayala ( P.C. - Dpto. Informtica)

Tema 9. PL/SQL de ORACLE.

Pgina 22 de 32

Hay que tener en cuenta que toda declaracin de funcin o procedimiento debe estar dentro del cuerpo del paquete, y que todo bloque de cdigo contenido dentro del cuerpo debe estar declarado dentro de la cabecera de paquete. Cuando se quiera acceder a las funciones, procedimientos y variables de un paquete se debe anteponer el nombre de este: Nombre_paquete.funcin(x) Nombre_paquete.procedimiento(x) Nombre_paquete.variable
CREATE OR REPLACE PACKAGE PK1 IS PROCEDURE xLis (xfamilia IN Articulos.cArtFml%TYPE); END; CREATE OR REPLACE PACKAGE BODY PK1 IS procedure xLis (xfamilia Articulos.cArtCdg%TYPE) IS xfam Articulos.cArtFml%type; xCod Articulos.cArtCdg%TYPE; xDes Articulos.cArtDsc%TYPE; CURSOR cArticulos IS SELECT cArtCdg,cArtDsc FROM Articulos WHERE cArtFml = xfam; BEGIN xfam := xfamilia; OPEN cArticulos; LOOP FETCH cArticulos INTO xCod,xDes; EXIT WHEN cArticulos%NOTFOUND; DBMS_OUTPUT.PUT_LINE (xDes); END LOOP; CLOSE cArticulos; END; END;

Ventajas del uso de Paquetes. Dentro de las ventajas que ofrece el uso de paquetes podemos citar que: Permite modularizar el diseo de nuestra aplicacin

El uso de Paquetes permite encapsular elementos relacionados entre s (tipos, variables, procedimientos, funciones) en un nico mdulo PL/Sql que llevar un nombre que identifique la funcionalidad del conjunto. Otorga flexibilidad al momento de disear la aplicacin

En el momento de disear una aplicacin todo lo que necesitaremos inicialmente es la informacin de interfaz en la especificacin del paquete. Puede codificarse y compilarse la especificacin sin su cuerpo para posibilitar que otros sub-programas que referencian a estos elementos declarados puedan compilarse sin errores. De esta manera podremos armar un prototipo de nuestro sistema antes de codificar el detalle del mismo.

I.E.S. Francisco Ayala ( P.C. - Dpto. Informtica)

Tema 9. PL/SQL de ORACLE.

Pgina 23 de 32

Permite ocultar los detalles de implementacin

Pueden especificarse cules tipos, variables y sub-programas dentro del paquete son pblicos (visibles y accesibles por otras aplicaciones y sub-programas fuera del paquete) o privados (ocultos e inaccesibles fuera del paquete). Por ejemplo, dentro del paquete pueden existir procedimientos y funciones que sern invocados por otros programas, as como tambin otras rutinas de uso interno del paquete que no tendrn posibilidad de ser accedidas fuera del mismo. Esto asegura que cualquier cambio en la definicin de estas rutinas internas afectar slo al paquete donde se encuentran, simplificando el mantenimiento y protegiendo la integridad del conjunto. Agrega mayor funcionalidad a nuestro desarrollo

Las definiciones pblicas de tipos, variables y cursores hechas en la especificacin de un paquete persisten a lo largo de una sesin. Por lo tanto pueden ser compartidas por todos los subprogramas y/o paquetes que se ejecutan en ese entorno durante esa sesin. Por ejemplo, puede utilizarse esta tcnica (en dnde slo se define una especificacin de paquete y no un cuerpo) para mantener tipos y variables globales a todo el sistema. Introduce mejoras al rendimiento

En relacin a su ejecucin, cuando un procedimiento o funcin que est definido dentro de un paquete es llamado por primera vez, todo el paquete es ingresado a memoria. Por lo tanto, posteriores llamadas al mismo u otros sub-programas dentro de ese paquete realizarn un acceso a memoria en lugar de a disco. Esto no sucede con procedimientos y funciones estndares. Permite la Sobrecarga de funciones (Overloading).

PL/SQL nos permite que varios procedimientos o funciones almacenadas, declaradas dentro de un mismo paquete, tengan el mismo nombre. Esto nos es muy til cuando necesitamos que los sub-programas puedan aceptar parmetros que contengan diferentes tipos de datos en diferentes instancias. En este caso Oracle ejecutar la versin de la funcin o procedimiento cuyo encabezado se corresponda con la lista de parmetros recibidos.

I.E.S. Francisco Ayala ( P.C. - Dpto. Informtica)

Tema 9. PL/SQL de ORACLE. Disparadores o TRIGGERS.

Pgina 24 de 32

Los disparadores (o triggers) son bloques de cdigo PL/SQL asociados a una tabla y que se ejecutan automticamente como reaccin a una operacin DML especfica (INSERT, UPDATE o DELETE) sobre dicha tabla. En definitiva, los disparadores son eventos a nivel de tabla que se ejecutan automticamente cuando se realizan ciertas operaciones sobre la tabla. Para crear un disparador utilizaremos la siguiente instruccin:
CREATE {OR REPLACE} TRIGGER nombre_disp [BEFORE|AFTER] [DELETE|INSERT|UPDATE {OF columnas}] [ OR [DELETE|INSERT|UPDATE {OF columnas}]...] ON tabla [FOR EACH ROW [WHEN condicion disparo]] [DECLARE] -- Declaracin de variables locales BEGIN -- Instrucciones de ejecucin [EXCEPTION] -- Instrucciones de excepcin END;

El uso de OR REPLACE permite sobrescribir un trigger existente. Si se omite, y el trigger existe, se producir, un error. En principio, dentro del cuerpo de programa del trigger podemos hacer uso de cualquier orden de consulta o manipulacin de la BD, y llamadas a funciones o procedimientos siempre que: No se utilicen comandos DDL No se acceda a las tablas que estn siendo modificadas con DELETE, INSERT o UPDATE en la misma sesin No se violen las reglas de integridad, es decir no se pueden modificar llaves primarias, ni actualizar llaves externas No se utilicen sentencias de control de transacciones (Commit, Rollback o Savepoint) No se llamen a procedimientos que trasgredan la restriccin anterior No se llame a procedimientos que utilicen sentencias de control de transacciones

Predicados condicionales.

Cuando se crea un trigger para ms de una operacin DML, se puede utilizar un predicado condicional en las sentencias que componen el trigger que indique que tipo de operacin o sentencia ha disparado el trigger. Estos predicados condicionales son los siguientes:
Inserting Deleting Updating Updating (columna)

Retorna true cuando el trigger ha sido disparado por un INSERT Retorna true cuando el trigger ha sido disparado por un DELETE Retorna true cuando el trigger ha sido disparado por un UPDATE Retorna true cuando el trigger ha sido disparado por un UPDATE y la columna ha sido modificada.

I.E.S. Francisco Ayala ( P.C. - Dpto. Informtica)

Tema 9. PL/SQL de ORACLE. CREATE TRIGGER audit_trigger BEFORE INSERT OR DELETE OR UPDATE ON classified_table FOR EACH ROW BEGIN IF INSERTING THEN INSERT INTO audit_table VALUES (USER || ' is inserting' || ' new key: ' || :new.key); ELSIF DELETING THEN INSERT INTO audit_table VALUES (USER || ' is deleting' || ' old key: ' || :old.key); ELSIF UPDATING('FORMULA') THEN INSERT INTO audit_table VALUES (USER || ' is updating' || ' old formula: ' || :old.formula || ' new formula: ' || :new.formula); ELSIF UPDATING THEN INSERT INTO audit_table VALUES (USER || ' is updating' || ' old key: ' || :old.key || ' new key: ' || :new.key); END IF; END;

Pgina 25 de 32

Tipos de triggers.

Los triggers pueden definirse para las operaciones INSERT, DELETE o Update, y pueden dispararse antes o despus de la operacin. Finalmente, el nivel de los disparadores puede ser la fila o registro o la orden. El modificador BEFORE o AFTER indica que el trigger se ejecutar antes o despus de ejecutarse la sentencia SQL definida por DELETE, INSERT o UPDATE. Si incluimos el modificador OF el trigger solo se ejecutar cuando la sentencia SQL afecte a los campos incluidos en la lista. El alcance de los disparadores puede ser la fila o de orden. El modificador FOR EACH ROW indica que el trigger se disparar cada vez que se realizan operaciones sobre cada fila de la tabla. Si se acompaa del modificador WHEN, se establece una restriccin; el trigger solo actuar, sobre las filas que satisfagan la restriccin. Tipos de disparadores.
Categoria Orden Temporalizacin Nivel Valores INSERT, DELETE, UPDATE BEFORE o AFTER Fila u Orden Comentarios

Define que tipo de operacin DML provoca la activacin del trigger Define si el disparador se activa antes o despus de que se ejecute la operacin DML Los disparadores con nivel de fila se activan una vez por cada fila afectada por la orden que provoc el disparo. Los Triggers con nivel de orden se activan slo una vez, antes o despus de la orden. Los disparadores con nivel de fila se identifican por la clusula FOR EACH ROW en la definicin del disparador.

I.E.S. Francisco Ayala ( P.C. - Dpto. Informtica)

Tema 9. PL/SQL de ORACLE. Orden de ejecucin de los triggers

Pgina 26 de 32

Una misma tabla puede tener varios triggers asociados. En tal caso es necesario conocer el orden en el que se van a ejecutar. Los disparadores se activan al ejecutarse la sentencia SQL. Si existe, se ejecuta el disparador de tipo BEFORE (disparador previo) con nivel de orden. 2. Para cada fila a la que afecte la orden: 2.1. Se ejecuta si existe, el disparador de tipo BEFORE con nivel de fila. 2.2. Se ejecuta la propia orden. 2.3. Se ejecuta si existe, el disparador de tipo AFTER (disparador posterior) con nivel de fila. 3. Se ejecuta, si existe, el disparador de tipo AFTER con nivel de orden.
1. Restricciones de los Triggers.

El cuerpo de un disparador es un bloque PL/SQL. Cualquier orden que sea legal en un bloque PL/SQL , es legal en el cuerpo de un disparador, con las siguientes restricciones: a. Un disparador no puede emitir ninguna orden de control de transacciones ( COMMIT, ROLLBACK o SAVEPOINT). El disparador se activa como parte de la ejecucin de la orden que provoc el disparo, y forma parte de la misma transaccin qu dicha orden. Cuando la orden que provoca la orden es confirmada o cancelada, se confirma o se cancela tambin el trabajo realizado por el disparador. b. Por las mismas razones, ningn procedure o funcin llamado por el disparador puede emitir rdenes de control de transacciones. c. El disparador no puede declarar variables de tipo LONG.
Utilizacin de :old y :new en los disparadores con nivel de fila.

Un disparador con nivel de fila se ejecuta una vez por cada fila procesada por la orden que provoca el disparo. Dentro del disparador, puede accederse a la fila que est siendo actualmente procesada utilizando, para ello, dos pseudo-registros, :old y :new. En principio tanto :old como :new son del tipo tabla_disparo%ROWTYPE;
Orden de disparo INSERT UPDATE DELETE :old :new

No definido; todos los campos toman el valor NULL. Valores originales de la fila, antes de la actualizacin. Valores originales, antes del borrado de la fila.

Valores que sern insertados cuando se complete la orden. Nuevos valores que sern escritos cuando se complete la orden. No definido; todos los campos toman el valor NULL.

I.E.S. Francisco Ayala ( P.C. - Dpto. Informtica)

Tema 9. PL/SQL de ORACLE.

Pgina 27 de 32

Ejemplo :
CREATE TRIGGER scott.emp_permit_changes BEFORE DELETE OR INSERT OR UPDATE ON scott.emp DECLARE dummy INTEGER; BEGIN /* If today is a Saturday or Sunday, then return an error.*/ IF (TO_CHAR(SYSDATE, 'DY') = 'SAT' OR TO_CHAR(SYSDATE, 'DY') = 'SUN') THEN raise_application_error( -20501, 'May not change employee table during the weekend'); END IF; /* Compare today's date with the dates of all company holidays. If today is a company holiday, then return an error.*/ SELECT COUNT(*) INTO dummy FROM company_holidays WHERE day = TRUNC(SYSDATE); IF dummy > 0 THEN raise_application_error( -20501, 'May not change employee table during a holiday'); END IF; /*If the current time is before 8:00AM or after 6:00PM, then return an error. */ IF (TO_CHAR(SYSDATE, 'HH24') < 8 OR TO_CHAR(SYSDATE, 'HH24') >= 18) THEN raise_application_error( -20502, 'May only change employee table during working hours'); END IF; END; La clusula WHEN.

La clusula WHEN slo es vlida para disparadores con nivel de fila. Si est presente, el cuerpo del disparador slo se ejecutar para las filas que cumplan la condicin especificada en la clusula.
CREATE TRIGGER tr1 BEFORE INSERT OR UPDATE OF salario ON scott.emp FOR EACH ROW WHEN (new.job <> 'PRESIDENT') BEGIN /* Cuerpo del disparador */ END;

Esto ltimo es equivalente a :


CREATE TRIGGER tr1 BEFORE INSERT OR UPDATE OF salario ON scott.emp FOR EACH ROW BEGIN IF :new.job <> 'PRESIDENT' THEN /* Cuerpo del disparador */ END IF; END;

Para hacer que un trigger ejecute un ROLLBACK de la transaccin que tiene activa y teniendo en cuenta que en las sentencias que componen el cuerpo de un trigger no puede haber este

I.E.S. Francisco Ayala ( P.C. - Dpto. Informtica)

Tema 9. PL/SQL de ORACLE.

Pgina 28 de 32

tipo de sentencias (rollback, commit,) hay que ejecutar error / excepcion mediante la sentencia raise_application_error cuya sintaxis es
RAISE_APPLICATION_ERROR(num_error,mensaje);

El num_error es un nmero entero cualquiera, aunque se aconseja que tenga 5 dgitos. Por ejemplo
raise_application_error( 20000, No se puede modificar el cliente.); Tabla mutando

Cuando se realiza un trigger sobre una tabla, dicha tabla se dice que est en proceso de mutacin, es decir, que se estn realizando cambios sobre ella y que por tanto dentro del trigger no se debe hacer ningn tipo de acceso a dicha tabla con operaciones DML (SELECT, INSERT, DELETE o UPDATE). Si queremos conocer los valores del registro de la tabla sobre la que se ha disparado el trigger, este ltimo debe estar declarado de forma FOR EACH ROW y acceder a sus valores mediante las pseudocolumnas :NEW y :OLD.
Campos Calculados

En algunos SGBDR se permite el uso de campos calculados. Son campos cuyo valor se calcula de forma automtica cuando cambia el valor de alguno de los campos o valores de los que depende. Por ejemplo, en SQL SERVER se hara de la siguiente forma:
CREATE TABLE FacturasL( nNumFac numeric(10) NOT NULL, nNumLin numeric(10) NOT NULL, cCodArt char(13) NOT NULL, nPvpArt numeric(14,4) DEFAULT 0, nUniArt numeric(14,4) DEFAULT 0, nDtoLin numeric(14,4) DEFAULT 0, nBaseImp AS nPvpArt * nUniArt, nAnnio AS YEAR(GetDate()), CONSTRAINT PK_FacturasL PRIMARY KEY (nNumFac, nNumLin) );

En el ejemplo anterior, los campos nBaseImp y nAnnio son calculados y su valor se calcula de forma automtica; as que no pueden ser ni insertados ni modificados. En Oracle no existen los campos calculados, as que, hemos de hacer uso de los triggers para simularlos. La forma de hacerlo es:
1. Creando una segunda tabla, con la misma PRIMARY KEY que la tabla sobre la

cual se van a realizar los clculos, ms los campos calculados


2. Crear los triggers necesarios para actualizar los campos calculados. -- EJEMPLO DE CAMPOS CALCULADOS EN UNA TABLA ORACLE CREATE TABLE FacturasL( nNumFac NUMBER(10) NOT NULL, nNumLin NUMBER(10) NOT NULL,

I.E.S. Francisco Ayala ( P.C. - Dpto. Informtica)

Tema 9. PL/SQL de ORACLE. cCodArt VARCHAR(13) NOT NULL, nPvpArt NUMBER(14,4) DEFAULT 0, nUniArt NUMBER(14,4) DEFAULT 0, nDtoLin NUMBER(14,4) DEFAULT 0, CONSTRAINT PK_FacturasL PRIMARY KEY (nNumFac, nNumLin) ); CREATE TABLE FacturasL_Calc( nNumFac NUMBER(10) NOT NULL, nNumLin NUMBER(10) NOT NULL, nBaseImp NUMBER(14,4) DEFAULT 0, nSubTotal NUMBER(14,4) DEFAULT 0, CONSTRAINT PK_FacturasL_Calc PRIMARY KEY (nNumFac, nNumLin) ); CREATE OR REPLACE TRIGGER tr_FacturasL_Ins_Upd AFTER INSERT OR DELETE OR UPDATE ON FacturasL FOR EACH ROW DECLARE PKE Exception; BEGIN

Pgina 29 de 32

-- No se puede cambiar la PK IF Updating('nNumFac') OR Updating('nNumLin') THEN RAISE PKE; -- Lanzar Excepcion END IF; IF Inserting THEN INSERT INTO FacturasL_Calc VALUES (:new.nNumFac,:new.nNumLin, :new.nPvpArt * :new.nUniArt, :new.nPvpArt * :new.nUniArt - (:new.nPvpArt * :new.nUniArt * :new.nDtoLin / 100) ); END IF; IF Deleting THEN DELETE FacturasL_Calc WHERE nNumFac = :old.nNumFac AND nNumLin = :old.nNumLin; END IF; IF Updating('nPvpArt') OR Updating('nUniArt') OR Updating('nDtoLin') THEN UPDATE FacturasL_Calc SET nBaseImp = :new.nPvpArt * :new.nUniArt, nSubTotal = :new.nPvpArt * :new.nUniArt - (:new.nPvpArt * :new.nUniArt * :new.nDtoLin / 100) WHERE nNumFac = :new.nNumFac AND nNumLin = :new.nNumLin; DBMS_OUTPUT.PUT_LINE('Cambio Realizado.'); END IF; EXCEPTION WHEN PKE THEN RAISE_APPLICATION_ERROR (-20001,'Error: No se puede modificar ni Nmero de Factura ni Lnea de Factura.'); WHEN OTHERS THEN RAISE_APPLICATION_ERROR (-20001,'Error: Actualizando campos calculados FacturasL_Calc.'); END ; -----------------------------------------

I.E.S. Francisco Ayala ( P.C. - Dpto. Informtica)

Tema 9. PL/SQL de ORACLE.

Pgina 30 de 32

SET SERVEROUTPUT ON; INSERT INTO FacturasL VALUES (1000,1,'HD-SEA01-1TB',60.5,3,10); INSERT INTO FacturasL VALUES (1000,2,'TFT LG 19',195,1,0); COMMIT; SELECT * FROM FacturasL; SELECT * FROM FacturasL_Calc; -- Hasta aqui para probar el INSERT

SET SERVEROUTPUT ON; UPDATE FacturasL SET cCodArt = 'HD-IBM01-3TB' WHERE nNumLin = 1; COMMIT; SELECT * FROM FacturasL; SELECT * FROM FacturasL_Calc; -- Hasta aqui para probar que el cambio de cCodArt no hace nada -- ni siquiera lanza la salida OUTPUT : Cambio Realizado SET SERVEROUTPUT ON; UPDATE FacturasL SET nPvpArt = 99 WHERE nNumLin = 1; COMMIT; SELECT * FROM FacturasL; SELECT * FROM FacturasL_Calc; -- Hasta aqui para probar que el cambio de nPvpArt lanza el Trigger -- Ademas lanza la salida OUTPUT : Cambio Realizado DELETE FacturasL WHERE nNumLin = 1; COMMIT; SELECT * FROM FacturasL; SELECT * FROM FacturasL_Calc; -- Hasta aqui para probar que el borrado de una linea lanza el Trigger

Para ms informacin sobre los disparadores consultar el Oracle SQL Reference

I.E.S. Francisco Ayala ( P.C. - Dpto. Informtica)

Tema 9. PL/SQL de ORACLE. Registros y tablas

Pgina 31 de 32

Existen dos tipos de datos que no hemos mencionado anteriormente: los registros (o estructuras) y las tablas (o arrays o vectores). Los dos tipos deben ser definidos como un nuevo tipo antes de declarar variables de ese nuevo tipo. El modo de definir nuevos tipos de variables en PL/SQL es a travs de la palabra reservada TYPE:
TYPE nuevo_tipo IS tipo_original.

Una vez definido en nuevo tipo, ya se pueden definir variables de ese nuevo tipo.
Registros:

Los registros no son ms que agrupaciones de tipos de variables que se acceden con el mismo nombre. La sintaxis de definicin de registros es:
TYPE nombre_registro IS RECORD( Campo1 tipo, Campo2 tipo, Campo3 tipo );

Por ejemplo:
TYPE alumno IS RECORD( n_alumno VARCHAR2(5), nombre VARCHAR2(25), tlf VARCHAR2(15) ); Tablas.

Una tabla no es ms que una coleccin de elementos identificados cada uno de ellos por un ndice. En muchos lenguajes se les denomina arrays o matrices. La sintaxis de definicin de tablas es:
TYPE nombre_tabla IS TABLE OF tipo_de_elementos;

El tamao de la tabla se define durante la declaracin de la variable.


Nombre_variable nombre_tabla := nombre_variable( lista de elementos );

Por ejemplo:
DECLARE TYPE array_enteros IS TABLE OF INTEGER; Un_array array_enteros := array_enteros( 0, 0, 0, 0 );

I.E.S. Francisco Ayala ( P.C. - Dpto. Informtica)

Tema 9. PL/SQL de ORACLE. Tunning bsico de SQL

Pgina 32 de 32

Una de las tareas ms importantes de las propias de un desarrollador de bases de datos es la de puesta a punto o tuning. Hay que tener en cuenta que las sentencias SQL pueden llegar a ser muy complejas y conforme el esquema de base de datos va creciendo las sentencias son ms complejas y confusas. Por es difcil escribir la sentencia correcta a la primera. Por todo ello despus de tener cada uno de los procesos escrito, hay que pasar por una etapa de tuning en la que se revisan todas las sentencias SQL para poder optimizarlas conforme a la experiencia adquirida. Tanto por cantidad como por complejidad, la mayora de las optimizaciones deben hacerse sobre sentencias SELECT, ya que son (por regla general) las responsables de la mayor prdida de tiempos. A continuacin se dan unas normas bsicas para escribir sentencias SELECT optimizadas. Las condiciones (tanto de filtro como de join) deben ir siempre en el orden en que est definido el ndice. Si no hubiese ndice por las columnas utilizadas, se puede estudiar la posibilidad de aadirlo, ya que tener ndices de ms slo penaliza los tiempos de insercin, actualizacin y borrado, pero no de consulta. Evitar la condiciones IN ( SELECT) sustituyndolas por joins. Colocar la tabla que devuelve menor nmero de registros en el ltimo lugar del FROM Una consulta cualificada con la clusula DISTINTC debe ser ordenada por el servidor aunque no se incluya la clusula ORDER BY.

I.E.S. Francisco Ayala ( P.C. - Dpto. Informtica)

También podría gustarte