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

k10*_*102 2 sql postgresql

我已经找到答案,但没找到.

所以我有一张桌子 types

CREATE TABLE types
(
  type_id serial NOT NULL,
  type_name character varying,
  CONSTRAINT un_type_name UNIQUE (type_name)
)
Run Code Online (Sandbox Code Playgroud)

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

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

select type_name, (select count(*) from ???) from types
Run Code Online (Sandbox Code Playgroud)

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

可以这样做吗?

Pav*_*ule 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();
Run Code Online (Sandbox Code Playgroud)


Erw*_*ter 5

我没有足够的信息,但我确实怀疑您的设计有问题。您不应该为每种类型都需要一个额外的表。

尽管如此,您想要做的事情无法完成 - 在纯 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;
Run Code Online (Sandbox Code Playgroud)

称呼:

SELECT * FROM f_type_ct();
Run Code Online (Sandbox Code Playgroud)

您需要学习手册中有关 plpgsql 的大部分章节,以了解这里发生的事情。

一个特别提示:强制转换regclass为防止 SQLi。您也可以使用更普遍适用quote_ident()的方法,但这不能正确处理模式限定的表名,而强制转换regclass则可以。它还只接受调用用户可见的表名。