2012-02-03 15 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には良い方法はありますか?)

は今、私はこの1つのようなクエリを実行したい:

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

は、各タイプのオブジェクトのすべての種類の名前と数のリストを取得します。

これはできますか?

答えて

3

plpgsqlが機能と動的SQLを使用することができますが、私は何かがあなたのデザインでオフになっていることを疑うん。すべてのタイプに余分なテーブルは必要ありません。

可能であれば、あなたがしたいことは、純粋なSQLで行うことはできません。 これは、しかし、動的SQLを実行plpgsqlが機能して行うことができます。

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のほとんどを勉強する必要があります。

特別なヒントの1つ:cast to regclassは、SQLiに対する保護手段です。より一般的に適用可能なquote_ident()を使用することもできますが、スキーマ修飾テーブル名は正しく処理されません。一方、キャストはregclassになります。また、呼び出し元のユーザーに表示される表名のみを受け入れます。

+0

素晴らしい!私はこの関数で何が起こっているのか理解しています:)私は関数なしでこれを行うことができると思いました。 **パフォーマンス上の理由から、**すべてのタイプの追加テーブルが必要です - 小さなテーブルはより効果的にインデックス化できますafaik – k102

+0

@ k102:インデックスは大きな(または巨大な)テーブルでうまく動作します。それが彼らのために作られたものです。小さなテーブルでは、索引をまったく使用するよりも順次読み取りが高速になることがよくあります。 –

4

あなたは、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

ハ、パベル、あなたは私の雷を盗んだ!すぐに他の誰かが答えるとは期待していませんでした。 :)明らかに、私はあなたのソリューションが好きです。あなたは私が思いついたことからそれを知ることができます。 2つの小さなこと:あなたは宣言で 'OUT'が欠けていて、' type_name'は 'text varying'で宣言されたOUTパラメータで例外を発生させる' character varying'と宣言されています。私は両方を修正した。 –

+0

ありがとう!私は知っていた(または私が知っていると思った)私はplpgsqlでそれを行うことができます、私はちょうどそれなしで行うことができると思った – k102

+0

修正Erwin :)ありがとう –

関連する問題