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
Postgresql 如何在postgres中执行存储过程的字符串结果_Postgresql_Stored Procedures_Plpgsql_Dynamic Sql - Fatal编程技术网

Postgresql 如何在postgres中执行存储过程的字符串结果

Postgresql 如何在postgres中执行存储过程的字符串结果,postgresql,stored-procedures,plpgsql,dynamic-sql,Postgresql,Stored Procedures,Plpgsql,Dynamic Sql,我创建了以下存储过程,它基本上接收表名和前缀。然后,该函数将查找共享此前缀的所有列,并将“select”查询命令“myoneliner”作为输出返回。 详情如下: CREATE OR REPLACE FUNCTION mytext (mytable text, myprefix text) RETURNS text AS $myoneliner$ declare myoneliner text; BEGIN SELECT 'SELECT ' || substr(cols,2,len

我创建了以下存储过程,它基本上接收表名和前缀。然后,该函数将查找共享此前缀的所有列,并将“select”查询命令“myoneliner”作为输出返回。 详情如下:

CREATE OR REPLACE FUNCTION mytext (mytable text, myprefix text)
RETURNS text AS $myoneliner$
declare
    myoneliner text;
BEGIN
   SELECT 'SELECT ' || substr(cols,2,length(cols)-2) ||' FROM '||mytable 
   INTO myoneliner  
     FROM (
        SELECT array(
           SELECT DISTINCT quote_ident(column_name::text)
           FROM   information_schema.columns
           WHERE  table_name = mytable
           AND    column_name LIKE myprefix||'%'
           order by quote_ident             
      )::text cols 
     ) sub;
   RETURN myoneliner;
END;
$myoneliner$ LANGUAGE plpgsql;
电话:

运行此存储过程及其后面的“select”后,我在数据输出窗口中获得以下输出,所有输出都位于一个单元格中,名为mytext:

'SELECT enrich_d_dkj_p_k27ac,enrich_lr_dkj_p_k27ac,enrich_r_dkj_p_k27ac
 FROM dkj_p_k27ac'
我希望基本上能够将收到的输出命令行作为输出并执行它。换句话说,我希望能够执行存储过程的输出。 我怎样才能做到

我尝试了以下方法:

CREATE OR REPLACE FUNCTION mytext (mytable text, myprefix text)
RETURNS SETOF RECORD AS $$
declare
        smalltext text;
    myoneliner text;
BEGIN
   SELECT 'SELECT ' || substr(cols,2,length(cols)-2) ||' FROM '||mytable 
   INTO myoneliner  
     FROM (
        SELECT array(
           SELECT DISTINCT quote_ident(column_name::text)
           FROM   information_schema.columns
           WHERE  table_name = mytable
           AND    column_name LIKE myprefix||'%'
           order by quote_ident             
      )::text cols 
     ) sub;

   smalltext=lower(myoneliner);
   raise notice '%','my additional text '||smalltext;
   RETURN QUERY EXECUTE smalltext;
END;
$$ LANGUAGE plpgsql;
调用函数:

SELECT * from mytext('dkj_p_k27ac','enri');
但我收到以下错误消息,请您建议我应该更改什么以使其执行

ERROR:  a column definition list is required for functions returning "record"
LINE 26: SELECT * from mytext('dkj_p_k27ac','enri');

********** Error **********

ERROR: a column definition list is required for functions returning "record"
SQL state: 42601
Character: 728

您的第一个问题是通过使用动态SQL和Craig建议的EXECUTE解决的。 但兔子洞更深:

CREATE OR REPLACE FUNCTION myresult(mytable text, myprefix text)
  RETURNS SETOF RECORD AS
$func$
DECLARE
   smalltext  text;
   myoneliner text;
BEGIN
   SELECT INTO myoneliner  
          'SELECT '
        || string_agg(quote_ident(column_name::text), ',' ORDER BY column_name)
        || ' FROM ' || quote_ident(mytable)
   FROM   information_schema.columns
   WHERE  table_name = mytable
   AND    column_name LIKE myprefix||'%'
   AND    table_schema = 'public';  -- schema name; might be another param

   smalltext := lower(myoneliner);  -- nonsense
   RAISE NOTICE 'My additional text: %', myoneliner;

   RETURN QUERY EXECUTE myoneliner;
END
$func$ LANGUAGE plpgsql;
但您不知道返回列的编号、可选名称和数据类型,在函数创建时甚至在调用时都不知道。不可能在一个电话里就做到这一点。您需要对数据库进行两个单独的查询

您可以使用使用多态类型的函数动态返回任何给定表的所有列,因为整个表都有一个定义良好的类型。相关答案的最后一章:


返回查询执行。但是,您的过程必须声明为返回记录集,然后调用者必须枚举调用中的列,这使得它没有什么用处。或者,您可以打开一个游标并返回REFCURSOR,然后调用者可以从游标中获取结果-但在这种情况下,您不能将结果作为子查询等的一部分使用,只能将其流式传输到客户端应用程序。这看起来像是的一个实例。我质疑这个设计。使用hstore或json列怎么样?您需要从我的_函数中调用select*过程…@Roy我就是这么说的-您必须识别查询中的列,因此它不会给您带来太多好处。我说过,调用方必须枚举调用中的列。您正试图做一些系统确实不擅长的事情,或者是专门为这些事情而设计的。@Roy有关记录集的信息,请参阅;对于大多数客户端,它们可以在结果集信息之前发送。然而,PostgreSQL的设计目前不允许其结果类型在规划期间未知且仅在执行时确定的查询,因此PostgreSQL无法做到这一点。此外,虽然需要两个单独的查询,但这并不一定意味着两次调用DB API的函数调用,或者两次往返。您可以执行类似于SELECT prepare_cursor'cursorname'的操作;从cursorname获取所有数据;在复合语句中。大多数客户机驱动程序都会处理这个问题。@CraigRinger:同样,您可以将临时表foo创建为。。。;在动态语句中,选择*FROM foo;在下一个查询中。可以是到服务器的一次往返,但可以是两个单独的查询。正如我所建议的,我澄清了问题,因为电话太模糊了。嗨@Erwin Brandstetter,非常感谢您的回复。信息量大,教育性强。我已经在我的问题中添加了一个新的部分-请参见上面我的第二次尝试。我基本上想知道是否可以创建第二个函数来接收myresult函数的文本输出,它基本上是一个SQL查询行,并且能够使用它来执行查询。我非常感谢你的帮助。这背后的动机是避免我在收到myresult输出后当前执行的复制/粘贴步骤。谢谢!请恢复对问题的编辑,并改为开始一个新问题。这些信息是为公众提供的,公众很难理解。您始终可以链接到此链接以了解上下文。
CREATE OR REPLACE FUNCTION myresult(mytable text, myprefix text)
  RETURNS SETOF RECORD AS
$func$
DECLARE
   smalltext  text;
   myoneliner text;
BEGIN
   SELECT INTO myoneliner  
          'SELECT '
        || string_agg(quote_ident(column_name::text), ',' ORDER BY column_name)
        || ' FROM ' || quote_ident(mytable)
   FROM   information_schema.columns
   WHERE  table_name = mytable
   AND    column_name LIKE myprefix||'%'
   AND    table_schema = 'public';  -- schema name; might be another param

   smalltext := lower(myoneliner);  -- nonsense
   RAISE NOTICE 'My additional text: %', myoneliner;

   RETURN QUERY EXECUTE myoneliner;
END
$func$ LANGUAGE plpgsql;
SELECT *
FROM   myresult('dkj_p_k27ac','enri') AS f (
  enrich_d_dkj_p_k27ac text  -- replace with actual column types
, enrich_lr_dkj_p_k27ac text
, enrich_r_dkj_p_k27ac text);