在postgres中使用选定的值作为表名

时间:2012-02-03 06:58:35

标签: sql postgresql

我已经找到了答案,但没找到。

所以我有一张桌子types

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

包含类型名称,例如users - 这是相应表users的名称。这个设计可能有点难看,但它是为了让用户创建自己的类型。 (有更好的方法可以解决这个问题吗?)

现在我想执行像这样的查询:

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

获取所有类型名称的列表和每种类型的对象数。

可以这样做吗?

2 个答案:

答案 0 :(得分:5)

您不能直接在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();

答案 1 :(得分:4)

我没有足够的信息,但我确实怀疑你的设计出了什么问题。每种类型都不需要额外的表格。

尽管如此,在纯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来了解这里发生了什么。

一个特殊提示:cast to regclass是对SQLi的保护。您也可以使用更普遍适用的quote_ident(),但这不能正确处理模式限定的表名,而转换为regclass。它还只接受主叫用户可见的表名。