2

我正在 Postgres 中开发一个函数,旨在为查询的每条记录恢复一组函数中包含的检查结果的值。这些函数中只有一个会返回正确的值。这些函数有一个公共前缀“fn_condicao_”,并接收一个“my_table”类型的对象作为参数。

由于进行检查的函数数量未知,我决定查阅 Postgres 目录,从表中pg_catalog.pg_proc搜索前缀为“fn_condicao_”的函数并使用 EXECUTE 动态执行它们。

我的问题是如何为EXECUTE传递正确的形状参数。

create or replace function test_conditions()
returns void as 
$$
declare
    v_record my_table%rowtype;
    v_function pg_proc%rowtype;    
begin 
    set search_path = 'pg_catalog';

    for v_record in (select * from my_table where id in (1,2,3)) loop
        for v_function in (
            SELECT  p.proname
            FROM    pg_namespace n
            JOIN    pg_proc p
            ON      p.pronamespace = n.oid
            WHERE   n.nspname = 'operacional'
            and p.proname like ('fn_condition\\_%')
            order by p.proname) 
        loop
            --execute 'select ' || v_function.proname || '(' || v_record || ')';
        end loop;
    end loop;
end;
$$ 
language plpgsql;

如何v_record正确传递上述函数中的注释EXECUTE命令?

execute 'select ' || v_function.proname || '(' || v_record || ')';  -- ???

示例函数:

create or replace function fn_condition_1(p_record my_table)
returns bigint as 
$$
begin 
    if ($1.atributo1 > $1.atributo2) then
        return 1;
    end if;
    return null;
end;
$$ 
language plpgsql;
4

2 回答 2

2

我相信您的问题是execute您的函数中的命令正在尝试插入值,v_record该值本质上将其转换为参数的离散列表,而不是函数期望的本机行类型。

如果您愿意更改每个函数的参数类型,那可能是处理此问题的最简单方法。如果没有,那么您需要某种方法将本机行类型传递给动态函数调用。尽管看起来很糟糕,但我认为这样的事情会起作用:

create or replace function test_conditions()
returns void as 
$$
declare
    v_record my_table%rowtype;
    v_function pg_proc%rowtype;    
begin 
    set search_path = 'pg_catalog';

    for v_record in (select * from my_table where id in (1,2,3)) loop
        for v_function in (
            SELECT  p.proname
            FROM    pg_namespace n
            JOIN    pg_proc p
            ON      p.pronamespace = n.oid
            WHERE   n.nspname = 'operacional'
            and p.proname like ('fn_condition_%')
            order by p.proname) 
        loop
          execute '
            do $ZOOM$
              declare
                v_rec my_table%rowtype;
              begin
                select *
                into v_rec
                from my_table
                where id = ' || v_record.id || ';

                perform ' || func_name || '(v_rec);
              end;
            $ZOOM$
          ';
        end loop;
    end loop;
end;
$$ 

另外,我认为您需要将您的更改selectperform(如上)......要么这样做,要么执行select into.

于 2016-01-22T03:13:43.213 回答
0
于 2017-01-18T13:03:16.417 回答