Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                

Construyendo Con Bloques en PL

Descargar como pdf o txt
Descargar como pdf o txt
Está en la página 1de 12

Construyendo con Bloques en PL/SQL

Por Steven Feuerstein


Traducido por Alfonso Vicente
Publicado en marzo 2012
Publicado en

Marzo/Abril 2011

Parte 1 en una serie de artículos sobre la comprensión y uso de PL/SQL


El lenguaje PL/SQL de Oracle celebró su cumpleaños número 22 en 2011. Lo sé porque estoy mirando la
primera guía del usuario de Oracle PL/SQL que se haya publicado, es de la versión 1.0 de PL/SQL, y su fecha
de publicación es Setiembre de 1989. Estaba trabajando para Oracle en ese momento, construyendo las
primeras herramientas de automatización utilizadas por la fuerza de ventas de Oracle EE.UU. Ya había
trabajado con PL/SQL dentro de SQL Forms 3.0, pero fue con el lanzamiento de la base de datos Oracle 6,
que PL/SQL estuvo disponible como un lenguaje independiente para desarrollo de aplicaciones.

Tres años más tarde, escribí mi primer libro sobre PL/SQL y desde entonces he estudiado este lenguaje, he
desarrollado montones y montones de código PL/SQL, y he escrito sobre este excelente lenguaje de
programación de base de datos. Por supuesto, yo no era el único. Miles de desarrolladores en todo el mundo
han construido una multitud de aplicaciones basadas en Oracle PL/SQL en las décadas desde que se liberó.

Lo mejor de todo es que sigue habiendo un flujo constante de nuevos desarrolladores PL/SQL. De hecho, con
la aparición relativamente reciente de la India, China y otras naciones como potencias de tecnología, he visto
a toda una nueva generación de desarrolladores descubrir PL/SQL y trabajar para dominarlo.

Para ayudar a que los recién llegados a PL/SQL saquen el máximo provecho de este lenguaje, Oracle
Magazine me ha pedido que escriba una serie de artículos para principiantes, de los cuales éste es el primero.
Si usted es un desarrollador experimentado en PL/SQL, también puede encontrar en estos artículos un repaso
práctico sobre sus fundamentos.

Para esta serie de artículos, voy a suponer que a pesar de ser nuevos en PL/SQL, mis lectores han tenido
alguna experiencia en programación y están familiarizados con SQL. Mi enfoque general, además, estará en
conseguir desarrolladores productivos en PL/SQL lo más rápido posible.

¿Qué es PL/SQL?
Para contestar esta pregunta, es importante recordar que en cada sitio Web que visitamos, cada aplicación
que se ejecuta es construida sobre un stack (una pila) de tecnologías de software. En la parte superior de la
pila está la capa de presentación, las pantallas o dispositivos interactivos con los que el usuario interactúa
directamente (hoy en día los lenguajes más populares para las capas de presentación son Java y .NET). En la
parte inferior de la pila está el lenguaje de máquina que se comunica con el hardware.
En algún lugar en medio de la pila de tecnología se encuentra la base de datos, el software que nos permite
almacenar y manipular grandes volúmenes de datos complejos. La tecnología de bases de datos relacionales,
construida en torno a SQL, es la tecnología de base de datos dominante en el mundo de hoy.

SQL es un lenguaje de conjuntos muy poderoso, cuyo único objetivo es manipular el contenido de bases de
datos relacionales. Si usted desarrolla aplicaciones basadas en bases de datos Oracle, usted (o el código de
alguien que escribe en un nivel inferior de la pila de la tecnología) debe ejecutar sentencias SQL para
recuperar datos desde o cambiar datos en la base de datos. Sin embargo, SQL no se puede utilizar para
implementar toda la lógica de negocios y la funcionalidad que el usuario final necesita en nuestras
aplicaciones. Esto nos lleva a PL/SQL.

PL/SQL significa Procedural Language/Structured Query Language (una extensión de programación


estructurada sobre SQL). PL/SQL ofrece un conjunto de instrucciones clásicos de la programación
estructurada (instrucción condicional IF, loops o iteraciones, asignaciones), organizado dentro de bloques (lo
que se explica más adelante), que complementan y amplían el alcance de SQL.
Sin duda que es posible crear aplicaciones sobre Oracle y SQL sin usar PL/SQL. Sin embargo, utilizar PL/SQL
para realizar operaciones específicas de bases de datos, particularmente la ejecución de sentencias SQL,
ofrece varias ventajas, incluyendo una estrecha integración con SQL, un mejor rendimiento a través del tráfico
de red reducido, y la portabilidad (los programas PL/SQL pueden correr en cualquier instancia de base de
datos Oracle). Por lo tanto, el código del front-end de muchas aplicaciones ejecuta tanto sentencias SQL
como bloques PL/SQL, para maximizar el rendimiento al tiempo que mejora la capacidad de mantenimiento de
las aplicaciones.

Construyendo bloques de programas PL/SQL


PL/SQL es un lenguaje estructurado con bloques. Un bloque PL/SQL es definido por las palabras clave
DECLARE, BEGIN, EXCEPTION, y END, que dividen el bloque en tres secciones

1. Declarativa: sentencias que declaran variables, constantes y otros elementos de código, que después
pueden ser usados dentro del bloque
2. Ejecutable: sentencias que se ejecutan cuando se ejecuta el bloque
3. Manejo de excepciones: una sección especialmente estructurada para atrapar y manejar cualquier
excepción que se produzca durante la ejecución de la sección ejecutable
Sólo la sección ejecutable es obligatoria. No es necesario que usted declare nada en un bloque, ni que
maneje las excepciones que se puedan lanzar.

Un bloque es en sí mismo una sentencia ejecutable, por lo que se pueden anidar los bloques unos dentro de
otros.

Aquí hay algunos ejemplos:

El clásico “¡Hola Mundo!” es un bloque con una sección ejecutable que llama al procedimiento
DBMS_OUTPUT.PUT_LINE para mostrar texto en pantalla:
BEGIN
DBMS_OUTPUT.put_line('¡Hola Mundo!');
END;

Las funciones y procedimientos —tipos de bloques con un nombre— son discutidos con mayor detalle más
adelante en este artículo, así como los paquetes. En pocas palabras, sin embargo, un paquete es un
contenedor de múltiples funciones y procedimientos. Oracle extiende PL/SQL con muchos paquetes
incorporados en el lenguaje.

El siguiente bloque declara una variable de tipo VARCHAR2 (un string) con un largo máximo de 100 bytes
para contener el string ‘¡Hola Mundo!’. Después, el procedimiento DBMS_OUTPUT.PUT_LINE acepta la
variable, en lugar del literal, para desplegarlo:

DECLARE
l_mensaje VARCHAR2(100) := '¡Hola Mundo!';
BEGIN
DBMS_OUTPUT.put_line(l_mensaje);
END;

Note que he llamado a la variable l_mensaje. Normalmente uso el prefijo l_ para variables locales —variables
definidas dentro del código de un bloque— y el prefijo g_ para variables globales definidas en un paquete.

El siguiente ejemplo de bloque agrega una sección de manejo de excepciones que atrapa cualquier excepción
(WHEN OTHERS) que pueda ser lanzada y muestra el mensaje de error, que es retornado por la función
SQLERRM (provista por Oracle).

DECLARE
l_mensaje VARCHAR2(100) := '¡Hola Mundo!';
BEGIN
DBMS_OUTPUT.put_line(l_mensaje);
EXCEPTION
WHEN OTHERS
THEN
DBMS_OUTPUT.put_line(SQLERRM);
END;

El siguiente ejemplo de bloque demuestra la habilidad de PL/SQL de anidar bloques dentro de bloques así
como el uso del operador de concatenación (||) para unir múltiples strings.

DECLARE
l_mensaje VARCHAR2(100) := '¡Hola';
BEGIN
DECLARE
l_mensaje2 VARCHAR2(100) := l_mensaje || ' Mundo!';
BEGIN
DBMS_OUTPUT.put_line(l_mensaje2);
END;
EXCEPTION
WHEN OTHERS
THEN
DBMS_OUTPUT.put_line(DBMS_UTILITY.format_error_stack);
END;

Ejecutando bloques PL/SQL


Una vez que hemos escrito un bloque de código PL/SQL éste se puede ejecutar. Existen muchas
herramientas para ejecutar código PL/SQL. La más básica es SQL*Plus, una interfaz de línea de comandos
para ejecutar sentencias SQL así como bloques PL/SQL. La Figura 1 muestra un ejemplo de ejecución del
más simple de los bloques de ejemplo de nuestro “¡Hola Mundo!” en SQL*Plus.

Figura 1: Ejecutando “¡Hola Mundo!” en SQL*Plus


La primera cosa que hacemos después de conectarnos a la base mediante SQL*Plus es habilitar la salida del
servidor, por lo que las llamadas a DBMS_OUTPUT.PUT_LINE resultarán en la visualización de texto en la
pantalla. Luego escribimos el código que constituye nuestro bloque. Finalmente, ingresamos una barra (/) para
decirle a SQL*Plus que ejecute ese código.

SQL*Plus entonces ejecuta el bloque y muestra el “¡Hola Mundo!” en la pantalla. SQL*Plus es provisto por
Oracle como una especie de línea base de entorno donde se pueden ejecutar sentencias SQL y bloques
PL/SQL. Mientras que algunos desarrolladores siguen utilizando únicamente SQL*Plus, la mayoría utiliza un
entorno de desarrollo integrado (IDE). Entre los más populares de estos entornos de desarrollo (basado en
encuestas informales que he tomado en mis sesiones de entrenamiento) son

• Oracle SQL Developer, de Oracle • Toad y SQL Navigator, de Quest Software • PL/SQL Developer, de
Allround Automations

Cada herramienta ofrece, con algunas diferencias, ventanas y pasos para crear, guardar, y ejecutar bloques
PL/SQL, así como habilitar y deshabilitar la salida del servidor. En esta serie de artículos, voy a suponer que
sólo tienen acceso a SQL*Plus y que van a ejecutar todas las sentencias en una ventana de comandos
SQL*Plus.

¡Póngale nombre a los bloques!

Todos los bloques que hemos visto hasta el momento son “anónimos”, no tienen nombres. Si los bloques
anónimos fueran la única manera de organizar el código, sería muy difícil usar PL/SQL para crear una
aplicación grande y compleja. Por esto, PL/SQL soporta la definición de bloques nombrados (named blocks),
también conocidos como subprogramas. Los subprogramas pueden ser procedimientos o funciones.
Generalmente, un procedimiento se utiliza para realizar una acción y una función se utiliza para calcular y
devolver un valor. Voy a tratar sobre subprogramas con mucho más detalle en un próximo artículo de esta
serie. Por ahora, vamos a asegurarnos de que se comprendan los conceptos básicos detrás de la creación del
subprograma.

Supongamos que necesitamos mostrar "¡Hola Mundo!" desde múltiples lugares en nuestra aplicación.
Queremos evitar la repetición de la misma lógica en todos esos lugares. Por ejemplo, ¿qué pasa cuando
tenemos que cambiar el mensaje, tal vez para "¡Hola Universo!"? Vamos a tener que encontrar todos los
lugares en nuestro código donde esta lógica aparece.

En su lugar, vamos a crear un procedimiento denominado hola_mundo mediante la ejecución de la siguiente


sentencia DDL (Data Definition Language):

CREATE OR REPLACE PROCEDURE hola_mundo IS


l_mensaje VARCHAR2(100) := '¡Hola Mundo!';
BEGIN
DBMS_OUTPUT.put_line(l_mensaje);
END hola_mundo;

Con esto hemos extendido PL/SQL. Además de llamar a los programas creados por Oracle e instalados en la
base de datos (como DBMS_OUTPUT.PUT_LINE), podemos llamar a nuestro propio subprograma dentro de
un bloque PL/SQL:

BEGIN
hola_mundo;
END;

Hemos escondido todos los detalles de cómo decir hola al mundo dentro del cuerpo (body), o implementación,
de nuestro procedimiento. Ahora podemos llamar a este procedimiento hola_mundo y mostrar el mensaje
deseado sin tener que escribir la llamada a DBMS_OUTPUT.PUT_LINE o averiguar la forma correcta de darle
formato al texto. Podemos llamar a este procedimiento desde cualquier lugar en nuestra aplicación. Así que si
alguna vez necesitamos cambiar ese texto, lo vamos a hacer en un solo lugar, el único punto de definición de
ese texto.

El procedimiento hola_mundo es muy simple. Tus procedimientos tendrán mucho más código, y casi siempre
también tendrán parámetros. Los parámetros pasan información a los subprogramas, cuando éstos son
llamados, y es lo que permite crear subprogramas más flexibles y genéricos. Se pueden usar en muchos
contextos diferentes.

He mencionado antes que algún día puede ser que desee mostrar "¡Hola Universo!" en lugar de "¡Hola
Mundo!". Podría hacer una copia de nuestro procedimiento hola_mundo y cambiar el texto que se muestra:

CREATE OR REPLACE PROCEDURE hola_universo IS


l_mensaje VARCHAR2(100) := '¡Hola Universo!';
BEGIN
DBMS_OUTPUT.put_line(l_mensaje);
END hola_universo;
Podríamos, sin embargo, terminar con las decenas de variantes del “mismo” procedimiento hola, que haría
muy difícil mantener nuestra aplicación. Un enfoque mucho mejor es analizar el procedimiento e identificar
qué partes se mantienen incambiadas (son estáticas) cuando el mensaje tiene que cambiar y qué partes
cambian. Luego podemos pasar las partes que cambian como parámetros y tener un procedimiento único que
se puede utilizar en diferentes circunstancias.

Así que vamos a cambiar hola_mundo (y hola_universo) a un nuevo procedimiento, hola_lugar:

CREATE OR REPLACE PROCEDURE hola_lugar (lugar_in IN VARCHAR2) IS


l_mensaje VARCHAR2(100);
BEGIN
l_mensaje := '¡Hola ' || place_in;
DBMS_OUTPUT.put_line(l_mensaje);
END hola_lugar;

Justo después del nombre del procedimiento, añadimos entre paréntesis de apertura y cierre, un único
parámetro. Podemos tener varios parámetros, pero cada parámetro de la misma forma básica:

nombre_de_parametro modo_de_parametro tipo_de_datos

En otras palabras, debemos proveer un nombre para el parámetro, el modo o forma en que éste será usado
(IN = sólo lectura), y el tipo de dato que será pasado al subprograma a través de este parámetro.

En este caso, vamos a pasar un texto de sólo lectura al procedimiento hola_lugar.

Y ahora podemos saludar a nuestro mundo y a nuestro universo como sigue:

BEGIN
hola_lugar('Mundo!');
hola_lugar('Universo!');
END;

Más adelante en esta serie vamos a explorar el concepto de reutilización y la manera de evitar la repetición,
pero debes ser capaz de ver en este ejemplo, el poder de ocultar la lógica detrás de un bloque con nombre.

Ahora supongamos que no sólo queremos mostrar nuestros mensajes "Hola". A veces tenemos que mantener
los mensajes en una tabla en la base de datos; en otras ocasiones, tenemos que pasar el texto de nuevo al
entorno del cliente para su visualización en un navegador Web. En otras palabras, necesitamos separar la
forma en que se construyó el mensaje "Hola" de la forma en que se utiliza (se visualiza, se guarda, se envía
otro programa, etc). Podemos alcanzar este nivel deseado de flexibilidad moviendo el código que construye el
mensaje a su propia función:

CREATE OR REPLACE FUNCTION


hola_mensaje(lugar_in IN VARCHAR2) RETURN VARCHAR2 IS
BEGIN
RETURN '¡Hola ' || place_in;
END hola_mensaje;

Este subprograma se diferencia del procedimiento original en lo siguiente:


• El tipo de programa es ahora FUNCTION y no PROCEDURE.
• El nombre del subprograma ahora describe los datos que se devuelven, no las acciones tomadas.
• El cuerpo o la implementación del subprograma contiene ahora una cláusula RETURN que construye el
mensaje y lo devuelve al bloque llamador.
• La cláusula RETURN después de la lista de parámetros establece el tipo de datos devuelto por la función.
Teniendo el código necesario para construir el mensaje dentro de la función hola_mensaje, podemos utilizar
este mensaje de múltiples maneras. Podemos, por ejemplo, llamar a la función para obtener el mensaje y
asignárselo a una variable:

DECLARE
l_mensaje VARCHAR2(100);
BEGIN
l_mensaje := hola_mensaje('Universo');
END;

Nota que llamamos a la función hola_mensaje como parte de una sentencia PL/SQL (en este caso, la
asignación de un texto a una variable). La función hola_mensaje devuelve un string, por lo que se puede
utilizar en lugar de un string en cualquier sentencia ejecutable.

También podemos volver a nuestro procedimiento hola_lugar y reemplazar el código utilizado para crear el
string con una llamada a la función:

CREATE OR REPLACE PROCEDURE


hola_lugar(place_in IN VARCHAR2) IS
BEGIN
DBMS_OUTPUT.put_line(hola_mensaje(place_in));
END hola_lugar;

También podemos llamar la función desde una sentencia SQL. En el siguiente bloque, insertamos el mensaje
en una tabla de la base:

BEGIN
INSERT INTO tabla_mensaje(fecha_mensaje, texto_mensaje)
VALUES (SYSDATE, hola_mensaje('Montevideo'));
END;

Aunque la lógica del “mensaje hola” es muy simple, demuestra el poder de asignar nombres a una o más
sentencias ejecutables (un algoritmo) y luego referenciar el algoritmo simplemente especificando el nombre y
los parámetros requeridos.

Los bloques PL/SQL con nombre, permiten construir aplicaciones complejas que pueden ser comprendidas y
mantenidas con relativa facilidad.

Sobre los nombres en una base Oracle


Ahora que ya se aprecia la importancia de asignar nombres a la lógica, es tiempo de hablar sobre las reglas
para los nombres (o, para ser más precisos, identificadores) tanto en PL/SQL como, de forma más general, en
una base Oracle.
Estas son las reglas para construir identificadores válidos en una base Oracle:

• El largo máximo es de 30 caracteres.


• El primer caracter debe ser una letra, pero cada caracter después del primero puede ser una letra, un
número (0 a 9), un signo de pesos ($), un guión bajo (_), o un numeral (#). Todos los siguientes son
identificadores válidos:

hola_mundo
hola$mundo
hola#mundo

pero estos son inválidos:


1hola_mundo
hola%mundo

• PL/SQL es case-insensitive (no es sensitivo a mayúsculas y minúsculas) con respecto a los identificadores.
PL/SQL trata todos los siguientes como el mismo identificador:

hola_mundo
Hola_Mundo
HOLA_MUNDO
Para ofrecer más flexibilidad, Oracle permite evitar las restricciones de la segunda y tercera regla, encerrando
al identificador entre comillas dobles. Un quoted identifier (identificador encerrado entre comillas) puede
contener cualquier secuencia de caracteres imprimibles excluyendo las comillas dobles; las diferencias entre
mayúsculas y minúsculas serán además preservadas. Así, todos los siguientes identificadores son válidos y
distintos:

"Abc"
"ABC"
"a b c"
Es muy raro encontrar identificadores entre comillas en código PL/SQL; algunos grupos de desarrollo los usan
para conformar con sus convenciones de nombres o porque encuentran que una mezcla de mayúsculas y
minúsculas resulta más fácil de leer.

Estas mismas reglas aplican a los nombres de los objetos de base de datos como tablas, vistas y
procedimientos, con una regla adicional: a menos que se encierren entre comillas los nombres de estos
objetos, Oracle los mantendrá en mayúsculas.

Así que cuando creamos un procedimiento como el que sigue:

CREATE OR REPLACE PROCEDURE hola_mundo IS


BEGIN
DBMS_OUTPUT.put_line('¡Hola Mundo!');
END hola_mundo;

la base de datos Oracle lo mantendrá con el nombre HOLA_MUNDO.

En el bloque siguiente, llamaremos este procedimiento tres veces, y aunque el nombre luzca diferente cada
vez, siempre se ejecutará el mismo procedimiento:

BEGIN
hola_mundo;
HOLA_MUNDO;
"HOLA_MUNDO";
END;

Por otro lado, la base Oracle no será capaz de ejecutar el procedimiento si lo llamamos como sigue:

BEGIN
"hola_mundo";
END;

Esto buscará dentro de la base un procedimiento llamado hola_mundo en lugar de HOLA_MUNDO.

Si no se quiere que los nombres de los subprogramas se mantengan en mayúsculas, los nombres se deben
encerrar entre comillas cuando se crea el subprograma:

CREATE OR REPLACE PROCEDURE "Hola_Mundo" IS


BEGIN
DBMS_OUTPUT.put_line('¡Hola Mundo!');
END "Hola_Mundo";

Ejecutando SQL dentro de bloques PL/SQL


PL/SQL es un lenguaje de programación de base de datos. Casi todos los programas que escribiremos en
PL/SQL leerán desde, o escribirán en, una base de datos Oracle utilizando SQL. Aunque estas series asumen
que se conoce SQL, debemos estar conscientes de la forma en que llamamos a las sentencias desde un
bloque PL/SQL.

Y aquí hay algunas buenas noticias: Oracle hace que sea muy fácil escribir y ejecutar sentencias SQL en
PL/SQL. La mayor parte de las veces, simplemente escribiremos las sentencias SQL directamente en nuestro
bloque PL/SQL y después agregaremos el código necesario para la interfaz entre las sentencias SQL y el
código PL/SQL.

Supongamos, por ejemplo, que tenemos una tabla llamada empleados, con una columna clave primaria
id_empleado, y una columna apellido. Podemos ver el apellido del empleado con ID 138, como sigue:

SELECT apellido
FROM empleados
WHERE id_empleado = 138

Ahora querríamos ejecutar esta misma consulta dentro de nuestro bloque PL/SQL y desplegar el nombre.
Para hacer esto, necesitaremos “copiar” el apellido desde la tabla a una variable local, lo cual podemos hacer
con la cláusula INTO:
DECLARE
v_apellido empleados.apellido%TYPE;
BEGIN
SELECT apellido
INTO v_apellido
FROM empleados
WHERE id_empleado = 138;

DBMS_OUTPUT.put_line(v_apellido);
END;

Primero declaramos una variable local, y haciendo esto introducimos otra característica elegante de PL/SQL:
la capacidad de fijar el tipo de datos de nuestra variable en función del tipo de datos de una columna en una
tabla (esto será profundizado más adelante en esta serie)

Después ejecutamos una consulta contra la base, obteniendo el apellido del empleado y asignándolo
directamente en la variable v_apellido.

Por supuesto, querremos hacer más que ejecutar sentencias SELECT en PL/SQL, también querremos
insertar, modificar y eliminar datos desde PL/SQL. Aquí hay ejemplos de cada uno de esos tipos de
sentencias DML:

• Eliminamos todos los empleados en el departamento 10 y mostramos cuántas tuplas fueron eliminadas:

DECLARE
v_id_departamento empleados.id_departamento%TYPE := 10;
BEGIN
DELETE FROM empleados
WHERE id_departamento = v_id_departamento;

DBMS_OUTPUT.put_line(SQL%ROWCOUNT);
END;

Referenciamos la variable PL/SQL directamente dentro de la sentencia DELETE. Cuando el bloque se


ejecuta, la variable se reemplaza con el valor actual, 10, y el DELETE es ejecutado por el motor de SQL.
SQL%ROWCOUNT es un atributo especial de cursor que retorna el número de tuplas modificadas por la
última sentencia DML ejecutada en nuestra sesión.

• Modificar todos los empleados en el departamento 10 con un 20% de incremento salarial.

DECLARE
v_id_departamento empleados.id_departamento%TYPE := 10;
BEGIN
UPDATE empleados
SET salario = salario * 1.2
WHERE id_departamento = v_id_departamento;

DBMS_OUTPUT.put_line(SQL%ROWCOUNT);
END;

Insertar un nuevo empleado en la tabla.

BEGIN
INSERT INTO empleados (id_empleado
, apellido
, id_departamento
, salario)
VALUES (100
, 'Feuerstein'
, 10
, 200000);

DBMS_OUTPUT.put_line(SQL%ROWCOUNT);
END;

En este bloque, proveímos los valores de las columnas como literales, en lugar de variables, directamente
dentro de la sentencia SQL.

Recursos para Desarrolladores PL/SQL


Si recién estás comenzando con PL/SQL, deberías conocer y aprovechar la multitud de recursos gratuitos
online que existen. Aquí hay algunos de los más populares y útiles:

• La página de PL/SQL en OTN (Oracle Technology Network),


en oracle.com/technetwork/database/features/plsql: un excelente punto de comienzo para explorar recursos
de PL/SQL en el popular sitio de OTN
• PL/SQL Obsession, en ToadWorld.com/SF: una colección de recursos de desarrollo PL/SQL del autor,
incluyendo material de entrenamiento, presentaciones, código ejemplo, estándares, videos de buenas
prácticas, y más

• PL/SQL Challenge, en plsqlchallenge.com: una pregunta diaria sobre PL/SQL que te ayudará a evaluar y
mejorar tu conocimiento sobre PL/SQL

A continuación: Controlando la ejecución en el bloque


En este artículo, has aprendido cómo se enmarca PL/SQL en el amplio mundo de la base de datos Oracle.
Has aprendido también cómo definir bloques de código PL/SQL y a nombrar esos bloques, de forma que el
código de tu aplicación puede ser utilizado y mantenido con más facilidad. Finalmente, fuiste introducido en la
ejecución de sentencias SQL dentro de PL/SQL.

¿Por qué anidar bloques?


Podemos poner BEGIN antes de cualquier conjunto de una o más sentencias ejecutables seguidas de un
END, creando un bloque anidado con esas sentencias. Hay dos ventajas principales para hacer esto: (1)
posponer la asignación de memoria para variables que se necesitan únicamente en el bloque anidado, y (2)
limitar la propagación de una excepción lanzada por una de las sentencias del bloque anidado.

Consideremos el siguiente bloque:

DECLARE
l_mensaje1 VARCHAR2(100) := 'Hola';
l_mensaje2 VARCHAR2(100) := ' Mundo!';
BEGIN
IF SYSDATE >= TO_DATE('01-JAN-2012')
THEN
l_mensaje2 := l_mensaje1 || l_mensaje2;
DBMS_OUTPUT.put_line(l_mensaje2);
ELSE
DBMS_OUTPUT.put_line(l_mensaje1);
END IF;
END;

El bloque despliega “¡Hola Mundo!” cuando la fecha de hoy (retornada por SYSDATE) es por lo menos el
primer día de 2012; en otro caso, únicamente despliega el mensaje “Hola”. Aunque este bloque se ejecute en
2011, asigna memoria para la variable l_mensaje2.

Si reestructuramos este bloque, la memoria para l_mensaje2 será asignada únicamente después del 2011:

DECLARE
l_mensaje1 VARCHAR2(100) := 'Hola';
BEGIN
IF SYSDATE > TO_DATE('01-JAN-2011')
THEN
DECLARE
l_mensaje2 VARCHAR2(100) := ' Mundo!';
BEGIN
l_mensaje2 := l_mensaje1 || l_mensaje2;
DBMS_OUTPUT.put_line(l_mensaje2);
END;
ELSE
DBMS_OUTPUT.put_line(l_mensaje1);
END IF;
END;

De forma similar, podemos agregar una sección de excepciones a este bloque anidado, atrapando errores y
permitiendo que el bloque exterior continúe con su ejecución:

DECLARE
l_mensaje1 VARCHAR2(100) := 'Hola';
BEGIN
DECLARE
l_mensaje2 VARCHAR2(5);
BEGIN
l_mensaje2 := ' Mundo!';
DBMS_OUTPUT.put_line(l_mensaje1 || l_mensaje2);
EXCEPTION
WHEN OTHERS
THEN
DBMS_OUTPUT.put_line(DBMS_UTILITY.format_error_stack);
END;
DBMS_OUTPUT.put_line(l_mensaje1);
END;

En este caso, el bloque anidado lanzará una excepción VALUE_ERROR, porque la variable l_mensaje2 es
muy pequeña (máximo de 5 bytes) para el texto “ Mundo!”.La sección de excepciones del bloque anidado
atrapará y desplegará el error. El bloque exterior continuará su ejecución.

Un posterior artículo en estas series se enfocará en cómo funciona el manejo de excepciones en PL/SQL.

Más adelante en esta serie de artículos, mostraré cómo controlar el flujo de ejecución en nuestros bloques:
lógica condicional con IF y CASE; lógica iterativa con FOR, WHILE y LOOP; así como lanzar y manejar
excepciones.

También podría gustarte