Preparar
Sus fórmulas se ven así:
d*b+(l*4+r)+(i/d)+s
Reemplazaría las variables con $n
notación para que puedan reemplazarse con valores directamente en plpgsql EXECUTE
(ver a continuación):
$1*$5+($3*4+$2)+($6/$1)+$4
Puede almacenar sus fórmulas originales adicionalmente (para el ojo humano) o generar este formulario dinámicamente con una expresión como:
SELECT regexp_replace(regexp_replace(regexp_replace(
regexp_replace(regexp_replace(regexp_replace(
'd*b+(l*4+r)+(i/d)+s'
, '\md\M', '$1', 'g')
, '\mr\M', '$2', 'g')
, '\ml\M', '$3', 'g')
, '\ms\M', '$4', 'g')
, '\mb\M', '$5', 'g')
, '\mi\M', '$6', 'g');
Solo asegúrate de que tu traducción sea sólida. Alguna explicación para las expresiones regexp :
\ m .. coincide solo al comienzo de una palabra
\ M .. coincide solo al final de una palabra
4to parámetro 'g'
... reemplazar globalmente
Función básica
CREATE OR REPLACE FUNCTION f_calc(
d int -- days worked that month
,r int -- new nodes accuired
,l int -- loyalty score
,s numeric -- subagent commission
,b numeric -- base rate
,i numeric -- revenue gained
,formula text
,OUT result numeric
) RETURNS numeric AS
$func$
BEGIN
EXECUTE 'SELECT '|| formula
INTO result
USING $1, $2, $3, $4, $5, $6;
END
$func$ LANGUAGE plpgsql SECURITY DEFINER IMMUTABLE;
Llamada:
SELECT f_calc(1, 2, 3, 4.1, 5.2, 6.3, '$1*$5+($3*4+$2)+($6/$1)+$4');
Devoluciones:
29.6000000000000000
Puntos principales
La función toma 6 parámetros de valor y formula text
como séptimo. Puse la fórmula al final, para que podamos usar en $1 .. $6
lugar de $2 .. $7
. Solo por el bien de la legibilidad.
Asigné tipos de datos para los valores como mejor me parecía. Asigne los tipos adecuados (para implementar controles básicos de cordura) o simplemente haga que todos numeric
:
Pase valores para la ejecución dinámica con la USING
cláusula Esto evita el vaciado de un lado a otro y hace que todo sea más simple, seguro y rápido.
Utilizo un OUT
parámetro porque es más elegante y hace una sintaxis más clara y corta. RETURN
No se necesita un final , el valor de los parámetros OUT se devuelve automáticamente.
Considere la conferencia sobre seguridad de @Chris y el capítulo "Cómo escribir las funciones de DEFINER DE SEGURIDAD de forma segura" en el manual. En mi diseño, el único punto de inyección es la fórmula misma.
Puede usar valores predeterminados para algunos parámetros para simplificar aún más la llamada.