无法在Postgres函数中删除临时表:“在此会话中被活动查询使用”

时间:2015-07-02 15:32:25

标签: postgresql plpgsql common-table-expression

现在需要一个名为waypoints的表格,并按照功能正文进行操作。

drop function if exists everything(waypoints);
create function everything(waypoints) RETURNS TABLE(node int, xy text[]) as $$
BEGIN
    drop table if exists bbox;
    create temporary table bbox(...);
    insert into bbox
        select ... from waypoints;

    drop table if exists b_spaces;
    create temporary table b_spaces(
        ...
    );
    insert into b_spaces
        select ...

    drop table if exists b_graph; -- Line the error flags.
    create temporary table b_graph(
       ...
    );
    insert into b_graph
        select ...

    drop table if exists local_green;
    create temporary table local_green(
        ...
    );
    insert into local_green 
        ...

    with aug_temp as (
        select ...
    )
    insert into b_graph(source, target, cost) (
        (select ... from aug_temp) 
        UNION 
        (select ... from aug_temp)
    );

    return query
        with 
        results as (
            select id1, ... from b_graph -- The relation being complained about.
        ),
        pkg as (
            select loc, ...
        )
        select id1, array_agg(loc) 
        from pkg
        group by id1;
    return;
END;
$$ LANGUAGE plpgsql;

这会返回cannot DROP TABLE b_graph because it is being used by active queries in this session

如何解决此问题?

1 个答案:

答案 0 :(得分:1)

错误信息非常明显,您无法在使用临时表时删除它。

您可以通过添加ON COMMIT DROP

来避免此问题

然而,这可能更简单。如果你不需要 所有那些临时表(我怀疑),你可以用CTE替换它们(或者大多数可能用更便宜的子查询替换它们)并简化为一个大问题。可以是plpgsql,也可以只是SQL:

CREATE FUNCTION everything(waypoints)
  RETURNS TABLE(node int, xy text[]) AS
$func$
   WITH bbox      AS (SELECT ... FROM waypoints)  -- not the fct. parameter!
    , b_spaces    AS (SELECT ... )
    , b_graph     AS (SELECT ... )
    , local_green AS (SELECT ... )
    , aug_temp    AS (SELECT ... )
    , b_graph2(source, target, cost) AS (
        SELECT ... FROM b_graph
        UNION ALL  -- guessing you really want UNION ALL
        SELECT ... FROM aug_temp
        UNION ALL 
        SELECT ... FROM aug_temp
       )
    , results     AS (SELECT id1, ... FROM b_graph2)
    , pkg         AS (SELECT loc, ... )
   SELECT id1, array_agg(loc) 
   FROM   pkg
   GROUP  BY id1
$func$ LANGUAGE sql;

视图只是存储查询("食谱"),而不是实际结果值("汤")。

使用CTE而不是创建临时表通常更便宜 查询中的派生表,按其典型整体性能排序(涉及索引的特殊情况的例外情况)。从慢到快:

CREATE TABLE
CREATE UNLOGGED TABLE
CREATE TEMP TABLE
CTE
subquery

UNION会尝试折叠重复的行。通常,人们真的想要UNION ALL,它只是追加行。更快,不会试图删除欺骗。