Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 在执行时传递ROWTYPE参数_Sql_Postgresql_Plpgsql_Postgresql 8.3 - Fatal编程技术网

Sql 在执行时传递ROWTYPE参数

Sql 在执行时传递ROWTYPE参数,sql,postgresql,plpgsql,postgresql-8.3,Sql,Postgresql,Plpgsql,Postgresql 8.3,我正在Postgres中开发一个函数,其目的是为查询的每个记录恢复包含在一组函数中的检查结果的值。这些函数中只有一个返回正确的值。这些函数有一个comun前缀“fn\u condico\u”,并将“my\u table”类型的对象作为参数接收 由于进行检查的函数数量未知,我决定参考Postgres目录,从表pg_catalog.pg_proc中搜索前缀为'fn_condico_'的函数,并使用execute动态执行它们 我的问题是如何为传递正确的形状参数 如何在上述函数中的注释的EXECUTE命

我正在Postgres中开发一个函数,其目的是为查询的每个记录恢复包含在一组函数中的检查结果的值。这些函数中只有一个返回正确的值。这些函数有一个comun前缀“fn\u condico\u”,并将“my\u table”类型的对象作为参数接收

由于进行检查的函数数量未知,我决定参考Postgres目录,从表
pg_catalog.pg_proc
中搜索前缀为'fn_condico_'的函数,并使用execute动态执行它们

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

如何在上述函数中的注释的
EXECUTE
命令中正确传递
v_记录

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;

我相信您的问题在于函数中的
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;
$$ 

此外,我认为您需要将
选择
更改为
执行
(如上所述)。。。要么这样做,要么做一个
选择进入

这个问题在中得到了回答。因此,我想与大家分享这项决议


数据库管理员回答 在Postgres 8.4或更高版本中,您可以使用
EXECUTE
USING
子句安全有效地传递值。这在您的8.3版中还不可用。在您的版本中,它可以像这样工作:

CREATE OR REPLACE FUNCTION test_conditions()
  RETURNS SETOF bigint AS
$func$
DECLARE
   _rec    record;
   _func   text;
   _result bigint;
BEGIN
   FOR _func in
      SELECT  p.proname
      FROM    pg_catalog.pg_namespace n
      JOIN    pg_catalog.pg_proc      p ON p.pronamespace = n.oid
      WHERE   n.nspname = 'operacional'
      AND     p.proname LIKE E'fn\\_condition\\_%'  -- no parens, proper string
      ORDER   BY p.proname  -- no parens
   LOOP
      FOR _rec in
         SELECT * FROM my_table WHERE id IN (1,2,3)  -- no parens needed
      LOOP
         EXECUTE 'SELECT ' || quote_ident(_func) || '(' || quote_literal(_rec) || ')'
         INTO _result;
         RETURN NEXT _result;
      END LOOP;
   END LOOP;
END
$func$  LANGUAGE plpgsql SET search_path = 'public';
电话:

  • 如果使用
    set search_path='pg_catalog'public
    模式中的表不再可见。全局设置搜索路径将是一个非常糟糕的主意。效果在设置期间保持不变。您可以使用
    SET LOCAL
    将其包含到事务中,但这仍然是一个坏主意。相反,如果确实需要,请仅设置函数的环境,如演示的那样。
    有关Postgres中搜索路径的详细信息:

  • 仅仅执行一个
    SELECT
    ,而不分配或返回结果是没有意义的。使用
    EXECUTE
    INTO
    子句,然后
    returnnext
    。在现代Postgres中,您可以用
    返回查询执行
    替换内部循环

  • 在构建动态查询字符串时,使用
    quote_ident()
    quote_literal()
    正确转义标识符和文字。在现代Postgres中,您将使用
    format()

  • 将整行强制转换为它的字符串表示、转义和强制转换不是很有效。此替代方法必须重复从表中读取数据,但在其他情况下更干净(行直接作为值传递):

示例函数 您还可以使用此SQL函数从根本上简化示例函数:

CREATE OR REPLACE FUNCTION fn_condition_1(p_record my_table)
  RETURNS bigint AS
$func$
   SELECT CASE WHEN $1.atributo1 > $1.atributo2 THEN bigint '1' END
$func$  LANGUAGE sql;

看起来您正试图用过程替换关系。您试图解决的真正问题是什么?我需要以友好的方式运行一组函数。这个过程是一个更大的过程的一部分,更复杂,不能用关系范式进行。这些函数可以随着时间的推移而增长,这就是为什么我尝试动态执行它们,以便添加新函数不会影响这个更大的过程@如果我错了,Clodoaldonet会纠正我,但我猜“do”命令在Postgres 8.3中不起作用@Hambone@GeisonSantos你可能是对的。不幸的是,我进入博士后的洗礼是9.2分。如果有人不在9.5上,我会郑重建议他们放弃一切并升级。单是改进后的排序就值得入场费。
SELECT * FROM test_conditions();
  FOR i IN
     VALUES (1), (2), (3)
  LOOP
     EXECUTE 'SELECT ' || quote_ident(_func) || '(t) FROM my_table t WHERE id = ' || i
     INTO _result;
     RETURN NEXT _result;
  END LOOP;
CREATE OR REPLACE FUNCTION fn_condition_1(p_record my_table)
  RETURNS bigint AS
$func$
   SELECT CASE WHEN $1.atributo1 > $1.atributo2 THEN bigint '1' END
$func$  LANGUAGE sql;