2017-09-24 131 views
1

我需要創建一個函數,該函數返回SELECT查詢的結果。此SELECT查詢是在此函數內創建的幾個臨時表的聯接。有沒有什麼辦法可以創建這樣的功能?下面是一個例子(這是很簡單,在現實中也有與長的查詢多個臨時表):使用臨時表創建函數使用這些臨時表返回選擇查詢

CREATE OR REPLACE FUNCTION myfunction() RETURNS TABLE (column_a TEXT, column_b TEXT) AS $$ 
BEGIN 
CREATE TEMPORARY TABLE raw_data ON COMMIT DROP 
AS 
SELECT d.column_a, d2.column_b FROM dummy_data d JOIN dummy_data_2 d2 using (id); 

RETURN QUERY (select distinct column_a, column_b from raw_data limit 100); 
END; 
$$ 
LANGUAGE 'plpgsql' SECURITY DEFINER 

我得到錯誤:

[Error] Script lines: 1-19 ------------------------- 
ERROR: RETURN cannot have a parameter in function returning set; 
use RETURN NEXT at or near "QUERY"Position: 237 

我提前道歉是否有明顯的錯誤,我這是新的。

PSQL版本的PostgreSQL 8.2.15(Greenplum數據4.3.12.0構建1)

+0

有趣。你得到的錯誤是什麼? –

+0

我已經將你的代碼輸入到SQLFiddle中,並且有一些語法技巧可能會或可能不會與你的情況相關,它似乎通過檢查並返回預期結果http://sqlfiddle.com/#!15/874fa/1 –

+0

你忘了提供你的Postgres版本,這是必不可少的。 「似乎無法讓它運行」並不是我聽說過的錯誤消息。順便說一句,沒有「psql函數」。你的是一個plpgsql函數。最後:是什麼讓你覺得你需要臨時表?甚至一個功能? –

回答

1

最可能的錯誤,這可能在Postgres的提高:

ERROR: column "foo" specified more than once

含義,至少有一個包含在兩個表中的更多列名稱(idUSING子句摺疊爲一個實例)。這不會在容忍重複輸出列名的普通SQL SELECT中引發異常。但是你不能創建一個重名的表。

的問題也適用於Greenplum的(就像你以後申報),這是 Postgres的。它在2005年從PostgreSQL中分離出來並分別開發。目前的Postgres手冊幾乎不適用。看看Greenplum documentation

psql只是標準的PostgreSQL交互式終端程序。顯然你使用PostgreSQL 8.2.15附帶的那個,但是RDBMS仍然是Greenplum,而不是Postgres。

語法修復(Postgres的,就像你第一次標記,還是相關的):

CREATE OR REPLACE FUNCTION myfunction() 
    RETURNS TABLE (column_a text, column_b text) AS 
$func$ 
BEGIN 
    CREATE TEMPORARY TABLE raw_data ON COMMIT DROP AS 
    SELECT d.column_a, d2.column_b -- explicit SELECT list avoids duplicate column names 
    FROM dummy_data d 
    JOIN dummy_data_2 d2 using (id); 

    RETURN QUERY 
    SELECT DISTINCT column_a, column_b 
    FROM raw_data 
    LIMIT 100; 
END 
$func$ LANGUAGE plpgsql SECURITY DEFINER; 

的例子就不會需要一個臨時表 - 除非你的函數調用後訪問該臨時表在同一事務(ON COMMIT DROP)。否則,普通的SQL函數在各方面都會更好。語法Postgres的的Greenplum:

CREATE OR REPLACE FUNCTION myfunction(OUT column_a text, OUT column_b text) 
    RETURNS SETOF record AS 
$func$ 
    SELECT DISTINCT d.column_a, d2.column_b 
    FROM dummy_data d 
    JOIN dummy_data_2 d2 using (id) 
    LIMIT 100; 
$func$ LANGUAGE plpgsql SECURITY DEFINER; 

並非最不重要的it should also work for Greenplum

此功能的唯一剩餘原因是SECURITY DEFINER。否則,您可以使用簡單的SQL語句(可能是準備好的語句)。

RETURN QUERY被添加到2008年的版本8.3 PL/pgSQL中,有些年份之後是Greenplum的分支。或許可以解釋你的錯誤信息:

ERROR: RETURN cannot have a parameter in function returning set; 
use RETURN NEXT at or near "QUERY" Position: 237 

旁白:LIMIT沒有ORDER BY產生任意性的結果。我假定你知道這一點。


如果由於某種原因,你真正需要臨時表,不能升級到5.0 Greenplum的like A. Scherbaum suggested,你仍然可以使它在Greenplum的版本4.3.x工作(如在Postgres的8.2)。使用FOR循環與RETURN NEXT組合。
實例:

2

最新版本Greenplum數據(5.0)的基於PostgreSQL 8.3版本,及其支持的RETURN QUERY語法。剛剛測試您的功能:

PostgreSQL 8.4devel (Greenplum Database 5.0.0-beta.10+dev.726.gd4a707c762 build dev)