postgresql中带有临时表的存储函数

Posted

技术标签:

【中文标题】postgresql中带有临时表的存储函数【英文标题】:Stored function with temporary table in postgresql 【发布时间】:2011-11-28 12:48:53 【问题描述】:

我不熟悉在 postgresql 和一般情况下编写存储函数。我正在尝试使用输入参数编写 onw 并返回存储在临时表中的一组结果。 我在我的函数中执行以下操作。 1) 获取所有消费者的列表并将他们的 id 存储在临时表中。 2) 遍历特定表并从上述列表中检索与每个值对应的值并存储在临时表中。 3)返回临时表。

这是我自己尝试编写的函数,

create or replace function getPumps(status varchar) returns setof record as $$    (setof record?) 
DECLARE 
cons_id integer[]; 
i integer; 
temp table tmp_table;--Point B 
BEGIN 
select consumer_id into cons_id  from db_consumer_pump_details; 
 FOR i in select * from cons_id LOOP 
    select objectid,pump_id,pump_serial_id,repdate,pumpmake,db_consumer_pump_details.status,db_consumer.consumer_name,db_consumer.wenexa_id,db_consumer.rr_no into tmp_table  from db_consumer_pump_details inner join db_consumer on db_consumer.consumer_id=db_consumer_pump_details.consumer_id 
where db_consumer_pump_details.consumer_id=i and db_consumer_pump_details.status=$1--Point A 
order by db_consumer_pump_details.consumer_id,pump_id,createddate desc limit 2 
END LOOP; 
return tmp_table   
END; 
$$ 
LANGUAGE plpgsql; 

但是我不确定我的方法以及我是否在上面代码中标记的 A 点和 B 点。并且在尝试创建临时表时遇到大量错误。

EDIT:让函数工作,但是当我尝试运行函数时出现以下错误。

   ERROR:  array value must start with "" or dimension information

这是我修改后的函数。

 create temp table tmp_table(objectid integer,pump_id integer,pump_serial_id varchar(50),repdate timestamp with time zone,pumpmake varchar(50),status varchar(2),consumer_name varchar(50),wenexa_id varchar(50),rr_no varchar(25));

  select consumer_id into cons_id  from db_consumer_pump_details;
   FOR i in select * from cons_id LOOP
insert into tmp_table 
select objectid,pump_id,pump_serial_id,repdate,pumpmake,db_consumer_pump_details.status,db_consumer.consumer_name,db_consumer.wenexa_id,db_consumer.rr_no   from db_consumer_pump_details inner join db_consumer on db_consumer.consumer_id=db_consumer_pump_details.consumer_id where db_consumer_pump_details.consumer_id=i and db_consumer_pump_details.status=$1
order by db_consumer_pump_details.consumer_id,pump_id,createddate desc limit 2;
 END LOOP;
 return query (select * from tmp_table);
 drop table tmp_table;
  END;
  $$
  LANGUAGE plpgsql;

【问题讨论】:

如果您愿意,可以返回行集而不是临时表 @triclosan,你能举个例子吗? create function GetEmployees() returns setof employee as 'select * from employee;' language 'sql'; 来自此维基:wiki.postgresql.org/wiki/… 【参考方案1】:

AFAIK 不能在 postgres 中将表声明为变量。你可以做的是在你的函数体中创建一个并彻底使用它(甚至在函数之外)。请注意,因为临时表在会话结束或提交之前不会被删除。

要走的路是使用RETURN NEXT or RETURN QUERY

至于函数结果类型,我一直觉得 RETURNS TABLE 更具可读性。

编辑: 您的 cons_id 数组是不必要的,只需迭代 select 返回的值。 您也可以在单个函数中包含多个返回查询语句,以将查询结果附加到函数返回的结果中。

在你的情况下:

CREATE OR REPLACE FUNCTION getPumps(status varchar) 
RETURNS TABLE (objectid INTEGER,pump_id INTEGER,pump_serial_id INTEGER....)   
AS 
$$
BEGIN 
    FOR i in SELECT consumer_id FROM db_consumer_pump_details LOOP

    RETURN QUERY(
        SELECT objectid,pump_id,pump_serial_id,repdate,pumpmake,db_consumer_pump_details.status,db_consumer.consumer_name,db_consumer.wenexa_id,db_consumer.rr_no FROM db_consumer_pump_details INNER JOIN db_consumer ON db_consumer.consumer_id=db_consumer_pump_details.consumer_id 
        WHERE db_consumer_pump_details.consumer_id=i AND db_consumer_pump_details.status=$1
        ORDER BY db_consumer_pump_details.consumer_id,pump_id,createddate DESC LIMIT 2 
    );
    END LOOP;
END;
$$

edit2:

您可能想看看this groupwise-k-maximum 问题的解决方案,因为这正是您要处理的问题。

【讨论】:

你看过我发布的编辑吗? ,谢谢!!稍加修改就可以很好地工作,一个不相关的问题,有没有办法获取将从上述查询返回的记录总数?显然 count(*) 不起作用。【参考方案2】:

只返回一个表(或查询)可能更容易

CREATE FUNCTION extended_sales(p_itemno int)
RETURNS TABLE(quantity int, total numeric) AS $$
BEGIN
  RETURN QUERY SELECT quantity, quantity * price FROM sales
             WHERE itemno = p_itemno;
END;
$$ LANGUAGE plpgsql;

(复制自postgresql docs)

【讨论】:

以上是关于postgresql中带有临时表的存储函数的主要内容,如果未能解决你的问题,请参考以下文章

通过存储在 Postgresql 中带有特殊字符的变量名中来删除约束

视图触发器事务存储过程函数

mysql七:视图触发器事务存储过程函数

mysql之视图触发器事务存储过程函数

表变量

Mysql:视图触发器事务存储过程函数