CURSO DE PL-SQL

c cc  c  cccc cc c* Entidades * Relaciones * Cardinalidad * 

Views 116 Downloads 3 File size 521KB

Report DMCA / Copyright

DOWNLOAD FILE

Recommend stories

Citation preview

c cc

 c  cccc cc c* Entidades

*

Relaciones

*

Cardinalidad

*

 cc   c c  c * ¿Qué es PL/SQL? * Estructuras de Bloque * Variables y Constantes Cursores

*

*

Manejo de Errores

*

Subprogramas * Paquetes * Ventajas en la utilización de PL/SQL  c!c" cc# $c*

*

Set de Caracteres y Unidades Léxicas Delimitadores e Identificadores

*

*

Tipos de Datos y Conversiones * Alcance y Visibilidad

*

 c%c&& cc# $c * Control Condicional: Sentencia IF

*

Controles de Iteración: Las sentencias LOOP y EXIT

*

Controles de Secuencia: Las sentencias GOTO y NULL Sentencias SQL * Procesamiento de Transacciones *  c'c $cc&&c * Declaración de Cursores Apertura de un Cursor

*

*

Recuperación de Filas * Cierre de un Cursor

*

 c(c $cc&&&c* Excepciones predefinidas * Excepciones definidas por el usuario * Uso de SQLCODE y SQLERRM  c)c* &#&  c* Procedimientos

*

Funciones * Uso de Parámetros Recursividad * Polimorfismo

*

*

*

*

 c+c c * Ventajas de la utilización de Paquetes

*

Especificación de Paquetes * Cuerpo de un Paquete * ANEXOS 73

 cccc cc c Al diseñar un sistema de información o un proyecto de tecnología se debe tener en cuenta varios factores que intervienen en el desarrollo del mismo. El éxito del proyecto dependerá de la calidad con que se desarrollen todas las etapas que se identifiquen. Algunas consideraciones se relacionan con reconocer ciertos componentes que participan en el diseño de una solución tecnológica, donde se incluye el análisis, el diseño lógico y físico de la solución y posteriormente su implantación. En el ámbito de los sistemas de información, se reconoce que el estudio de los procesos de negocio deberá desembocar prontamente en el establecimiento de un modelo lógico de datos, que refleje de la mejor forma posible la complejidad que puede llegar a adquirir el sistema real.

Figura 1-1 Curva de estudio de casos

Cuando se estudia un proceso de negocio o una situación cualquiera, se presenta una importante diversidad de componentes o casos, unos muy frecuentes, otros menos y algunos eventuales. Cuando se trata de crear un sistema que refleje este proceso, surge la pregunta ¿cuáles son los componentes que voy a considerar en el diseño?. Cuanto mayor sea el número de componentes, casos o situaciones, considerados, mayor será la complejidad del diseño. Particularmente, si deben considerarse las situaciones excepcionales, el diseño será muy complejo y por ende caro. Ê 

REALIDAD MODELO Figura 1-2: Abstracción de la realidad para generar un modelo Abstracción es la actividad por la cual se recogen las características comunes más relevantes y esenciales de una &  , para generar unc, Este modelo deberá tener un  & , desde el punto de vista de quién lo usará, semejante a la realidad que representa. Por esta razón el modelo deberá poseer tantos atributos de la realidad, como corresponda a su operación interna y a su relación con otros modelos.   Entonces, cuando se modela una realidad, surge la necesidad de identificar aquellas i  i que conforman la situación en estudio y representarlas con objetos genéricos que tengan el nivel de abstracción adecuado que permitan reconocer las características del objeto que se está modelando. Estas entidades poseerán entonces características o atributos que las determinarán en forma detallada y que ayudarán incluso a relacionarlas con otras entidades del mismo modelo. Ejemplo:

Sea la entidad CLIENTE en una cadena de tiendas, que representa a las personas que compran los productos que son ofrecidos por la empresa. La notación más común para representar una entidad, en la génesis de un modelo de datos, es la siguiente:

Si la tienda ofrece determinados productos y la venta de éstos es registrada en un pedido, entonces las entidades PRODUCTO y PEDIDO también pertenecerán al modelo de datos lógico:

Ahora, cuando debemos detallar las características de estas entidades que son relevantes para el proceso de negocio que se está analizando, las escribimos en el recuadro inferior. En este ejemplo, las características relevantes de las entidades definidas podrían ser las siguientes:

V  i   En todas las entidades es preciso identificar aquel atributo que identifica unívocamente a cada ocurrencia dentro de ella. Es la que llamamos   i  o  . Si observamos nuestro modelo, es claro que los atributos principales de cada entidad deberían ser los siguientes: Cliente ¬ RUT Pedido ¬ No. de Pedido Producto ¬ Código del Producto Hasta aquí se han establecido ciertas entidades que, luego del análisis practicado a la situación en estudio, se han definido como las más representativas del modelo de negocio. También se han precisado las características más importantes de cada una de ellas, las cuales se conocen con el nombre de   en un modelo relacional.

  A continuación, cuando ya se encuentra definida cada entidad en forma individual, el siguiente paso es descubrir las relaciones que existen entre ellas, las cuales también se determinan por las i  i i que se está modelando. En el ejemplo, se entiende que los clientes son los que realizan los pedidos. Además, cada pedido puede involucrar uno o más artículos (productos) ofrecidos por la empresa. De esta manera, se desprende que las relaciones se producen entre las entidades, las cuales simbolizamos con una línea que las une. Ejemplo:

Al observar detenidamente estas líneas que unen a nuestras entidades podremos darnos cuenta que tienen formas muy diferentes. Esto no ha sido un capricho del editor de este manual, sino una nomenclatura muy conocida para representar las cardinalidades o número de veces en que las ocurrencias de una entidad participan sobre otra.

 &   Existen varias formas de anotar la cardinalidad de las relaciones que se identifican en un modelo. Todas ellas son dependientes de la posición, es decir, un mismo símbolo dibujado al revés significa una cosa totalmente diferente en el modelo. En este manual estudiaremos la notación siguiente: 1. Este símbolo representa que cada ocurrencia de la entidad de la izquierda participa cero o muchas veces en una relación con algún ítem de la entidad de la derecha ( ). Al mismo tiempo, indica que una ocurrencia de la entidad de la derecha siempre se relaciona con algún ítem en la entidad de la izquierda ( ). Por ejemplo, en la relación:

La cardinalidad indicada, al leerla de izquierda a derecha, asegura que "cada Cliente realiza 0 ó más pedidos a la tienda". Por otro lado, también aclara que "un pedido sólo se asocia con un solo Cliente" (al leer de derecha a izquierda). En una implementación física (un paso más adelante que este diseño) se podrá observar que algunos atributos o características de algunas entidades deben ser traspasadas a otras para mantener la integridad de los datos que se modelan en esta etapa. 2. Este símbolo es especial porque está representando una relación de muchos ítems de una entidad sobre muchos otros de la otra entidad. En palabras, aterrizando a nuestro pequeño modelo, se leería de la siguiente forma:

a.c "Un pedido debe contener por lo menos un producto y como máximo varios de ellos" ( ). b.c "Un mismo producto puede aparecer ninguna o muchas veces en un mismo pedido" ( ). La lectura es fácil, pero su implementación física requerirá de un paso adicional, que es romper esta relación de "muchos a muchos" y crear una nueva entidad que relacione de manera simple a cada una de las entidades "Producto" y "Pedido". Si se tuviera en cuenta este mismo punto al momento de efectuar el modelo lógico, podríamos haber propuesto un esquema como el siguiente:

En este nuevo modelo (o submodelo) se   la relación anterior y fabricamos dos nuevas relaciones más sencillas y que aportan tanta o más información que la anterior. Por ejemplo, ahora podemos conocer el número de la caja donde se efectuó la venta, que no era un atributo ni del pedido ni de los productos. Sin embargo, no era necesario buscar un atributo a la nueva entidad, puesto que ésta podría estar vacía si no existe un dato que la caracterice en forma adecuada dentro de nuestro modelo del negocio. Finalmente, según nuestra manera natural de ver las cosas, entendemos que las entidades y relaciones revisadas en las páginas anteriores, aclaran la participación de los objetos del negocio para ejemplificar los temas revisados hasta aquí. Sin embargo, debo demostrar ahora que esta misma lógica no puede ser entendida por un sistema computacional o un administrador de bases de datos, por muy poderoso que éste sea.

La razón es muy simple y se ejemplificará de la siguiente manera: Suponga las siguientes ocurrencias de las entidades anteriormente definidas: c &*

- & 

.





5.555.555-5

6.666.666-6

7.777.777-7

*&

Sergio

Marco Antonio

Luis Fernando

 

Contreras Ruiz

Fernández Ríos

Cárcamo Vera

&/

Los Copihues #48

Las Encinas #1000

Apoquindo #777

6666666

7777777

0" 1&c &*

- & 

.



/#

A100

B123

C430

*&

Microondas

Mesa de Televisor

Silla

2c 

15

10

10

2c 34

40

60

60

i Si el Cliente "A" efectúa un pedido de 3 sillas y un microondas. ¿Cómo debería representarlo la relación de "Pedido"? ii Antes de conocer la respuesta final, observemos cómo debería reflejarlo el modelo: Supongamos el pedido número 1000, efectuado el 15 de diciembre por un total de $115.000 (suponga que el microondas vale $70.000 y cada silla $15.000). 1c &*

- &

,c1

1000

56

15-Dic-2000

 

$115.000

Al revisar esta ocurrencia en la entidad de "Pedido" es obvio que no podemos relacionarla de ninguna manera con algún cliente. Sin embargo, al modelarlo estuvo correcto, pero era el   y la     de la relación quienes nos informaban de que los pedidos los efectuaban los clientes en tal o cual cantidad. Entonces, al implementar la solución debemos considerar también lo siguiente: "Cada vez que encontremos una relación de uno-a-uno, simbolizada por , como en el caso de los pedidos y los clientes en la figura siguiente, se entenderá que el atributo principal de la entidad que es afectada por esta cardinalidad deberá traspasarse a la otra entidad". Como en nuestro modelo este tipo de relación se da entre "Cliente" y "Pedido", entonces el modelo físico de esa relación se vería de la siguiente manera:

Y de esa manera, al pasar el atributo principal de "Cliente" (RUT) a la entidad "Pedido", se logra establecer claramente un nexo físico en la base de datos.  cc   c c  c 780cc1 89 PL/SQL provee una manera muy cómoda de relacionar los conceptos de bases de datos y manejarlos mediante ciertas estructuras de control, dentro del contexto de una herramienta netamente de programación. Su utilización es dentro del administrador de bases de datos "Oracle" y sus principales características son la posibilidad que brinda de utilizar sentencias SQL para manipular datos en Oracle y sentencias de control de flujo para organizar esta manipulación de datos. Dentro del lenguaje, es posible declarar constantes y variables, definir procedimientos y funciones y atrapar errores en tiempo de ejecución. Así visto, PL/SQL combina la el poder de la manipulación de datos, con SQL, y las facilidades del procesamiento de los mismos, tal como en los más modernos lenguajes de programación.

&& cc.  PL/SQL es un lenguaje i  i i, lo que quiere decir que la unidad básica de codificación son bloques lógicos, los que a su vez pueden contener otros subbloques dentro de ellos, con las mismas características. Un bloque (o sub-bloque) permite agrupar en forma lógica un grupo de sentencias. De esta manera se pueden efectuar declaraciones de variables que sólo tendrán validez en los bloques donde éstas se definan. Un bloque PL/SQL tiene tres partes: una sección de i , una sección de ii y otra de manejo de iii. Sólo el bloque de ejecución es obligatorio en un programa PL/SQL. Es posible anidar sub-bloques en la sección ejecutable y de excepciones, pero no en la sección de declaraciones.

Figura 2-1: Estructura de bloques de un programa PL/SQL

- & *c:c  PL/SQL permite declarar constantes y variables para ser utilizadas en cualquier expresión dentro de un programa. La única condición exigida por PL/SQL es que cada variable (o constante) debe estar declarada antes de ser utilizada en una expresión. Las variables pueden corresponder a cualquier tipo de dato de SQL, tal como , i o  i, o algún tipo de PL/SQL, como  i o ii. Por ejemplo, si desea declarar una variable llamada "part_no" que almacene cuatro dígitos numéricos y otra variable "in_stock" de tipo booleano, es decir, que almacene solamente los valores True o False, la declaración se vería como sigue: part_no number(4) ; in_stock boolean ; V    i   i

Es posible asignar valores a las variables de dos formas. La primera utiliza el operador ";". La variable se ubica al lado izquierdo y la expresión al lado derecho del símbolo. Por ejemplo: tax := price * tax_rate ; bonus := current_salary * 0.10 ; amount := TO_NUMBER(SUBSTR(µ750 dólares¶, 1, 3)) ; valid := False ; La segunda forma de asignar valores a variables es obtener valores directamente desde la base de datos, como en: SELECT sal * 0.10 INTO bonus FROM emp WHERE empno = emp_id ; pi  i Vi En la declaración de una constante (muy similar a la de una variable), se debe incorporar la palabra reservada "constant" e inmediatamente asignar el valor deseado. En adelante, no se permitirán reasignaciones de valores para aquella constante que ya ha sido definida. Ejemplo: i    VÊ i   

&& Los cursores son áreas de trabajo que permiten ejecutar sentencias SQL y procesar la información obtenida de ellos. Hay dos tipos de cursores: implícitos y explícitos. PL/SQL declara implícitamente un cursor para todas las sentencias de manipulación de datos, incluyendo las consultas que retornan sólo una fila. Para consultas que devuelven más de una fila, es posible declarar explícitamente un cursor que procese las filas en forma individual. Por ejemplo: DECLARE CURSOR curs_01 IS SELECT empno, ename, job FROM emp WHERE deptno=20; El conjunto de filas retornado se denomina "set de resultados". Su tamaño está determinado por el número de filas que calzan con el criterio de selección de la query que implementa el cursor. Las filas son procesadas de a una cada vez.

En el capítulo dedicado exclusivamente a estos componentes del lenguaje, se detallarán las características de las diferentes modalidades de utilización de los cursores.

Figura 2-2: Recuperación de filas a través de un cursor

$cc&&& PL/SQL provee una fácil manera de detectar y procesar ciertas condiciones de error predefinidas (o definidas por el usuario), llamadas iii. Cuando ocurre un error se procesa una excepción, esto es, se detiene la ejecución normal del programa y se transfiere el control a un segmento especial del programa que tiene por objeto manejar estas situaciones excepcionales. Estas rutinas que se codifican en forma separada se conocen con el nombre de ii  i. Las excepciones predefinidas son gatilladas automáticamente por el sistema cuando ocurre un error de cierta naturaleza. Además, es posible alcanzar excepciones definidas con el usuario, simplemente haciendo un llamado a éstas utilizando la sentencia i.

* &#&   En PL/SQL existen dos tipos de subprogramas, llamados procedimientos y funciones, los que pueden manejar parámetros de entrada y de salida. Un subprograma es un programa en miniatura, que comienza con un encabezado, una sección opcional de declaraciones, una sección de ejecución y una sección opcional de manejo de excepciones, como cualquier otro programa de PL/SQL.

1  Es posible almacenar lógicamente un conjunto de tipos de datos relacionados, variables, cursores e incluso subprogramas dentro de un ii. Cada paquete involucra la definición y tratamiento de todos los elementos recién mencionados. Los paquetes se descomponen en dos partes: una  " / y un & .

La ii (package specification) es idéntica a una sección de declaración de aplicaciones. En esta especie de encabezado es posible declarar tipos, constantes, variables, excepciones, cursores y subprogramas disponibles para su uso en el i del paquete. De esta manera, el cuerpo (package body) define la implementación de esos subprogramas declarados en el apartado anterior. Ejemplo de uso de paquetes: CREATE PACKAGE emp_actions as -- package specification PROCEDURE hire_employee (empno NUMBER, ename CHAR, «) ; PROCEDURE fire_employee (empid NUMBER) ; END emp_actions ; CREATE PACKAGE BODY emp_actions AS -- package body PROCEDURE hire_employee (empno NUMBER, ename CHAR, «) IS BEGIN INSERT INTO emp VALUES (empno, ename, «); END hire_employee; PROCEDURE fire_employee (emp_id NUMBER) IS BEGIN DELETE FROM emp WHERE empno = emp_id; END fire_employee; END emp_actions; Los paquetes pueden ser compilados y almacenados en una base de datos Oracle y su contenido puede ser compartido por varias aplicaciones. Cuando un paquete es llamado para su ejecución, éste se almacena completamente en memoria la primera vez. Las siguientes llamadas no requieren efectuar este procedimiento cada vez y por esto aumentan la eficiencia de los programas. - $ cc c< /cc1 8 PL/SQL es un lenguaje de procesamiento de transacciones completamente portable y con un alto rendimiento, que proporciona las siguientes ventajas al ser utilizado: Soporte para SQL Soporte para la programación orientada a objetos

Mejor rendimiento Alta productividad Completa portabilidad Integración con Oracle garantizada Seguridad i   SQL se ha convertido en el lenguaje estándar de bases de datos por su flexibilidad de uso y facilidad de aprenderlo. Unos pocos comandos permiten la fácil manipulación de prácticamente toda la información almacenada en una base de datos. SQL es no-procedural, lo cual significa que es Oracle quien se preocupará de cómo ejecutar de la mejor manera un requerimiento señalado en una sentencia SQL. No es necesaria la conexión entre varias sentencias porque Oracle las ejecuta de a una a la vez. PL/SQL le permite a usted una completa manipulación de los datos almacenados en una base Oracle, proporciona comandos de control de transacciones y permite utilizar las funciones de SQL, operadores y pseudocolumnas. Así, usted puede manipular los datos en Oracle de una manera flexible y segura. Además, PL/SQL soporta tipos de datos de SQL, lo que reduce la necesidad de convertir los datos al pasar de una a otra aplicación. PL/SQL también soporta SQL dinámico, una avanzada técnica de programación que convierte a sus aplicaciones en más flexibles y versátiles. i    i    i Los objetos se han convertido en una herramienta ideal para modelar situaciones de la vida real. Con su utilización es posible reducir el costo y tiempo de construcción de aplicaciones complejas. Otra ventaja es que utilizando una metodología de este tipo es posible mantener diferentes equipos de programadores construyendo aplicaciones basadas en el mismo grupo de objetos. Permitir el encapsulamiento del código en bloques es el primer paso para la implementación de métodos asociados a diferentes tipos de objetos construidos también con PL/SQL. i i  i Sin PL/SQL, Oracle tendría que procesar las instrucciones una a una. Cada llamada produciría un overhead considerable, sobre todo si consideramos que estas consultas viajan a través de la red. Por el contrario, con PL/SQL, un bloque completo de sentencias puede ser enviado cada vez a Oracle, lo que reduce drásticamente la intensidad de comunicación con la base de datos. Los procedimientos almacenados escritos con PL/SQL son compilados una vez y

almacenados en formato ejecutable, lo que produce que las llamadas sean más rápidas y eficientes. Además, ya que los procedimientos almacenados se ejecutan en el propio servidor, el tráfico por la red se reduce a la simple llamada y el envío de los parámetros necesarios para su ejecución. El código ejecutable se almacena en caché y se comparte a todos los usuarios, redundando en mínimos requerimientos de memoria y disminuyendo el overhead al mínimo. Ê      Si se decide utilizar otros productos de Oracle como  i   y  i i, es posible integrar bloques completos de PL/SQL en un trigger de Oracle Forms, debido a que PL/SQL es el mismo en todos los ambientes. V  i     Las aplicaciones escritas con PL/SQL son portables a cualquier sistema operativo y plataforma en la cual se encuentre corriendo Oracle. En otras palabras, PL/SQL corre dondequiera que se encuentre corriendo Oracle también. Esto significa que se pueden codificar librerías que podrán ser reutilizadas en otros ambientes. i   i PL/SQL y los lenguajes SQL en general se encuentran perfectamente integrados. PL/SQL soporta todos los tipos de datos de SQL. Los atributos %TYPE y %ROWTYPE integran PL/SQL con SQL, permitiendo la declaración de variables basado en tipos de columnas de tablas de la base de datos. Lo anterior provee independencia de los datos, reduce costos de mantención y permite a los programas adaptarse a los cambios en la base de datos para cumplir con las nuevas necesidades del negocio. i  Los procedimientos almacenados construidos con PL/SQL habilitan la división de la lógica del cliente con la del servidor. De esta manera, se previene que se efectúe manipulación de los datos desde el cliente. Además, se puede restringir el acceso a los datos de Oracle, permitiendo a los usuarios la ejecución de los procedimientos almacenados para los cuales tengan privilegios solamente.

 c!c" cc# $c Este capítulo se centra en pequeños aspectos del lenguaje, tal como el grupo de caracteres válidos, las palabras reservadas, signos de puntuación y otras reglas de formación de sentencias que es preciso conocer antes de empezar a trabajar con el resto de funcionalidades.

cc & &c:c c04  Las instrucciones del lenguaje deben ser escritas utilizando un grupo de caracteres válidos. PL/SQL no es sensible a mayúsculas o minúsculas. El grupo de caracteres incluye los siguientes: Äc Äc Äc Äc

Letras mayúsculas y minúsculas de la A a la Z Números del 0 al 9 Los símbolos ( ) + - * / < > = ! ~ ^ ; . µ @ % , " # $ & _ | { } ? [ ] Tabuladores, espacios y saltos de carro

Una línea de texto en un programa contiene lo que se conoce como unidades léxicas, los que se clasifican como sigue: Äc Äc Äc Äc

Delimitadores (símbolos simples y compuestos) Identificadores (incluye palabras reservadas) Literales Comentarios

Por ejemplo en la instrucción: bonus := salary * 0.10; -- cálculo del bono se observan las siguientes unidades léxicas: Äc Äc Äc Äc Äc

Los identificadores  y   El símbolo compuesto ; Los símbolos simples O y El literal numérico ! El comentario ""   i "

Para asegurar la fácil comprensión del código se pueden añadir espacios entre identificadores o símbolos. También es una buena práctica utilizar saltos de línea e indentaciones para permitir una mejor legibilidad. Ejemplo: IF x>y THEN max := x; ELSE max := y; END IF; Puede reescribirse de la siguiente manera para mejorar el aspecto y legibilidad: IF x > y THEN max := x; ELSE max := y; END IF;

 &cc " & Un delimitador es un símbolo simple o compuesto que tiene un significado especial dentro de PL/SQL. Por ejemplo, es posible utilizar delimitadores para representar operaciones aritméticas, por ejemplo: *

#" 

=

operador de suma

>

indicador de atributo

?

delimitador de caracteres

,

selector de componente



operador de división

@

expresión o delimitador de lista

A

expresión o delimitador de lista



indicador de variable host

B

separador de ítems

O

operador de multiplicación



delimitador de un identificador entre comillas

;

operador relacional

C

operador relacional

D

operador relacional

E

indicador de acceso remoto terminador de sentencias



negación u operador de substracción

Los delimitadores compuestos consisten de dos caracteres, como por ejemplo: *

#" 

;

operador de asignación

;D

operador de asociación

FF

operador de concatenación

OO

operador de exponenciación

CC

comienzo de un rótulo

DD

fin de un rótulo

O

comienzo de un comentario de varias líneas

O

fin de un comentario de varias líneas

,,

operador de rango

CD

operador relacional

G;

operador relacional

H;

operador relacional

C;

operador relacional

D;

operador relacional



comentario en una línea

Los identificadores incluyen constantes, variables, excepciones, cursores, subprogramas y paquetes. Un identificador se forma de una letra, seguida opcionalmente de otras letras, números, signo de moneda, underscore y otros signos numéricos. La longitud de un identificador no puede exceder los 30 caracteres. Se recomienda que los nombres de los identificadores utilizados sean descriptivos. Algunos identificadores especiales, llamados    ii  , tienen un especial significado sintáctico en PL/SQL y no pueden ser redefinidos. Son palabras reservadas, por ejemplo, BEGIN, END, ROLLBACK, etc.

 cc c:cI& Cada constante y variable posee un tipo de dato el cual especifica su forma de almacenamiento, restricciones y rango de valores válidos. Con PL/SQL se proveen diferentes tipos de datos predefinidos. Un tipo i  no tiene componentes internas; un tipo  i tiene otras componentes internas que pueden ser manipuladas individualmente. Un tipo de iii almacena valores, llamados i, que designan a otros elementos de programa. Un tipo  (large object) especifica la ubicación de un tipo especial de datos que se almacenan de manera diferente. En la figura 3-1 se muestran los diferentes tipos de datos predefinidos y disponibles para ser utilizados.

Figura 3-1: Tipos de datos de PL/SQL V ii Algunas veces se hace necesario convertir un valor desde un tipo de dato a otro. En PL/SQL se aceptan las conversiones de datos    y i . Una conversión explícita es aquella que se efectúa utilizando las funciones predefinidas. Por ejemplo, para convertir un valor de carácter a fecha o número se utiliza TO_DATE o TO_NUMBER. Existe una cantidad limitada de funciones de conversión, que implementan esta característica de conversión explícita. Cuando se hace necesario, PL/SQL puede convertir un tipo de dato a otro en forma implícita. Esto significa que la interpretación que se dará a algún dato será el que mejor se adecue dependiendo del contexto en que se encuentre. Tampoco significa que todas las conversiones son permitidas. Algunos ejemplos de conversión implícita más comunes se dan cuando variables de tipo  se operan matemáticamente para obtener un resultado numérico. Si PL/SQL no puede decidir a qué tipos de dato de destino puede convertir una variable se generará un error de compilación.  * ccI&c  c J  BIN_INT CHAR DATE LONG NUMBER

PLS_INT RAW

ROWID VARCHAR2

 . K  J

X X

X



X

 L

X

X

X

X

X

X

X

X

X

1 K 

X

X

X

M

X

X

 M 

X X

X

X X

X

X

X

X

X

 .

-J

X

X

X

X

X

X X X

X

X

X

X

X

X

| i # $ El atributo %TYPE define el tipo de una variable utilizando una definición previa de otra variable o columna de la base de datos. Ejemplo: DECLARE credito REAL(7,2); debito credito%TYPE; « También se podría declarar una variable siguiendo el tipo de un campo de alguna tabla, como por ejemplo en: debito cuenta.debe%TYPE; La ventaja de esta última forma es que no es necesario conocer el tipo de dato del campo "debe" de la tabla "emp", manteniendo la independencia necesaria para proveer más flexibilidad y rapidez en la construcción de los programas. | i #  $ El atributo %ROWTYPE precisa el tipo de un registro (i ) utilizando una definición previa de una tabla o vista de la base de datos. También se puede asociar a una variable como del tipo de la estructura retornada por un cursor.

Ejemplo: DECLARE emp_rec emp%ROWTYPE; CURSOR c1 IS SELECT deptno, dname, loc FROM dept; dept_rec c1%ROWTYPE; En este ejemplo la variable i i tomará el formato de un registro completo de la tabla i  y la variable ii se define por una estructura similar a la retornada por el cursor !.

 c:c-*  Las referencias a un identificador son resueltas de acuerdo a su alcance y visibilidad dentro de un programa. El  i de un identificador es aquella región de la unidad de programa (bloque, subprograma o paquete) desde la cual se puede referenciar al identificador. Un identificador es visible sólo en las regiones en que se puede referenciar. La figura 3-2 muestra el alcance y visibilidad de la variable 4, la cual está declarada en dos bloques cerrados diferentes. Los identificadores declarados en un bloque de PL/SQL se consideran locales al bloque y globales a todos sus sub-bloques o bloques anidados. De esto se desprende que un mismo identificador no se puede declarar dos veces en un mismo bloque pero sí en varios bloques diferentes, cuantas veces se desee.

Figura 3-2: Alcance y Visibilidad de Identificadores

Este ejemplo ilustra el alcance y visibilidad (o posibilidad de ser referenciada) de una determinada variable 4, que ha sido declarada en dos bloques anidados. La variable más externa tiene un alcance más amplio pero cuando es referenciada en el bloque en que se ha declarado otra variable con el mismo nombre, es esta última la que puede ser manipulada y no la primera.

 c%c&& cc# $c Este capítulo muestra como estructurar el flujo de control dentro de un programa PL/SQL. Se podrá entender como las distintas sentencias se encuentran conectadas mediante un poderoso y simple control de estructuras que constan de un punto de entrada y uno de salida. En su conjunto estas estructuras pueden manejar cualquier situación y permiten una correcta estructuración del programa. De acuerdo con el ii  i  $, cualquier programa computacional puede ser escrito utilizando las estructuras básicas de control que se muestran en la figura 4-1. Estas se pueden combinar de todas las maneras necesarias para alcanzar la solución de un problema dado. Las estructuras de selección verifican cierta condición, después ejecutan cierta secuencia de expresiones dependiendo si la condición resultó ser verdadera o falsa. Una   es cualquier variable o expresión que retorna un valor booleano (TRUE o FALSE).

Las estructuras de iteración ejecutan una secuencia de sentencias repetidamente mientras la condición permanezca verdadera. Las estructuras de secuencia simplemente ejecutan una secuencia de estamentos en el orden que ocurren.

Figura 4-1: Estructuras de Control &c c  c 5 A menudo es necesario tomar alternativas de acción dependiendo de las circunstancias. La sentencia IF permite ejecutar una secuencia de acciones condicionalmente. Esto es, si la secuencia es ejecutada o no depende del valor de la condición a evaluar. Existen tres modos para esta instrucción: IF ± THEN, IF ± THEN ± ELSE y IF ± THEN ± ELSIF. IF ± THEN Este es el modo más simple y consiste en asociar una condición con una secuencia de sentencias encerradas entre las palabras reservadas THEN y END IF (no ENDIF). Ejemplo: IF condición THEN secuencia_de_sentencias END IF; La secuencia de sentencias es ejecutada sólo si la condición es verdadera. Si la condición es falsa o nula no realiza nada. Un ejemplo real de su utilización es la siguiente: IF condición THEN calcular_bonus (emp_id) UPDATE sueldos SET pago = pago + bonus WHERE emp_no = emp_id; END IF;

IF ± THEN ± ELSE Esta segunda modalidad de la sentencia IF adiciona una nueva palabra clave: ELSE, seguida por una secuencia alternativa de acciones: IF condición THEN secuencia_de_sentencias_1 ELSE secuencia_de_sentencias_2 END IF; La secuencia de sentencias en la cláusula ELSE es ejecutada solamente si la condición es falsa o nula. Esto implica que la presencia de la cláusula ELSE asegura la ejecución de alguna de las dos secuencias de estamentos. En el ejemplo siguiente el primer UPDATE es ejecutado cuando la condición es verdadera, en el caso que sea falsa o nula se ejecutará el segundo UPDATE: IF tipo_trans = µCR¶ THEN UPDATE cuentas SET balance = balance + credito WHERE « ELSE UPDATE cuentas SET balance = balance ± debito WHERE « END IF; Las cláusulas THEN y ELSE pueden incluir estamentos IF, tal como lo indica el siguiente ejemplo: IF tipo_trans = µCR¶ THEN UPDATE cuentas SET balance = balance + credito WHERE « ELSE IF nuevo_balance >= minimo_balance THEN UPDATE cuentas SET balance = balance ± debito WHERE « ELSE RAISE fondos_insuficientes; END IF;

END IF; IF ± THEN ± ELSIF Algunas veces se requiere seleccionar una acción de una serie de alternativas mutuamente exclusivas. El tercer modo de la sentencia IF utiliza la clave ELSIF (no ELSEIF) para introducir condiciones adicionales, como se observa en el ejemplo siguiente: IF condición_1 THEN secuencia_de_sentencias_1 ELSIF condición_2 THEN secuencia_de_sentencias_2 ELSE secuencia_de_sentencias_3 END IF; Si la primera condición es falsa o nula, la cláusula ELSIF verifica una nueva condición. Cada sentencia IF puede poseer un número indeterminado de cláusulas ELSIF; la palabra clave ELSE que se encuentra al final es opcional. Las condiciones son evaluadas una a una desde arriba hacia abajo. Si alguna es verdadera, la secuencia de sentencias que corresponda será ejecutada. Si cada una de las condiciones analizadas resultan ser falsas, la secuencia correspondiente al ELSE será ejecutada: BEGIN « IF sueldo > 50000 THEN bonus : = 1500; ELSIF sueldo > 35000 THEN bonus : = 500; ELSE bonus : = 100; END IF;

INSERT INTO sueldos VALUES (emp_id, bonus, ); END; Si el valor de sueldo es mayor que 50.000, la primera y segunda condición son verdaderas, sin embargo a  se le asigna 1500, ya que la segunda condición jamás es verificada. En este caso sólo se verifica la primera condición para luego pasar el control a la sentencia INSERT.

&cc & /c c c

1c:cN c La sentencia LOOP permite ejecutar una secuencia de acciones múltiples veces. Todas ellas gobernadas por una condición que regula la ejecución de la iteración. Existen tres modalidades para esta instrucción: LOOP, WHILE ± LOOP y FOR ± LOOP. LOOP El modo básico (o infinito) de LOOP encierra una serie de acciones entre las palabras clave LOOP y END LOOP, como en el siguiente ejemplo: LOOP secuencia_de_instrucciones END LOOP; Con cada iteración del ciclo las sentencias son ejecutadas. Para terminar estos ciclos de ejecución se utiliza la palabra clave EXIT. Es posible ubicar innumerables EXIT dentro del loop, obviamente ninguno fuera de él. Existen dos modalidades para utilizar esta sentencia: EXIT y EXIT ± WHEN. EXIT La cláusula EXIT obliga al loop a concluir incondicionalmente. Cuando se encuentra un EXIT en el código, el loop es completado inmediatamente y pasa el control a la próxima sentencia. LOOP IF ranking_credito < 3 THEN « EXIT; --Termina el loop inmediatamente END IF;

END LOOP; Es necesario recordar que esta sentencia debe estar dentro del loop. Para completar un bloque PL/SQL antes de que su final natural sea alcanzado, es posible utilizar la instrucción RETURN. EXIT ± WHEN Esta sentencia permite terminar el loop de manera condicional. Cuando se encuentra un EXIT la condición de la cláusula WHEN es evaluada. Si la condición es verdadera el loop es terminado y el control es pasado a la próxima sentencia. Ejemplo: LOOP FECTH c1 INTO « EXIT WHEN c1%NOTFOUND; -- termina el loop si la condición es verdadera « END LOOP; CLOSE c1; Hasta que la condición no sea verdadera el loop no puede completarse, esto implica que necesariamente dentro de las sentencias el valor de la condición debe ir variando. En el ejemplo anterior si la ejecución de FETCH retorna una fila la condición es falsa. Cuando FETCH falla al retornar una fila, la condición es verdadera por lo que el loop es completado y el control es pasado a la sentencia CLOSE. La sentencia EXIT ± WHEN reemplaza la utilización de un IF. A modo de ejemplo se pueden comparar los siguientes códigos: IF count > 100 THEN | EXIT WHEN count > 100; EXIT; | END IF; | Ambos códigos son equivalentes, pero el EXIT ± WHEN es más fácil de leer y de entender. $i En todos los bloques escritos en PL/SQL, los ciclos pueden ser rotulados. Un rótulo es un identificador encerrado entre los signos dobles CC y DD y debe aparecer al comienzo de un loop, como se muestra a continuación:

LOOP secuencia de sentencias END LOOP; La última sentencia puede cambiarse también por $p   ; WHILE - LOOP Esta sentencia se asocia a una condición con una secuencia de sentencias encerradas por las palabras clave LOOP y END LOOP, como sigue: WHILE condición LOOP secuencia_de_sentencias END LOOP; Antes de cada iteración del ciclo se evalúa la condición. Si ésta es verdadera se ejecuta la secuencia de sentencias y el control se devuelve al inicio del loop. Si la condición en falsa o nula, el ciclo se rompe y el control se transfiere a la próxima instrucción, fuera del loop. FOR - LOOP En las instrucciones anteriores el número de iteraciones es desconocido, mientras no se evalúa la condición del ciclo. Con una instrucción del tipo FOR-LOOP, la iteración se efectúa un número finito (y conocido) de veces. La sintaxis de esta instrucción es la siguiente: FOR   IN [REVERSE]    ..     LOOP secuencia_de_sentencias END LOOP; El contador no necesita ser declarado porque por defecto se crea para el bloque que involucra el ciclo y luego se destruye. Por defecto, la iteración ocurre en forma creciente, es decir, desde el menor valor aportado hasta el mayor. Sin embargo, si se desea alterar esta condición por defecto, se debe incluir explícitamente en la sentencia la palabra REVERSE. Los límites de una iteración pueden ser literales, variables o expresiones, pero que deben evaluarse como números enteros.

Un contador de loop tiene validez sólo dentro del ciclo. No es posible asignar un valor a una variable contadora de un loop, fuera de él. Ejemplo: FOR cont IN 1..10 LOOP « END LOOP; sum := cont + 1 ; -- Esto no está permitido La sentencia EXIT también puede ser utilizada para abortar la ejecución del loop en forma prematura. Por ejemplo, en el siguiente trozo de programa la secuencia normal debería completarse luego de 10 veces de ejecutarse, pero la aparición de la cláusula EXIT podría hacer que ésta termine antes: FOR j IN 1..10 LOOP FETCH c1 INTO emprec; EXIT WHEN c1%NOTFOUND; « END LOOP; O también se puede utilizar:

FOR i IN 1..5 LOOP « FOR j IN 1..10 LOOP FETCH c1 INTO emprec; EXIT externo WHEN c1%NOTFOUND; -- sale de ambos ciclos « END LOOP; END LOOP externo; -- el control retorna a esta línea

&cc  c c cL  c:cc Ocasionalmente podría ser útil la utilización de una sentencia de este tipo. A pesar de que es sabido que la sentencia GOTO redunda en un código más complejo y desordenado a veces podría cooperar en la implementación de un programa. La sentencia nula puede cooperar con la fácil lectura del código cuando este sobrepasa una cantidad determinada de instrucciones y torna más difícil su comprensión. GOTO La sentencia GOTO obliga a saltar a un rótulo del programa en forma incondicional. El rótulo debe ser único dentro de su alcance y debe preceder a una sentencia ejecutable o a un bloque PL/SQL. Cuando es ejecutada, esta instrucción transfiere el control a la sentencia o bloque rotulada. Los siguientes ejemplos ilustran una forma válida de utilizar la sentencia GOTO y otra no válida. Ejemplo válido: BEGIN «

BEGIN UPDATE emp SET« « END; « GOTO ,>=,