2015-10-07 149 views
2

我在'on commit drop'選項中使用函數中的臨時表。我的問題是,在某些情況下,更多的全局函數可以調用第一個函數兩次,因此在提交之前調用兩次「create temp table」 - 所以我有正常的錯誤「relation [my_temp_table]已經存在」。退出函數時刪除臨時表

我在函數的末尾使用臨時表來返回其在「返回查詢」中的行,所以在離開函數之前我不能手動刪除表。

CREATE OR REPLACE FUNCTION my_function(_value text) 
RETURNS setof my_table AS $$ 
DECLARE 
    resultCount integer := 0; 
BEGIN 

    create temp table my_temp_table on commit drop as 
    select * 
    from my_table 
    where value = _value ; 

    select count(*) into resultCount from my_temp_table; 
    if (resultCount = 0) then 
     raise exception 'value not found'; 
     end if; 

    return query 
    select * from my_temp_table; 

END;$$ LANGUAGE plpgsql VOLATILE COST 100; 
ALTER FUNCTION my_function(text) OWNER TO postgres 

如果你想知道爲什麼我用一個臨時表,而不是MY_TABLE直接的方式,那是因爲我需要一個非常快速的響應和MY_TABLE是非常大的(幾十幾百萬行),所以這樣我可以要求它只有一次而不是三次(搜索,計數和返回)。

我找到了一個不使用臨時表和創建類型的解決方法,但my_table的結構會改變很多次,實際上我有幾十個「我的表」和有關「我的函數」,所以這是一種方法每次我的表格結構都會改變時,不要再寫所有的函數。

函數必須返回與它請求的表相同的結構。

如何在離開功能時放下桌子?還是有更好的解決方法?

回答

4

...在「返回查詢」返回其行,所以我無法手動刪除該表之前,我離開的功能。

其實你可以。你可以使用幾個RETURN QUERY。 手冊後:

當PL/pgSQL函數被聲明爲返回SETOF [...]的各個項目,返回通過RETURN NEXT或RETURN QUERY命令的序列被指定,然後,在最後RETURN指令不帶參數用來表示該功能已執行完畢

所以,你可以這樣做:

RETURN QUERY 
     SELECT * FROM my_temp_table; 
DROP TABLE my_temp_table; 
RETURN; 
+0

非常感謝這是完美的! –

+0

此代碼會引發錯誤。 –

2

你可以刪除該表以防萬一

... 
BEGIN 
    drop table if exists my_temp_table; 
    create temp table my_temp_table on commit drop as 
    .... 

但......其實你並不需要一個臨時表。試試這個代碼:

... 
    return query 
    select * 
    from my_table 
    where value = _value ; 

    if not found then 
     raise exception 'value not found'; 
    end if; 
... 
+0

我會用下面的最終「迴歸」,但我會definitly用「如果不是發現「!非常感謝 ! –

+0

@ThomasPerrin - 這真的不管回報聲明在哪裏。 Klin爲你提供了完整的功能,只需測試一下。 –

+0

是的,它的工作原理,謝謝 –