Ваш заголовок запрашивает нечто иное, чем ваш пример.
- Функция должна быть создана , прежде чем вы сможете ее вызвать.(название)
- Необходимо выражение .Вам понадобится мета-функция для этого.(пример)
Я представлю решения для обоих.
1.Динамическая оценка выражений
Необходимо учитывать, что результирующий тип может различаться.Для этого я использую полиморфные типы.
-- DROP SCHEMA x CASCADE;
CREATE SCHEMA x;
CREATE OR REPLACE FUNCTION x.f1(int)
RETURNS int AS
$$SELECT $1 * 100;$$
LANGUAGE sql IMMUTABLE;
CREATE OR REPLACE FUNCTION x.f2(text)
RETURNS text AS
$$SELECT $1 || '_foo';$$
LANGUAGE sql IMMUTABLE;
CREATE TABLE x.my_expr (expr text PRIMARY KEY, def text, rettype text);
INSERT INTO x.my_expr VALUES
('x', $$x.f1(3)$$, 'int')
,('y', $$x.f2('bar')$$, 'text')
;
CREATE OR REPLACE FUNCTION x.f_eval(text, _type anyelement, OUT _result anyelement)
AS
$x$
BEGIN
EXECUTE
'SELECT ' || (SELECT def FROM x.my_expr WHERE expr = $1)
INTO _result;
END;
$x$
LANGUAGE plpgsql;
Звоните:
SELECT x.f_eval('x', (SELECT rettype FROM x.my_expr WHERE expr = 'x'));
f_eval
--------
300
(1 row)
SELECT x.f_eval('y', (SELECT rettype FROM x.my_expr WHERE expr = 'y'));
f_eval
---------
bar_foo
(1 Zeile)
2.Динамическое создание и использование функций
Можно динамически создавать функции, а затем использовать их.Вы не можете сделать это с простым SQL, однако.Для этого вам понадобится другая функция или хотя бы блок анонимного кода (оператор DO) , представленный в PostgreSQL 9.0.
Может работать так:
-- DROP SCHEMA x CASCADE;
CREATE SCHEMA x;
CREATE TABLE x.my_func (func text PRIMARY KEY, def text);
INSERT INTO x.my_func VALUES('f'
, $$CREATE OR REPLACE FUNCTION f(int)
RETURNS int AS
'SELECT $1 * 100;'
LANGUAGE sql IMMUTABLE$$);
CREATE OR REPLACE FUNCTION x.f_create_func(text)
RETURNS void AS $x$
BEGIN
EXECUTE (SELECT def FROM x.my_func WHERE func = $1);
END;
$x$
LANGUAGE plpgsql;
Вызов:
select x.f_create_func('f');
SELECT f(3);
Вы можете отказаться от этой функции впоследствии.
В большинстве случаев вам следует просто создать вместо этого функции и покончить с ними.Используйте отдельные схемы, если у вас есть проблемы с несколькими версиями или привилегиями.
Для получения дополнительной информации о функциях, которые я использовал здесь, см. мой соответствующий ответ на dba.stackexchange.com .