Oracle básico (IV): Programación en PL/SQL


El lenguaje de programación de Oracle, llamado PL/SQL, es un lenguaje portable, procedural y de transacción muy potente y de fácil manejo, con las siguientes características fundamentales:

1.    Incluye todos los comandos de SQL estudiados en el artículo Oracle Básico I y II (ver revista Algoritmo números 8 y 9, respectivamente):

       -    SELECT

       -    INSERT

       -    UPDATE

       -    DELETE.

2.    Es una extensión de SQL, ya que este es un lenguaje no completo dado que no incluye las herramientas clásicas de programación. Por eso, PL/SQL amplia sus posibilidades al incorporar las siguientes sentencias:

 

       -    Control condicional

 

                IF ... THEN ... ELSE ... ENDIF  

 

       -    Ciclos

 

                FOR ... LOOP
      
WHILE ... LOOP
 

-      3.    Incorpora opciones avanzadas en:

-       Control y tratamiento de errores llamado excepciones.

-      Manejo de cursores.

-      Variedad de  procedimientos y  funciones empaquetadas incorporadas  en el módulo SQL*Forms para la programación de disparadores (Trigger) y procedimientos del usuario (Procedure).

Estructura del bloque de código

Veamos a continuación la organización del bloque de código de PL/SQL, compuesto por cuatro secciones DECLARE, BEGIN, EXCEPTION y END como se detalla en el fuente 1:

/* --- Fuente 1 -----------------------------------------------------------

[<< nombre del bloque >>]
        
Etiqueta que identifica al Bloque. 


[DECLARE]

        
Declaración de
                  
Variable
                  
Constante                         Se inicializa con un valor que no se puede modificar.                   Cursor                              Area de trabajo que contiene los datos de la fila de la tabla en uso. El cursor es el resultado de una sentencia SELECT.         ExcepciónVariables                    para control de errores.

BEGIN

        
Código.

[EXCEPTION]

        
Control y tratamiento de errores.         Es el punto al que se transfiere el control del programa siempre que exista un problema. Los indicadores de excepción pueden ser definidos por el usuario o por el sistema, como es por ejemplo la excepción ZERO_DIVIDE. Las excepciones se activan automáticamente al ocurrir un error, existiendo la definición de la excepción OTHERS que considera aquellos errores no definidos y que siempre se ubica al final de todas las excepciones.
END
[nombre del bloque];
        
Fin del Bloque.
 

Con el ejemplo del fuente 2 ilustraremos las distintas secciones que componen un bloque de código en PL/SQL. En este caso deseamos calcular la venta promedio del día y, en caso que la misma sea menor a lo esperado, se debe registrar en la tabla VENTABAJA.

/* --- Fuente 2 -----------------------------------------------------------

DECLARE
        
esperada          CONSTANT NUMBER(5) := 500;

        
xtotal            NUMBER;
        
xcant             NUMBER;

        
xprom             NUMBER;
BEGIN
        
/*Asigna a la variable xtotal el TOTAL de las ventas
        
y a la variable xcant la cantidad de ventas del día.

        
*/
        
SELECT SUM(valor),COUNT(valor) INTO xtotal,xcant
                  
FROM ventas WHERE fecha=sysdate;
        
xprom:=xtotal/xcant;
        
IF xprom >= esperada THEN

                  
message('Ventas por encima de la esperada');
                  
pause;
        
ELSE
                  
/*Se registra en la tabla ventabaja las ventas por debajo
                  
del promedio esperado */

                  
INSERT INTO ventabaja VALUES (sysdate,xprom);
        
END IF;
EXCEPTION
        
WHEN ZERO_DIVIDE THEN

                  
message('No se realizaron ventas en el día');
        
pause;
        
WHEN OTHERS THEN
                  
message('Error Indefinido');
        
pause;
END;
 

Asignación de valores

Las dos formas que existen para asignar valores a variables de memoria, vistas en el ejemplo anterior, son:

-      Con el operador de asignación :=, como cuando calculamos el promedio de las ventas asignándole valor a la variable xprom con la siguiente sentencia:

 

          xprom:=xtotal/xcant; 

 

-      Con la sentencia SELECT que contiene la orden INTO, como se muestra, es la asignación de valores a las variables xtotal y xcant con el siguiente código:

 

          SELECT SUM(valor),
                  
COUNT(valor)
                  
INTO xtotal,xcant
                  
FROM ventas
                  
WHERE fecha=sysdate;
 

Veamos a continuación, con la creación del procedimiento FECHAALTA, la asignación de valores a una variable de registro llamada Client_Rec, que va a contener la estructura de una fila de la tabla CLIENTES y que estará formada por todos los campos correspondientes a la tabla. Para esto usaremos el atributo de variable %ROWTYPE que declara una variable de registro que contiene la estructura de la tabla, y después, con el uso de la sentencia SELECT * INTO, se asigna a la variable de registro los valores de la fila. La referencia a un dato contenido en la variable de registro se hace de la forma variable_registro.campo, como por ejemplo cliente_rec.fecha hace referencia a la fecha del alta del cliente.

Pasemos a mostrar lo anteriormente expuesto a través del código del fuente 3.

/* --- Fuente 3 -----------------------------------------------------------

PROCEDURE FECHAALTA IS

        
BEGIN
               
DECLARE
                        
cliente_rec  clientes%ROWTYPE;
               
BEGIN
                        
SELECT * INTO cliente_rec
                                  
FROM clientes
                                  
WHERE codigo = 5;
                        
IF cliente_rec.fecha>sysdate-10
                        
THEN

                                  
message(        cliente_rec.nombre||
                                                        
' Dado de alta en los últimos 10 días');

                                  
pause;
                        
ELSE
                                  
message(        cliente_rec.nombre||

                                                        
' Dado de alta hace más de 10 días');
                                  
pause;
                        
END IF;

        
END;
END;
 

SELECT con control de excepciones

La sentencia SELECT en PL/SQL no muestra en pantalla las filas resultantes de la consulta, como ocurre en SQL (el cual trabaja en forma interactiva) sino que, según sea la acción a realizar, así será la cantidad de filas devueltas por la consulta, existiendo en este caso una de las tres posibles situaciones recogidas en la tabla 1:

Cantidad de filas

Acción

Una

Se realiza la siguiente sentencia

Más de una

Ocurre la excepción TOO_MANY_ROWS

1