2014-04-01 62 views
3

我們能否在函數中使用CASE條件表達式中的SELECT語句?
我試過以下功能來完成上述任務。PostgreSQL:如何在函數中使用CASE表達式中的SELECT語句?

例如:我有一個函數用於顯示包含一些行的表。

create or replace function test(n integer) 
returns table (name text,city text) as 
$body$ 
begin 
    case n when 1 then 
    select * from table1 

    when 2 then 
    select * from table2 

    when 3 then 
    select * from view1 

    end; 
end; 
$body$ 
language plpgsql; 

--Calling功能

select * from test(1); 
/*have to show details of table1*/ 

select * from test(2); 
/*have to show details of table2*/ 

select * from test(3); 
/*have to display details of view1*/ 

回答

2

其實,有一個plpgsql CASE statement,不要與SQL CASE expression混淆:

CREATE OR REPLACE function test(n integer) 
    RETURNS TABLE (name text, city text) AS 
$func$ 
BEGIN 

CASE n 
WHEN 1 THEN 
    RETURN QUERY SELECT t.name, t.city FROM table1 t; 
WHEN 2 THEN 
    RETURN QUERY SELECT t.foo, t.bar FROM table2 t; 
WHEN 3 THEN 
    RETURN QUERY SELECT t.bar, t.bamm FROM view1 t; 
END CASE; 

END 
$func$ LANGUAGE plpgsql; 
  • 如果聲明的功能RETURNS TABLE (name text, city text),那麼你的SELECT語句應該有匹配的類型列的列表。
    如果另一方面您想要SELECT *,則相應地將函數聲明爲RETURNS SETOF table1

  • 當爲返回類型命名列時,這些變量在函數體中可見。請務必對與名稱相沖突的列名進行表格限定。所以t.name而不是隻有name

  • 函數內查詢的列名在外面不可見。只有聲明的返回類型。所以名稱不必匹配,只是數據類型。

無論哪種方式,我建議把事情簡單化:

CREATE OR REPLACE function test(n integer) 
    RETURNS SETOF table1 AS 
$func$ 

SELECT * FROM table1 t WHERE n = 1 
UNION ALL 
SELECT * FROM table2 t WHERE n = 2 
UNION ALL 
SELECT * FROM view1 t WHERE n = 3; 

$func$ LANGUAGE sql; 

相同的結果。一樣快。 SQL或PL/pgSQL函數是一個口味和其他一些細節的問題。 PL/pgSQL對於獨立呼叫可能更快。 SQL可以更容易嵌套。

+0

非常感謝。這裏有點混亂。 UNION ALL需要所有的列都是相同的,但是當我想顯示一個具有不同列的表時,可以在這裏嗎? – Meem

+0

@Meem:*列號*和*日期類型*必須匹配(或者在緊密相關的類型之間可以自動轉換)。或者你必須填寫常量並施放以使它們匹配。功能也是如此。對於'UNION'查詢,只使用第一條腿的名字,'UNION'查詢後面的名字不是無關緊要的。對於函數,只使用聲明的'RETURN'類型的名稱。 –

+0

哦!沒關係。 – Meem

2

爲此,您需要一個IF聲明和RETURN QUERY,例如

create or replace function test(n integer) 
returns table (name text,city text) as 
$body$ 
begin 
    IF n = 1 THEN 
     RETURN QUERY select * from table1; 
    ELIF n = 2 THEN 
     RETURN QUERY select * from table2; 
    ELIF n = 3 THEN 
     RETURN QUERY select * from view1; 
    END IF; 
end; 
$body$ 
language plpgsql; 

雖然這是一件非常奇怪的事情。

+0

還有一個問題,如果我想顯示從上面的返回表具有不同列名的table2行,那麼如何顯示它。 – Meem

+0

如果您想要提出其他問題,請發佈新問題;堆棧溢出試圖保持每個問題的一個主要主題。 –

+0

好吧,我會照顧它的。 – Meem