函数可以作为匿名函数直接存储在列中作为其值吗?
我想说我希望这个功能存储在列中。 示例(伪代码):
表my_table:pk(int),my_function(func)
func(x){return x * 100}
后来用它作为:
select
t.my_function(some_input) AS output
from
my_table as t
where t.pk = 1999
每个pk的功能可能会有所不同。
答案 0 :(得分:6)
你的标题除了你的例子之外还有别的东西。
我将为两者提供解决方案。
您必须考虑到结果类型可能会有所不同。我使用多态类型。
-- 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)
可以动态创建函数然后使用它们。但是,您无法使用纯SQL执行此操作。您必须使用另一个function来执行此操作,或至少使用PostgreSQL 9.0中引入的anonymous code block (DO statement)。
它可以像这样工作:
-- 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);
您可能希望之后删除该功能。
在大多数情况下,您应该只创建函数并完成它。如果您遇到多个版本或特权问题,请使用单独的模式。
有关我在此处使用的功能的详细信息,请参阅my related answer on dba.stackexchange.com。