2012-02-03 20 views
1

我已經找到了答案,但沒有找到答案。在postgres中使用選定的值作爲表名

,所以我有一個表types

CREATE TABLE types 
(
    type_id serial NOT NULL, 
    type_name character varying, 
    CONSTRAINT un_type_name UNIQUE (type_name) 
) 

持有類型名,可以說users - 這是對應的表users的名稱。這個設計可能有點難看,但它是爲了讓用戶創建自己的類型而設計的。 (有沒有更好的方式來acheve這一點?)

現在我想這樣一個執行一個查詢:

select type_name, (select count(*) from ???) from types 

讓每種類型的對象的所有類型的名稱和數量的清單。

可以這樣做嗎?

回答

3

我沒有足夠的信息,但我懷疑的東西是關閉與您的設計。你不應該爲每種類型需要一張額外的桌子。

即便如此,您想要做的事情也無法完成 - 在純SQL中。 它可以用PLPGSQL函數來完成執行動態SQL,雖然:

CREATE OR REPLACE FUNCTION f_type_ct() 
    RETURNS TABLE (type_name text, ct bigint) AS 
$BODY$ 
DECLARE 
    tbl  text; 
BEGIN 
    FOR tbl IN SELECT t.type_name FROM types t ORDER BY t.type_name 
    LOOP 
     RETURN QUERY EXECUTE 
     'SELECT $1, count(*) FROM ' || tbl::regclass 
     USING tbl; 
    END LOOP; 
END; 
$BODY$ 
    LANGUAGE plpgsql; 

電話:

SELECT * FROM f_type_ct(); 

你需要學習的大部分chapter about plpgsql in the manual的理解什麼是怎麼回事。

一個特別提示:cast to regclass是針對SQLi的一種安全措施。您也可以使用更一般適用的quote_ident(),但那不能正確處理符合模式限定的表名,而將其轉換爲regclass。它也只接受主叫用戶可見的表名。

+0

太棒了!我明白這個功能發生了什麼:)我想我可以做到這一點,沒有功能。 **爲了性能的原因**需要額外的表格 - 小表格可以更有效地索引afaik – k102 2012-02-03 09:06:31

+0

@ k102:順便說一下,索引在大(或巨大)表格中工作得很好。這就是他們的目標。對於小表,順序讀取通常比使用索引更快。 – 2012-08-24 23:19:41

4

你不能直接從SQL做

您可以使用PLPGSQL功能和動態SQL

CREATE OR REPLACE FUNCTION tables_count(OUT type_name character varying, OUT rows bigint) 
RETURNS SETOF record AS $$ 
BEGIN 
    FOR tables_count.type_name IN SELECT types.type_name FROM types 
    LOOP 
    EXECUTE 'SELECT COUNT(*) FROM ' || quote_ident(tables_count.type_name) INTO tables_count.rows; 
    RETURN NEXT; 
    END LOOP; 
    RETURN; 
END; 
$$ LANGUAGE plpgsql; 

SELECT * FROM tables_count(); 
+0

哈,帕維爾,你偷了我的雷!沒有期待別人回答這麼快。 :)顯然,我喜歡你的解決方案。你可以從我的想法中得知這一點。兩件小事:你在聲明中遺漏了一個'OUT',並且'type_name'被聲明爲'character varying',它將用你聲明的OUT類型爲'text'的參數產生一個異常。我修正了兩個。 – 2012-02-03 09:06:49

+0

謝謝!我知道(或者以爲我知道)我可以在plpgsql中做到這一點,我只是覺得如果沒有它,怎麼辦呢 – k102 2012-02-03 09:08:26

+0

謝謝修復Erwin :) – 2012-02-03 20:01:06

相關問題