Anuncios en tutorial de programación PLSQL

lunes, 4 de marzo de 2019

Cómo evitar el uso de constantes fijas (hard-coded) en PL/SQL

Chiste de perros e Internet para amenizar el tema de las constantes fijas en PLSQLEsta claro que la mayoría de los programas y aplicaciones PLSQL tienen su propio conjunto de constantes que determinan las características de dicha aplicación. Por lo general, estos valores constantes tienen que ser utilizados en distintos lugares del código. En muchas ocasiones estos valores permanecerán invariables durante todo el ciclo de vida de la aplicación pero, en muchos otros casos, cambiarán de forma periódica (por ejemplo, una vez al año).

Pongamos un ejemplo, supongamos que en un programa PL/SQL establecemos que el salario anual de un empleado no puede superar los 50.000 euros. Podemos codificar esta norma utilizando la siguiente subrutina:

IF l_salario_anual > 50000
THEN
RAISE_APPLICATION_ERROR (
-20001, 
'El salario anual no puede ser superior
a 50000 euros');
END IF;

La mayoría de los programadores sabemos que referenciar un valor constante de esta manera no es muy recomendable. En inglés se dice que la constante está "hard-coded" directamente en la rutina. Resulta obvio señalar que este tipo de prácticas suele derivar en problemas, ya que el valor de 50.000 euros cambiará muy probablemente de año en año y, cuando esto ocurra, deberemos revisar el código PLSQL y cambiar el antiguo valor por el nuevo en cada uno de los sitios donde sea utilizado.

En PL/SQL disponemos de tres formas bastante evidentes de evitar tener que utilizar constantes directamente en el código:
  • Crear un paquete PLSQL que asigne el valor a esa constante
  • Crear un función PLSQL que devuelva dicho valor
  • Almacenar y gestionar el valor de dicha constante en una tabla de la base de datos Oracle
A continuación pondré un ejemplo de cada una de las opciones mencionadas.

Paquete PL/SQL de constantes

CREATE PACKAGE c_constantes IS
c_salario_maximo CONSTANT NUMBER := 50000;
END c_constantes;

Una vez definido el paquete ya sólo tendríamos que referirnos al mismo de la siguiente manera:

IF l_salario_anual > 
c_constantes.c_salario_maximo
THEN
RAISE_APPLICATION_ERROR (
-20001, 
'El salario anual no puede ser superior a '
|| c_constantes.c_salario_maximo
|| ' euros');
END IF;

Función PL/SQL que devuelve el valor de la constante

CREATE PACKAGE f_constantes IS
FUNCTION f_salario_maximo RETURN NUMBER;
END f_constantes;

CREATE PACKAGE BODY f_constantes IS
FUNCTION f_salario_maximo RETURN NUMBER IS
BEGIN
RETURN 50000;
END;
END f_constantes;

Y ahora para referirnos a la constante utilizaríamos el siguiente código:

IF l_salario_anual > 
f_constantes.f_salario_maximo()
THEN
RAISE_APPLICATION_ERROR (
-20001, 
'El salario anual no puede ser superior a '
|| f_constantes.f_salario_maximo()
|| ' euros');
END IF;

Almacenar la constante en una tabla de la base de datos

Si en nuestra aplicación debemos gestionar un buen número de constantes, la opción más recomendable sería crear una tabla con los campos, por ejemplo, "nombre", "descripción" y "valor", y sacar de ella los valores constantes correspondientes. En nuestro caso, y suponiendo que el campo "valor" es un VARCHAR2, podríamos escribir la siguiente función PLSQL:

CREATE PACKAGE t_constantes IS
FUNCTION t_numero 
(t_nombre IN tabla_constantes.valor%TYPE) 
RETURN NUMBER;
END t_constantes;

CREATE PACKAGE BODY t_constantes IS
FUNCTION t_numero 
(p_nombre IN tabla_constantes.valor%TYPE) 
RETURN NUMBER IS
BEGIN
v_valor tabla_constantes.valor%TYPE;
SELECT valor
INTO v_valor
FROM tabla_constantes
WHERE nombre = p_nombre;
RETURN TO_NUMBER(v_valor);
END;
END t_constantes;

Y para referirnos a la constante utilizaríamos algo semejante a:

IF l_salario_anual >
t_constantes.t_numero('salario maximo')
THEN
RAISE_APPLICATION_ERROR (
-20001, 
'El salario anual no puede ser superior a '
|| t_constantes.t_numero('salario maximo')
|| ' euros');
END IF;

En este ejemplo he definido una función para devolver valores de tipo numérico (NUMBER), pero igualmente podríamos definir funciones semejantes que devuelvan valores de tipo VARCHAR2, DATE, etcétera.

Artículos relacionados:
Tipos de datos en PLSQL.
Procedimientos y funciones en PLSQL.

5 comentarios:

sulubc dijo...

Excelente pagina, me tope con ella por casualidad y no sabes ke gran ayuda es, muchas gracias por estos tips y esperemos ke sigas con muchos mas, soy del df y trabajo para BI, aki estamos utilizando la version 10g y pues es interesante ver todo lo ke puede uno hacer, muchas gracias por compartirnos tus experiencias y consejos !

saludos !

Carlos.

JLPM dijo...

Gracias Sulubc, lamentablemente no dispongo de mucho tiempo para escribir en este blog con más frecuencia, pero prometo seguir escribiendo un artículo al mes.

Dimony dijo...

La seguiré con atención, yo también curro con forms y me vendrá bien todos estos truquillos.

Unknown dijo...

Hola, me gustaría ver la opción que me ayudara con un ejercicio de pl/sql que no he podido resolver

Gregory Rivero dijo...

Hola Pepelu he seguido tu blog y me ha sido de gran ayuda, quisiera saber si tienes pensado publicar algo relacionado a FORMS, o piensas seguir con la tematica de PL/SQL por ahi seria buenisimos que hables de las Expresiones regulares (REGEXP) y las funciones analiticas son buenos temas.