Postgres:函数中的临时表是持久的。为什么呢?

时间:2015-11-20 13:53:10

标签: sql postgresql postgresql-9.3 temp-tables sql-function

我在postgresql数据库中有以下功能:

CREATE OR REPLACE FUNCTION get_unused_part_ids()
  RETURNS integer[] AS
$BODY$
DECLARE
  part_ids integer ARRAY;
BEGIN
  create temporary table tmp_parts
      as
  select vendor_id, part_number, max(price) as max_price
    from refinery_akouo_parts
   where retired = false
   group by vendor_id, part_number
  having min(price) < max(price);

  -- do some work etc etc

  -- simulate ids being returned
  part_ids = '{1,2,3,4}';
  return part_ids;

END;
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;
ALTER FUNCTION get_unused_part_ids()
  OWNER TO postgres;

这会编译,但是当我运行时:

select get_unused_part_ids();

临时表tmp_parts仍然存在。之后我可以选择它。原谅我,因为我习惯了t-sql / MSSQL的特定功能。这不是MSSQL的情况。我做错了什么?

3 个答案:

答案 0 :(得分:3)

manual之后

  

临时表会在会话结束时自动删除,或者可选地在当前事务结束时删除(参见下面的ON COMMIT)

断开连接后会话结束。不是在事务提交之后。因此,默认行为是保留临时表,直到您的连接仍然打开。您必须添加ON COMMIT DROP;才能实现所需的行为:

create temporary table tmp_parts on commit drop
      as
  select vendor_id, part_number, max(price) as max_price
    from refinery_akouo_parts
   where retired = false
   group by vendor_id, part_number
  having min(price) < max(price)
on commit drop;

答案 1 :(得分:3)

该表仅在会话结束时删除。您需要指定要删除的ON COMMIT选项,它将在事务结束时删除该表。

  create temporary table tmp_parts 
  on commit drop
      as
  select vendor_id, part_number, max(price) as max_price
    from refinery_akouo_parts
   where retired = false
   group by vendor_id, part_number
  having min(price) < max(price);

答案 2 :(得分:1)

在两个数据库中对临时表的处理方式不同。在SQL Server中,它们将在创建它们的存储过程的末尾被删除。

在Postgres中,临时表被分配给会话(或事务),如documentation中所述:

  

如果指定,则将表创建为临时表。临时   表会在会话结束时自动删除,或者   可选地在当前事务结束时(请参阅ON COMMIT   下面)。现有的具有相同名称的永久表不可见   临时表存在时的当前会话,除非它们   使用模式限定名称引用。在a上创建的任何索引   临时表也是自动临时的。

这个概念介于SQL Server中的常规临时表和全局临时表之间(全局临时表以##开头)。