2015-07-02 36 views
0

預計現在將生成一個名爲waypoints的表,並按照函數體進行操作。無法在Postgres函數中刪除臨時表:「正在由此會話中的活動查詢使用」

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

如何去糾正這個問題?

+0

爲什麼使用臨時表?臨時表是否應該在函數外引用?另外:你的Postgres版本總是*必要的細節的一部分。 –

+0

@ErwinBrandstetter因爲它們都是獲得我最終結果的中間體。我使用的是9.3,我將其添加到問題中。 – Louis93

+0

另外,從CTE讀取和寫入的速度與從表讀取和寫入一樣快嗎?因爲當我提出意見時,每次訪問視圖時,視圖都會重新計算。 – Louis93

回答

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,它只是附加行。速度更快,並且不會嘗試去除模糊。

+0

真棒@Erwin。我在那裏看到沒有返回,它們沒有必要嗎? – Louis93

+0

@ Louis93:RETURN在plpgsql中是必需的,我轉換到'LANGUAGE sql'作爲簡化的例子。你也可以使用plpgsql。 –

+0

你好 - 希望這是最後的阻擋者。所以在'results' CTE中,我調用了一個像這樣的函數:'pgr_ksp('select * FROM b_graph')'來形成結果' 但是,我回過頭來看:'relation「b_graph」不存在'。 b_graph是否必須是表格? – Louis93

相關問題