PostgreSQL:将函数作为值存储在列中

PostgreSQL:将函数作为值存储在列中,postgresql,dynamic-sql,Postgresql,Dynamic Sql,函数是否可以作为匿名函数直接存储在列中作为其值 假设我希望这个函数存储在列中。 示例(伪代码): 表my_表:pk(int),my_函数(func) func(x){返回x*100} 然后将其用作: select t.my_function(some_input) AS output from my_table as t where t.pk = 1999 每个pk的函数可能不同。您的标题要求的不是您的示例 必须先创建函数,然后才能调用它。(标题) 必须对表达式进行计算。

函数是否可以作为匿名函数直接存储在列中作为其值

假设我希望这个函数存储在列中。 示例(伪代码):

表my_表:pk(int),my_函数(func)

func(x){返回x*100}

然后将其用作:

select 
    t.my_function(some_input) AS output
from 
    my_table as t 
where t.pk = 1999

每个pk的函数可能不同。

您的标题要求的不是您的示例

  • 必须先创建函数,然后才能调用它。(标题)
  • 必须对表达式进行计算。你需要一个元函数。(示例)
  • 我将介绍这两种方法的解决方案

    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;
    
    电话:

    2.动态创建和使用函数 可以动态创建函数,然后使用它们。但是,使用普通SQL无法做到这一点。您必须使用另一个或至少一个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;
    
    电话:

    之后可能需要删除该函数

    在大多数情况下,您应该只创建函数,然后用它来完成。如果多个版本或权限有问题,请使用单独的架构


    有关我在此处使用的功能的更多信息,请参见。

    您可能是指
    my_function()
    一些实际的\u架构。my_function()
    而不是
    t。my_function()
    ,因为
    t
    是表别名。只要我们没有尝试那种疯狂,那么只要函数输出一个非设置的、非记录的值(即它不输出一行或一个表),那么是的,应该可以。不,听起来像是没有。my_function()正是他想要的。基本上,DB相当于函数指针或clousure。是的,我的意思是类似闭包的东西。谢谢你Erwin提供了这个例子。我怀疑我所问的可能不起作用,所以这个或类似的问题是计划B。您如何在
    x.f_eval
    中分配返回数据类型?我看到您将
    \u键入anyelement
    作为第二个参数;但是,我不知道它是如何在函数定义中使用的。忽略上面的注释。。。详情见
    -- 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);