Bereiten
Ihre Formeln sehen folgendermaßen aus:
d*b+(l*4+r)+(i/d)+s
Ich würde die Variablen durch $n
Notation ersetzen, damit sie direkt in plpgsql durch Werte ersetzt werden können EXECUTE
(siehe unten):
$1*$5+($3*4+$2)+($6/$1)+$4
Sie können Ihre Originalformeln zusätzlich (für das menschliche Auge) speichern oder dieses Formular dynamisch mit einem Ausdruck wie dem folgenden generieren:
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');
Stellen Sie einfach sicher, dass Ihre Übersetzung solide ist. Einige Erklärungen für die regulären Ausdrücke :
\ m .. stimmt nur am Anfang eines Wortes
überein \ M .. stimmt nur am Ende eines Wortes überein
4. Parameter 'g'
.. global ersetzen
Hauptfunktion
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;
Anruf:
SELECT f_calc(1, 2, 3, 4.1, 5.2, 6.3, '$1*$5+($3*4+$2)+($6/$1)+$4');
Kehrt zurück:
29.6000000000000000
Hauptpunkte
Die Funktion nimmt 6 Wert Parameter und formula text
als 7 .. Ich habe die Formel zuletzt gesetzt, damit wir $1 .. $6
stattdessen verwenden können $2 .. $7
. Nur aus Gründen der Lesbarkeit.
Ich habe den Werten nach eigenem Ermessen Datentypen zugewiesen. Weisen Sie die richtigen Typen zu (um grundlegende Sanitätsprüfungen durchzuführen) oder machen Sie einfach alle numeric
:
Übergeben Sie Werte für die dynamische Ausführung mit der USING
Klausel. Dies vermeidet das Hin- und Herwerfen und macht alles einfacher, sicherer und schneller.
Ich benutze einen OUT
Parameter, weil das eleganter ist und eine kürzere, klarere Syntax ermöglicht. Ein Finale RETURN
wird nicht benötigt, der Wert der OUT-Parameter wird automatisch zurückgegeben.
Beachten Sie den Vortrag über Sicherheit von @Chris und das Kapitel "Sicheres Schreiben von SECURITY DEFINER-Funktionen" im Handbuch. In meinem Design ist der einzige Injektionspunkt die Formel selbst.
Sie können für einige Parameter Standardeinstellungen verwenden , um den Aufruf weiter zu vereinfachen.