Preparare
Le tue formule si presentano così:
d*b+(l*4+r)+(i/d)+s
Vorrei sostituire le variabili con la $n
notazione in modo che possano essere sostituite con i valori direttamente in plpgsql EXECUTE
(vedi sotto):
$1*$5+($3*4+$2)+($6/$1)+$4
Puoi memorizzare anche le tue formule originali (per l'occhio umano) o generare questo modulo in modo dinamico con un'espressione come:
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');
Assicurati solo che la traduzione sia valida. Qualche spiegazione per le espressioni regexp :
\ m .. corrisponde solo all'inizio di una parola
\ M .. corrisponde solo alla fine di una parola
4 ° parametro 'g'
.. sostituire a livello globale
Funzione principale
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;
Chiamata:
SELECT f_calc(1, 2, 3, 4.1, 5.2, 6.3, '$1*$5+($3*4+$2)+($6/$1)+$4');
Ritorna:
29.6000000000000000
Punti importanti
La funzione accetta 6 parametri e formula text
come settimo. Ho messo la formula per ultima, quindi possiamo usare al $1 .. $6
posto di $2 .. $7
. Solo per motivi di leggibilità.
Ho assegnato i tipi di dati per i valori come ho ritenuto opportuno. Assegna i tipi corretti (per implementare i controlli di integrità di base) o semplicemente eseguili tutti numeric
:
Passa i valori per l'esecuzione dinamica con la USING
clausola. Questo evita il lancio avanti e indietro e rende tutto più semplice, sicuro e veloce.
Uso un OUT
parametro perché è più elegante e rende la sintassi più chiara e più breve. RETURN
Non è necessario un finale , il valore dei parametri OUT viene restituito automaticamente.
Considera la lezione sulla sicurezza di @Chris e il capitolo "Scrivere in sicurezza le funzioni di DEFINER" nel manuale. Nel mio progetto, l'unico punto di iniezione è la formula stessa.
È possibile utilizzare i valori predefiniti per alcuni parametri per semplificare ulteriormente la chiamata.