Подготовить
Ваши формулы выглядят так:
d*b+(l*4+r)+(i/d)+s
Я бы заменил переменные на $n
нотации, чтобы они могли быть заменены значениями непосредственно в plpgsql EXECUTE
(см. Ниже):
$1*$5+($3*4+$2)+($6/$1)+$4
Вы можете дополнительно сохранить исходные формулы (для человеческого глаза) или динамически сгенерировать эту форму с помощью следующего выражения:
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');
Просто убедитесь, что ваш перевод звучит правильно. Некоторое объяснение выражений регулярных выражений :
\ m .. соответствует только в начале слова
\ M .. соответствует только в конце слова
4-й параметр 'g'
.. заменить глобально
Основная функция
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;
Вызов:
SELECT f_calc(1, 2, 3, 4.1, 5.2, 6.3, '$1*$5+($3*4+$2)+($6/$1)+$4');
Возвращает:
29.6000000000000000
Основные моменты
Функция принимает 6 значений параметра и formula text
как 7-й. Я ставлю формулу последней, чтобы мы могли использовать $1 .. $6
вместо $2 .. $7
. Просто для удобства чтения.
Я назначил типы данных для значений по своему усмотрению. Назначьте подходящие типы (для реализации базовых проверок работоспособности) или просто сделайте их все numeric
:
Передайте значения для динамического выполнения с USING
предложением. Это позволяет избежать бросания вперед и назад и делает все проще, безопаснее и быстрее.
Я использую OUT
параметр, потому что это более элегантно и делает для более короткого более ясного синтаксиса. Окончательный RETURN
вариант не требуется, значение параметра (ов) OUT возвращается автоматически.
Рассмотрите лекцию по безопасности @Chris и главу «Безопасное написание функций БЕЗОПАСНОСТИ» в руководстве. В моем дизайне единственной точкой внедрения является сама формула.
Вы можете использовать значения по умолчанию для некоторых параметров, чтобы еще больше упростить вызов.